提交 17bb51d5 编写于 作者: L Linus Torvalds

Merge branch 'akpm-incoming-2'

* akpm-incoming-2: (139 commits)
  epoll: make epoll_wait() use the hrtimer range feature
  select: rename estimate_accuracy() to select_estimate_accuracy()
  Remove duplicate includes from many files
  ramoops: use the platform data structure instead of module params
  kernel/resource.c: handle reinsertion of an already-inserted resource
  kfifo: fix kfifo_alloc() to return a signed int value
  w1: don't allow arbitrary users to remove w1 devices
  alpha: remove dma64_addr_t usage
  mips: remove dma64_addr_t usage
  sparc: remove dma64_addr_t usage
  fuse: use release_pages()
  taskstats: use real microsecond granularity for CPU times
  taskstats: split fill_pid function
  taskstats: separate taskstats commands
  delayacct: align to 8 byte boundary on 64-bit systems
  delay-accounting: reimplement -c for getdelays.c to report information on a target command
  namespaces Kconfig: move namespace menu location after the cgroup
  namespaces Kconfig: remove the cgroup device whitelist experimental tag
  namespaces Kconfig: remove pointless cgroup dependency
  namespaces Kconfig: make namespace a submenu
  ...
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h> #include <signal.h>
#include <linux/genetlink.h> #include <linux/genetlink.h>
...@@ -266,11 +267,13 @@ int main(int argc, char *argv[]) ...@@ -266,11 +267,13 @@ int main(int argc, char *argv[])
int containerset = 0; int containerset = 0;
char containerpath[1024]; char containerpath[1024];
int cfd = 0; int cfd = 0;
int forking = 0;
sigset_t sigset;
struct msgtemplate msg; struct msgtemplate msg;
while (1) { while (!forking) {
c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:"); c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
if (c < 0) if (c < 0)
break; break;
...@@ -319,6 +322,28 @@ int main(int argc, char *argv[]) ...@@ -319,6 +322,28 @@ int main(int argc, char *argv[])
err(1, "Invalid pid\n"); err(1, "Invalid pid\n");
cmd_type = TASKSTATS_CMD_ATTR_PID; cmd_type = TASKSTATS_CMD_ATTR_PID;
break; break;
case 'c':
/* Block SIGCHLD for sigwait() later */
if (sigemptyset(&sigset) == -1)
err(1, "Failed to empty sigset");
if (sigaddset(&sigset, SIGCHLD))
err(1, "Failed to set sigchld in sigset");
sigprocmask(SIG_BLOCK, &sigset, NULL);
/* fork/exec a child */
tid = fork();
if (tid < 0)
err(1, "Fork failed\n");
if (tid == 0)
if (execvp(argv[optind - 1],
&argv[optind - 1]) < 0)
exit(-1);
/* Set the command type and avoid further processing */
cmd_type = TASKSTATS_CMD_ATTR_PID;
forking = 1;
break;
case 'v': case 'v':
printf("debug on\n"); printf("debug on\n");
dbg = 1; dbg = 1;
...@@ -370,6 +395,15 @@ int main(int argc, char *argv[]) ...@@ -370,6 +395,15 @@ int main(int argc, char *argv[])
goto err; goto err;
} }
/*
* If we forked a child, wait for it to exit. Cannot use waitpid()
* as all the delicious data would be reaped as part of the wait
*/
if (tid && forking) {
int sig_received;
sigwait(&sigset, &sig_received);
}
if (tid) { if (tid) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
cmd_type, &tid, sizeof(__u32)); cmd_type, &tid, sizeof(__u32));
......
...@@ -18,7 +18,8 @@ CONTENTS: ...@@ -18,7 +18,8 @@ CONTENTS:
1.2 Why are cgroups needed ? 1.2 Why are cgroups needed ?
1.3 How are cgroups implemented ? 1.3 How are cgroups implemented ?
1.4 What does notify_on_release do ? 1.4 What does notify_on_release do ?
1.5 How do I use cgroups ? 1.5 What does clone_children do ?
1.6 How do I use cgroups ?
2. Usage Examples and Syntax 2. Usage Examples and Syntax
2.1 Basic Usage 2.1 Basic Usage
2.2 Attaching processes 2.2 Attaching processes
...@@ -293,7 +294,16 @@ notify_on_release in the root cgroup at system boot is disabled ...@@ -293,7 +294,16 @@ notify_on_release in the root cgroup at system boot is disabled
value of their parents notify_on_release setting. The default value of value of their parents notify_on_release setting. The default value of
a cgroup hierarchy's release_agent path is empty. a cgroup hierarchy's release_agent path is empty.
1.5 How do I use cgroups ? 1.5 What does clone_children do ?
---------------------------------
If the clone_children flag is enabled (1) in a cgroup, then all
cgroups created beneath will call the post_clone callbacks for each
subsystem of the newly created cgroup. Usually when this callback is
implemented for a subsystem, it copies the values of the parent
subsystem, this is the case for the cpuset.
1.6 How do I use cgroups ?
-------------------------- --------------------------
To start a new job that is to be contained within a cgroup, using To start a new job that is to be contained within a cgroup, using
......
...@@ -526,6 +526,23 @@ Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> ...@@ -526,6 +526,23 @@ Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---------------------------- ----------------------------
What: namespace cgroup (ns_cgroup)
When: 2.6.38
Why: The ns_cgroup leads to some problems:
* cgroup creation is out-of-control
* cgroup name can conflict when pids are looping
* it is not possible to have a single process handling
a lot of namespaces without falling in a exponential creation time
* we may want to create a namespace without creating a cgroup
The ns_cgroup is replaced by a compatibility flag 'clone_children',
where a newly created cgroup will copy the parent cgroup values.
The userspace has to manually create a cgroup and add a task to
the 'tasks' file.
Who: Daniel Lezcano <daniel.lezcano@free.fr>
----------------------------
What: iwlwifi disable_hw_scan module parameters What: iwlwifi disable_hw_scan module parameters
When: 2.6.40 When: 2.6.40
Why: Hareware scan is the prefer method for iwlwifi devices for Why: Hareware scan is the prefer method for iwlwifi devices for
......
...@@ -136,6 +136,7 @@ Table 1-1: Process specific entries in /proc ...@@ -136,6 +136,7 @@ Table 1-1: Process specific entries in /proc
statm Process memory status information statm Process memory status information
status Process status in human readable form status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
pagemap Page table
stack Report full stack trace, enable via CONFIG_STACKTRACE stack Report full stack trace, enable via CONFIG_STACKTRACE
smaps a extension based on maps, showing the memory consumption of smaps a extension based on maps, showing the memory consumption of
each mapping each mapping
...@@ -370,6 +371,7 @@ Shared_Dirty: 0 kB ...@@ -370,6 +371,7 @@ Shared_Dirty: 0 kB
Private_Clean: 0 kB Private_Clean: 0 kB
Private_Dirty: 0 kB Private_Dirty: 0 kB
Referenced: 892 kB Referenced: 892 kB
Anonymous: 0 kB
Swap: 0 kB Swap: 0 kB
KernelPageSize: 4 kB KernelPageSize: 4 kB
MMUPageSize: 4 kB MMUPageSize: 4 kB
...@@ -378,9 +380,15 @@ The first of these lines shows the same information as is displayed for the ...@@ -378,9 +380,15 @@ The first of these lines shows the same information as is displayed for the
mapping in /proc/PID/maps. The remaining lines show the size of the mapping mapping in /proc/PID/maps. The remaining lines show the size of the mapping
(size), the amount of the mapping that is currently resident in RAM (RSS), the (size), the amount of the mapping that is currently resident in RAM (RSS), the
process' proportional share of this mapping (PSS), the number of clean and process' proportional share of this mapping (PSS), the number of clean and
dirty shared pages in the mapping, and the number of clean and dirty private dirty private pages in the mapping. Note that even a page which is part of a
pages in the mapping. The "Referenced" indicates the amount of memory MAP_SHARED mapping, but has only a single pte mapped, i.e. is currently used
currently marked as referenced or accessed. by only one process, is accounted as private and not as shared. "Referenced"
indicates the amount of memory currently marked as referenced or accessed.
"Anonymous" shows the amount of memory that does not belong to any file. Even
a mapping associated with a file may contain anonymous pages: when MAP_PRIVATE
and a page is modified, the file page is replaced by a private anonymous copy.
"Swap" shows how much would-be-anonymous memory is also used, but out on
swap.
This file is only present if the CONFIG_MMU kernel configuration option is This file is only present if the CONFIG_MMU kernel configuration option is
enabled. enabled.
...@@ -397,6 +405,9 @@ To clear the bits for the file mapped pages associated with the process ...@@ -397,6 +405,9 @@ To clear the bits for the file mapped pages associated with the process
> echo 3 > /proc/PID/clear_refs > echo 3 > /proc/PID/clear_refs
Any other value written to /proc/PID/clear_refs will have no effect. Any other value written to /proc/PID/clear_refs will have no effect.
The /proc/pid/pagemap gives the PFN, which can be used to find the pageflags
using /proc/kpageflags and number of times a page is mapped using
/proc/kpagecount. For detailed explanation, see Documentation/vm/pagemap.txt.
1.2 Kernel data 1.2 Kernel data
--------------- ---------------
......
...@@ -80,8 +80,10 @@ dirty_background_bytes ...@@ -80,8 +80,10 @@ dirty_background_bytes
Contains the amount of dirty memory at which the pdflush background writeback Contains the amount of dirty memory at which the pdflush background writeback
daemon will start writeback. daemon will start writeback.
If dirty_background_bytes is written, dirty_background_ratio becomes a function Note: dirty_background_bytes is the counterpart of dirty_background_ratio. Only
of its value (dirty_background_bytes / the amount of dirtyable system memory). one of them may be specified at a time. When one sysctl is written it is
immediately taken into account to evaluate the dirty memory limits and the
other appears as 0 when read.
============================================================== ==============================================================
...@@ -97,8 +99,10 @@ dirty_bytes ...@@ -97,8 +99,10 @@ dirty_bytes
Contains the amount of dirty memory at which a process generating disk writes Contains the amount of dirty memory at which a process generating disk writes
will itself start writeback. will itself start writeback.
If dirty_bytes is written, dirty_ratio becomes a function of its value Note: dirty_bytes is the counterpart of dirty_ratio. Only one of them may be
(dirty_bytes / the amount of dirtyable system memory). specified at a time. When one sysctl is written it is immediately taken into
account to evaluate the dirty memory limits and the other appears as 0 when
read.
Note: the minimum value allowed for dirty_bytes is two pages (in bytes); any Note: the minimum value allowed for dirty_bytes is two pages (in bytes); any
value lower than this limit will be ignored and the old configuration will be value lower than this limit will be ignored and the old configuration will be
......
...@@ -223,7 +223,7 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n) ...@@ -223,7 +223,7 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
*/ */
static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask) static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
{ {
dma64_addr_t dac_offset = alpha_mv.pci_dac_offset; dma_addr_t dac_offset = alpha_mv.pci_dac_offset;
int ok = 1; int ok = 1;
/* If this is not set, the machine doesn't support DAC at all. */ /* If this is not set, the machine doesn't support DAC at all. */
...@@ -756,7 +756,7 @@ static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg, ...@@ -756,7 +756,7 @@ static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
spin_lock_irqsave(&arena->lock, flags); spin_lock_irqsave(&arena->lock, flags);
for (end = sg + nents; sg < end; ++sg) { for (end = sg + nents; sg < end; ++sg) {
dma64_addr_t addr; dma_addr_t addr;
size_t size; size_t size;
long npages, ofs; long npages, ofs;
dma_addr_t tend; dma_addr_t tend;
......
...@@ -269,7 +269,8 @@ void ptrace_disable(struct task_struct *child) ...@@ -269,7 +269,8 @@ void ptrace_disable(struct task_struct *child)
user_disable_single_step(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,
unsigned long addr, unsigned long data)
{ {
unsigned long tmp; unsigned long tmp;
size_t copied; size_t copied;
...@@ -292,7 +293,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -292,7 +293,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
force_successful_syscall_return(); force_successful_syscall_return();
ret = get_reg(child, addr); ret = get_reg(child, addr);
DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret)); DBG(DBG_MEM, ("peek $%lu->%#lx\n", addr, ret));
break; break;
/* When I and D space are separate, this will have to be fixed. */ /* When I and D space are separate, this will have to be fixed. */
...@@ -302,7 +303,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -302,7 +303,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_POKEUSR: /* write the specified register */ case PTRACE_POKEUSR: /* write the specified register */
DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data)); DBG(DBG_MEM, ("poke $%lu<-%#lx\n", addr, data));
ret = put_reg(child, addr, data); ret = put_reg(child, addr, data);
break; break;
default: default:
......
...@@ -1075,13 +1075,15 @@ static int ptrace_sethbpregs(struct task_struct *tsk, long num, ...@@ -1075,13 +1075,15 @@ static int ptrace_sethbpregs(struct task_struct *tsk, long num,
} }
#endif #endif
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
ret = ptrace_read_user(child, addr, (unsigned long __user *)data); ret = ptrace_read_user(child, addr, datap);
break; break;
case PTRACE_POKEUSR: case PTRACE_POKEUSR:
...@@ -1089,34 +1091,34 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1089,34 +1091,34 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_GETREGS: case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data); ret = ptrace_getregs(child, datap);
break; break;
case PTRACE_SETREGS: case PTRACE_SETREGS:
ret = ptrace_setregs(child, (void __user *)data); ret = ptrace_setregs(child, datap);
break; break;
case PTRACE_GETFPREGS: case PTRACE_GETFPREGS:
ret = ptrace_getfpregs(child, (void __user *)data); ret = ptrace_getfpregs(child, datap);
break; break;
case PTRACE_SETFPREGS: case PTRACE_SETFPREGS:
ret = ptrace_setfpregs(child, (void __user *)data); ret = ptrace_setfpregs(child, datap);
break; break;
#ifdef CONFIG_IWMMXT #ifdef CONFIG_IWMMXT
case PTRACE_GETWMMXREGS: case PTRACE_GETWMMXREGS:
ret = ptrace_getwmmxregs(child, (void __user *)data); ret = ptrace_getwmmxregs(child, datap);
break; break;
case PTRACE_SETWMMXREGS: case PTRACE_SETWMMXREGS:
ret = ptrace_setwmmxregs(child, (void __user *)data); ret = ptrace_setwmmxregs(child, datap);
break; break;
#endif #endif
case PTRACE_GET_THREAD_AREA: case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value, ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) data); datap);
break; break;
case PTRACE_SET_SYSCALL: case PTRACE_SET_SYSCALL:
...@@ -1126,21 +1128,21 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1126,21 +1128,21 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef CONFIG_CRUNCH #ifdef CONFIG_CRUNCH
case PTRACE_GETCRUNCHREGS: case PTRACE_GETCRUNCHREGS:
ret = ptrace_getcrunchregs(child, (void __user *)data); ret = ptrace_getcrunchregs(child, datap);
break; break;
case PTRACE_SETCRUNCHREGS: case PTRACE_SETCRUNCHREGS:
ret = ptrace_setcrunchregs(child, (void __user *)data); ret = ptrace_setcrunchregs(child, datap);
break; break;
#endif #endif
#ifdef CONFIG_VFP #ifdef CONFIG_VFP
case PTRACE_GETVFPREGS: case PTRACE_GETVFPREGS:
ret = ptrace_getvfpregs(child, (void __user *)data); ret = ptrace_getvfpregs(child, datap);
break; break;
case PTRACE_SETVFPREGS: case PTRACE_SETVFPREGS:
ret = ptrace_setvfpregs(child, (void __user *)data); ret = ptrace_setvfpregs(child, datap);
break; break;
#endif #endif
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/cnt32_to_63.h> #include <linux/cnt32_to_63.h>
#include <asm/mach/time.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
#include <asm/localtimer.h> #include <asm/localtimer.h>
......
...@@ -89,7 +89,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -89,7 +89,7 @@ void __kunmap_atomic(void *kvaddr)
int idx, type; int idx, type;
if (kvaddr >= (void *)FIXADDR_START) { if (kvaddr >= (void *)FIXADDR_START) {
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
idx = type + KM_TYPE_NR * smp_processor_id(); idx = type + KM_TYPE_NR * smp_processor_id();
if (cache_is_vivt()) if (cache_is_vivt())
...@@ -101,6 +101,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -101,6 +101,7 @@ void __kunmap_atomic(void *kvaddr)
#else #else
(void) idx; /* to kill a warning */ (void) idx; /* to kill a warning */
#endif #endif
kmap_atomic_idx_pop();
} else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) { } else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) {
/* this address was obtained through kmap_high_get() */ /* this address was obtained through kmap_high_get() */
kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)])); kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/dmaengine.h>
/* dev types for memcpy */ /* dev types for memcpy */
#define STEDMA40_DEV_DST_MEMORY (-1) #define STEDMA40_DEV_DST_MEMORY (-1)
......
...@@ -146,9 +146,11 @@ static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs) ...@@ -146,9 +146,11 @@ static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs)
return ret; return ret;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
void __user *datap = (void __user *) data;
switch (request) { switch (request) {
/* Read the word at location addr in the child process */ /* Read the word at location addr in the child process */
...@@ -158,8 +160,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -158,8 +160,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
ret = ptrace_read_user(child, addr, ret = ptrace_read_user(child, addr, datap);
(unsigned long __user *)data);
break; break;
/* Write the word in data at location addr */ /* Write the word in data at location addr */
...@@ -173,11 +174,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -173,11 +174,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_GETREGS: case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data); ret = ptrace_getregs(child, datap);
break; break;
case PTRACE_SETREGS: case PTRACE_SETREGS:
ret = ptrace_setregs(child, (const void __user *)data); ret = ptrace_setregs(child, datap);
break; break;
default: default:
......
...@@ -38,12 +38,13 @@ ...@@ -38,12 +38,13 @@
* Get contents of register REGNO in task TASK. * Get contents of register REGNO in task TASK.
*/ */
static inline long static inline long
get_reg(struct task_struct *task, long regno, unsigned long __user *datap) get_reg(struct task_struct *task, unsigned long regno,
unsigned long __user *datap)
{ {
long tmp; long tmp;
struct pt_regs *regs = task_pt_regs(task); struct pt_regs *regs = task_pt_regs(task);
if (regno & 3 || regno > PT_LAST_PSEUDO || regno < 0) if (regno & 3 || regno > PT_LAST_PSEUDO)
return -EIO; return -EIO;
switch (regno) { switch (regno) {
...@@ -74,11 +75,11 @@ get_reg(struct task_struct *task, long regno, unsigned long __user *datap) ...@@ -74,11 +75,11 @@ get_reg(struct task_struct *task, long regno, unsigned long __user *datap)
* Write contents of register REGNO in task TASK. * Write contents of register REGNO in task TASK.
*/ */
static inline int static inline int
put_reg(struct task_struct *task, long regno, unsigned long data) put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
{ {
struct pt_regs *regs = task_pt_regs(task); struct pt_regs *regs = task_pt_regs(task);
if (regno & 3 || regno > PT_LAST_PSEUDO || regno < 0) if (regno & 3 || regno > PT_LAST_PSEUDO)
return -EIO; return -EIO;
switch (regno) { switch (regno) {
...@@ -240,7 +241,8 @@ void user_disable_single_step(struct task_struct *child) ...@@ -240,7 +241,8 @@ void user_disable_single_step(struct task_struct *child)
clear_tsk_thread_flag(child, TIF_SINGLESTEP); clear_tsk_thread_flag(child, TIF_SINGLESTEP);
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
...@@ -368,14 +370,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -368,14 +370,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return copy_regset_to_user(child, &user_bfin_native_view, return copy_regset_to_user(child, &user_bfin_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(void __user *)data); datap);
case PTRACE_SETREGS: case PTRACE_SETREGS:
pr_debug("ptrace: PTRACE_SETREGS\n"); pr_debug("ptrace: PTRACE_SETREGS\n");
return copy_regset_from_user(child, &user_bfin_native_view, return copy_regset_from_user(child, &user_bfin_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(const void __user *)data); datap);
case_default: case_default:
default: default:
......
...@@ -76,9 +76,11 @@ ptrace_disable(struct task_struct *child) ...@@ -76,9 +76,11 @@ ptrace_disable(struct task_struct *child)
* (in user space) where the result of the ptrace call is written (instead of * (in user space) where the result of the ptrace call is written (instead of
* being returned). * being returned).
*/ */
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
switch (request) { switch (request) {
...@@ -93,10 +95,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -93,10 +95,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp; unsigned long tmp;
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) if ((addr & 3) || regno > PT_MAX)
break; break;
tmp = get_reg(child, addr >> 2); tmp = get_reg(child, regno);
ret = put_user(tmp, datap); ret = put_user(tmp, datap);
break; break;
} }
...@@ -110,19 +112,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -110,19 +112,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Write the word at location address in the USER area. */ /* Write the word at location address in the USER area. */
case PTRACE_POKEUSR: case PTRACE_POKEUSR:
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) if ((addr & 3) || regno > PT_MAX)
break; break;
addr >>= 2; if (regno == PT_DCCR) {
if (addr == PT_DCCR) {
/* don't allow the tracing process to change stuff like /* don't allow the tracing process to change stuff like
* interrupt enable, kernel/user bit, dma enables etc. * interrupt enable, kernel/user bit, dma enables etc.
*/ */
data &= DCCR_MASK; data &= DCCR_MASK;
data |= get_reg(child, PT_DCCR) & ~DCCR_MASK; data |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
} }
if (put_reg(child, addr, data)) if (put_reg(child, regno, data))
break; break;
ret = 0; ret = 0;
break; break;
...@@ -141,7 +141,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -141,7 +141,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
} }
data += sizeof(long); datap++;
} }
break; break;
...@@ -165,7 +165,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -165,7 +165,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
put_reg(child, i, tmp); put_reg(child, i, tmp);
data += sizeof(long); datap++;
} }
break; break;
......
...@@ -126,9 +126,11 @@ ptrace_disable(struct task_struct *child) ...@@ -126,9 +126,11 @@ ptrace_disable(struct task_struct *child)
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
switch (request) { switch (request) {
...@@ -163,10 +165,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -163,10 +165,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp; unsigned long tmp;
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) if ((addr & 3) || regno > PT_MAX)
break; break;
tmp = get_reg(child, addr >> 2); tmp = get_reg(child, regno);
ret = put_user(tmp, datap); ret = put_user(tmp, datap);
break; break;
} }
...@@ -180,19 +182,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -180,19 +182,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Write the word at location address in the USER area. */ /* Write the word at location address in the USER area. */
case PTRACE_POKEUSR: case PTRACE_POKEUSR:
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2) if ((addr & 3) || regno > PT_MAX)
break; break;
addr >>= 2; if (regno == PT_CCS) {
if (addr == PT_CCS) {
/* don't allow the tracing process to change stuff like /* don't allow the tracing process to change stuff like
* interrupt enable, kernel/user bit, dma enables etc. * interrupt enable, kernel/user bit, dma enables etc.
*/ */
data &= CCS_MASK; data &= CCS_MASK;
data |= get_reg(child, PT_CCS) & ~CCS_MASK; data |= get_reg(child, PT_CCS) & ~CCS_MASK;
} }
if (put_reg(child, addr, data)) if (put_reg(child, regno, data))
break; break;
ret = 0; ret = 0;
break; break;
......
...@@ -254,23 +254,26 @@ void ptrace_disable(struct task_struct *child) ...@@ -254,23 +254,26 @@ void ptrace_disable(struct task_struct *child)
user_disable_single_step(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,
unsigned long addr, unsigned long data)
{ {
unsigned long tmp; unsigned long tmp;
int ret; int ret;
int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
/* 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: {
tmp = 0; tmp = 0;
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0) if (addr & 3)
break; break;
ret = 0; ret = 0;
switch (addr >> 2) { switch (regno) {
case 0 ... PT__END - 1: case 0 ... PT__END - 1:
tmp = get_reg(child, addr >> 2); tmp = get_reg(child, regno);
break; break;
case PT__END + 0: case PT__END + 0:
...@@ -299,23 +302,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -299,23 +302,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
if (ret == 0) if (ret == 0)
ret = put_user(tmp, (unsigned long *) data); ret = put_user(tmp, datap);
break; 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)
break; break;
ret = 0; switch (regno) {
switch (addr >> 2) {
case 0 ... PT__END - 1: case 0 ... PT__END - 1:
ret = put_reg(child, addr >> 2, data); ret = put_reg(child, regno, data);
break;
default:
ret = -EIO;
break; break;
} }
break; break;
...@@ -324,25 +322,25 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -324,25 +322,25 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return copy_regset_to_user(child, &user_frv_native_view, return copy_regset_to_user(child, &user_frv_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(child->thread.user->i), 0, sizeof(child->thread.user->i),
(void __user *)data); datap);
case PTRACE_SETREGS: /* Set all integer regs in the child. */ case PTRACE_SETREGS: /* Set all integer regs in the child. */
return copy_regset_from_user(child, &user_frv_native_view, return copy_regset_from_user(child, &user_frv_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(child->thread.user->i), 0, sizeof(child->thread.user->i),
(const void __user *)data); datap);
case PTRACE_GETFPREGS: /* Get the child FP/Media state. */ case PTRACE_GETFPREGS: /* Get the child FP/Media state. */
return copy_regset_to_user(child, &user_frv_native_view, return copy_regset_to_user(child, &user_frv_native_view,
REGSET_FPMEDIA, REGSET_FPMEDIA,
0, sizeof(child->thread.user->f), 0, sizeof(child->thread.user->f),
(void __user *)data); datap);
case PTRACE_SETFPREGS: /* Set the child FP/Media state. */ case PTRACE_SETFPREGS: /* Set the child FP/Media state. */
return copy_regset_from_user(child, &user_frv_native_view, return copy_regset_from_user(child, &user_frv_native_view,
REGSET_FPMEDIA, REGSET_FPMEDIA,
0, sizeof(child->thread.user->f), 0, sizeof(child->thread.user->f),
(const void __user *)data); datap);
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
......
...@@ -68,7 +68,7 @@ EXPORT_SYMBOL(__kmap_atomic); ...@@ -68,7 +68,7 @@ EXPORT_SYMBOL(__kmap_atomic);
void __kunmap_atomic(void *kvaddr) void __kunmap_atomic(void *kvaddr)
{ {
int type = kmap_atomic_idx_pop(); int type = kmap_atomic_idx();
switch (type) { switch (type) {
case 0: __kunmap_atomic_primary(4, 6); break; case 0: __kunmap_atomic_primary(4, 6); break;
case 1: __kunmap_atomic_primary(5, 7); break; case 1: __kunmap_atomic_primary(5, 7); break;
...@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr)
default: default:
BUG(); BUG();
} }
kmap_atomic_idx_pop();
pagefault_enable(); pagefault_enable();
} }
EXPORT_SYMBOL(__kunmap_atomic); EXPORT_SYMBOL(__kunmap_atomic);
...@@ -50,27 +50,29 @@ void ptrace_disable(struct task_struct *child) ...@@ -50,27 +50,29 @@ void ptrace_disable(struct task_struct *child)
user_disable_single_step(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,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
/* 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 = 0; unsigned long tmp = 0;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { if ((addr & 3) || addr >= sizeof(struct user)) {
ret = -EIO; ret = -EIO;
break ; break ;
} }
ret = 0; /* Default return condition */ ret = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
if (addr < H8300_REGS_NO) if (regno < H8300_REGS_NO)
tmp = h8300_get_reg(child, addr); tmp = h8300_get_reg(child, regno);
else { else {
switch(addr) { switch (regno) {
case 49: case 49:
tmp = child->mm->start_code; tmp = child->mm->start_code;
break ; break ;
...@@ -88,24 +90,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -88,24 +90,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
} }
if (!ret) if (!ret)
ret = put_user(tmp,(unsigned long *) data); ret = put_user(tmp, datap);
break ; break ;
} }
/* when I and D space are separate, this will have to be fixed. */ /* when I and D space are separate, this will have to be fixed. */
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 */
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) { if ((addr & 3) || addr >= sizeof(struct user)) {
ret = -EIO; ret = -EIO;
break ; break ;
} }
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_ER0) { if (regno == PT_ORIG_ER0) {
ret = -EIO; ret = -EIO;
break ; break ;
} }
if (addr < H8300_REGS_NO) { if (regno < H8300_REGS_NO) {
ret = h8300_put_reg(child, addr, data); ret = h8300_put_reg(child, regno, data);
break ; break ;
} }
ret = -EIO; ret = -EIO;
...@@ -116,11 +117,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -116,11 +117,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp; unsigned long tmp;
for (i = 0; i < H8300_REGS_NO; i++) { for (i = 0; i < H8300_REGS_NO; i++) {
tmp = h8300_get_reg(child, i); tmp = h8300_get_reg(child, i);
if (put_user(tmp, (unsigned long *) data)) { if (put_user(tmp, datap)) {
ret = -EFAULT; ret = -EFAULT;
break; break;
} }
data += sizeof(long); datap++;
} }
ret = 0; ret = 0;
break; break;
...@@ -130,12 +131,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -130,12 +131,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int i; int i;
unsigned long tmp; unsigned long tmp;
for (i = 0; i < H8300_REGS_NO; i++) { for (i = 0; i < H8300_REGS_NO; i++) {
if (get_user(tmp, (unsigned long *) data)) { if (get_user(tmp, datap)) {
ret = -EFAULT; ret = -EFAULT;
break; break;
} }
h8300_put_reg(child, i, tmp); h8300_put_reg(child, i, tmp);
data += sizeof(long); datap++;
} }
ret = 0; ret = 0;
break; break;
......
...@@ -56,10 +56,10 @@ typedef u64 cputime64_t; ...@@ -56,10 +56,10 @@ typedef u64 cputime64_t;
#define jiffies64_to_cputime64(__jif) ((__jif) * (NSEC_PER_SEC / HZ)) #define jiffies64_to_cputime64(__jif) ((__jif) * (NSEC_PER_SEC / HZ))
/* /*
* Convert cputime <-> milliseconds * Convert cputime <-> microseconds
*/ */
#define cputime_to_msecs(__ct) ((__ct) / NSEC_PER_MSEC) #define cputime_to_usecs(__ct) ((__ct) / NSEC_PER_USEC)
#define msecs_to_cputime(__msecs) ((__msecs) * NSEC_PER_MSEC) #define usecs_to_cputime(__usecs) ((__usecs) * NSEC_PER_USEC)
/* /*
* Convert cputime <-> seconds * Convert cputime <-> seconds
......
...@@ -1177,7 +1177,8 @@ ptrace_disable (struct task_struct *child) ...@@ -1177,7 +1177,8 @@ ptrace_disable (struct task_struct *child)
} }
long long
arch_ptrace (struct task_struct *child, long request, long addr, long data) arch_ptrace (struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
switch (request) { switch (request) {
case PTRACE_PEEKTEXT: case PTRACE_PEEKTEXT:
......
...@@ -622,9 +622,11 @@ void ptrace_disable(struct task_struct *child) ...@@ -622,9 +622,11 @@ void ptrace_disable(struct task_struct *child)
} }
long long
arch_ptrace(struct task_struct *child, long request, long addr, long data) arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
/* /*
...@@ -639,8 +641,7 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -639,8 +641,7 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data)
* 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:
ret = ptrace_read_user(child, addr, ret = ptrace_read_user(child, addr, datap);
(unsigned long __user *)data);
break; break;
/* /*
...@@ -661,11 +662,11 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -661,11 +662,11 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_GETREGS: case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data); ret = ptrace_getregs(child, datap);
break; break;
case PTRACE_SETREGS: case PTRACE_SETREGS:
ret = ptrace_setregs(child, (void __user *)data); ret = ptrace_setregs(child, datap);
break; break;
default: default:
......
...@@ -156,55 +156,57 @@ void user_disable_single_step(struct task_struct *child) ...@@ -156,55 +156,57 @@ void user_disable_single_step(struct task_struct *child)
singlestep_disable(child); singlestep_disable(child);
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
unsigned long tmp; unsigned long tmp;
int i, ret = 0; int i, ret = 0;
int regno = addr >> 2; /* temporary hack. */
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
/* 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:
if (addr & 3) if (addr & 3)
goto out_eio; goto out_eio;
addr >>= 2; /* temporary hack. */
if (addr >= 0 && addr < 19) { if (regno >= 0 && regno < 19) {
tmp = get_reg(child, addr); tmp = get_reg(child, regno);
} else if (addr >= 21 && addr < 49) { } else if (regno >= 21 && regno < 49) {
tmp = child->thread.fp[addr - 21]; tmp = child->thread.fp[regno - 21];
/* Convert internal fpu reg representation /* Convert internal fpu reg representation
* into long double format * into long double format
*/ */
if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
tmp = ((tmp & 0xffff0000) << 15) | tmp = ((tmp & 0xffff0000) << 15) |
((tmp & 0x0000ffff) << 16); ((tmp & 0x0000ffff) << 16);
} else } else
goto out_eio; goto out_eio;
ret = put_user(tmp, (unsigned long *)data); ret = put_user(tmp, datap);
break; 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 */
if (addr & 3) if (addr & 3)
goto out_eio; goto out_eio;
addr >>= 2; /* temporary hack. */
if (addr == PT_SR) { if (regno == PT_SR) {
data &= SR_MASK; data &= SR_MASK;
data |= get_reg(child, PT_SR) & ~SR_MASK; data |= get_reg(child, PT_SR) & ~SR_MASK;
} }
if (addr >= 0 && addr < 19) { if (regno >= 0 && regno < 19) {
if (put_reg(child, addr, data)) if (put_reg(child, regno, data))
goto out_eio; goto out_eio;
} else if (addr >= 21 && addr < 48) { } else if (regno >= 21 && regno < 48) {
/* Convert long double format /* Convert long double format
* into internal fpu reg representation * into internal fpu reg representation
*/ */
if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) { if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
data = (unsigned long)data << 15; data <<= 15;
data = (data & 0xffff0000) | data = (data & 0xffff0000) |
((data & 0x0000ffff) >> 1); ((data & 0x0000ffff) >> 1);
} }
child->thread.fp[addr - 21] = data; child->thread.fp[regno - 21] = data;
} else } else
goto out_eio; goto out_eio;
break; break;
...@@ -212,16 +214,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -212,16 +214,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_GETREGS: /* Get all gp regs from the child. */ case PTRACE_GETREGS: /* Get all gp regs from the child. */
for (i = 0; i < 19; i++) { for (i = 0; i < 19; i++) {
tmp = get_reg(child, i); tmp = get_reg(child, i);
ret = put_user(tmp, (unsigned long *)data); ret = put_user(tmp, datap);
if (ret) if (ret)
break; break;
data += sizeof(long); datap++;
} }
break; break;
case PTRACE_SETREGS: /* Set all gp regs in the child. */ case PTRACE_SETREGS: /* Set all gp regs in the child. */
for (i = 0; i < 19; i++) { for (i = 0; i < 19; i++) {
ret = get_user(tmp, (unsigned long *)data); ret = get_user(tmp, datap);
if (ret) if (ret)
break; break;
if (i == PT_SR) { if (i == PT_SR) {
...@@ -229,25 +231,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -229,25 +231,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp |= get_reg(child, PT_SR) & ~SR_MASK; tmp |= get_reg(child, PT_SR) & ~SR_MASK;
} }
put_reg(child, i, tmp); put_reg(child, i, tmp);
data += sizeof(long); datap++;
} }
break; break;
case PTRACE_GETFPREGS: /* Get the child FPU state. */ case PTRACE_GETFPREGS: /* Get the child FPU state. */
if (copy_to_user((void *)data, &child->thread.fp, if (copy_to_user(datap, &child->thread.fp,
sizeof(struct user_m68kfp_struct))) sizeof(struct user_m68kfp_struct)))
ret = -EFAULT; ret = -EFAULT;
break; break;
case PTRACE_SETFPREGS: /* Set the child FPU state. */ case PTRACE_SETFPREGS: /* Set the child FPU state. */
if (copy_from_user(&child->thread.fp, (void *)data, if (copy_from_user(&child->thread.fp, datap,
sizeof(struct user_m68kfp_struct))) sizeof(struct user_m68kfp_struct)))
ret = -EFAULT; ret = -EFAULT;
break; break;
case PTRACE_GET_THREAD_AREA: case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value, ret = put_user(task_thread_info(child)->tp_value, datap);
(unsigned long __user *)data);
break; break;
default: default:
......
...@@ -112,9 +112,12 @@ void ptrace_disable(struct task_struct *child) ...@@ -112,9 +112,12 @@ void ptrace_disable(struct task_struct *child)
user_disable_single_step(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,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
...@@ -122,53 +125,48 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -122,53 +125,48 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp; unsigned long tmp;
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || if ((addr & 3) || addr > sizeof(struct user) - 3)
addr > sizeof(struct user) - 3)
break; break;
tmp = 0; /* Default return condition */ tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
ret = -EIO; ret = -EIO;
if (addr < 19) { if (regno < 19) {
tmp = get_reg(child, addr); tmp = get_reg(child, regno);
if (addr == PT_SR) if (regno == PT_SR)
tmp >>= 16; tmp >>= 16;
} else if (addr >= 21 && addr < 49) { } else if (regno >= 21 && regno < 49) {
tmp = child->thread.fp[addr - 21]; tmp = child->thread.fp[regno - 21];
} else if (addr == 49) { } else if (regno == 49) {
tmp = child->mm->start_code; tmp = child->mm->start_code;
} else if (addr == 50) { } else if (regno == 50) {
tmp = child->mm->start_data; tmp = child->mm->start_data;
} else if (addr == 51) { } else if (regno == 51) {
tmp = child->mm->end_code; tmp = child->mm->end_code;
} else } else
break; break;
ret = put_user(tmp,(unsigned long *) data); ret = put_user(tmp, datap);
break; 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 > sizeof(struct user) - 3)
addr > sizeof(struct user) - 3)
break; break;
addr = addr >> 2; /* temporary hack. */ if (regno == PT_SR) {
if (addr == PT_SR) {
data &= SR_MASK; data &= SR_MASK;
data <<= 16; data <<= 16;
data |= get_reg(child, PT_SR) & ~(SR_MASK << 16); data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
} }
if (addr < 19) { if (regno < 19) {
if (put_reg(child, addr, data)) if (put_reg(child, regno, data))
break; break;
ret = 0; ret = 0;
break; break;
} }
if (addr >= 21 && addr < 48) if (regno >= 21 && regno < 48)
{ {
child->thread.fp[addr - 21] = data; child->thread.fp[regno - 21] = data;
ret = 0; ret = 0;
} }
break; break;
...@@ -180,11 +178,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -180,11 +178,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = get_reg(child, i); tmp = get_reg(child, i);
if (i == PT_SR) if (i == PT_SR)
tmp >>= 16; tmp >>= 16;
if (put_user(tmp, (unsigned long *) data)) { if (put_user(tmp, datap)) {
ret = -EFAULT; ret = -EFAULT;
break; break;
} }
data += sizeof(long); datap++;
} }
ret = 0; ret = 0;
break; break;
...@@ -194,7 +192,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -194,7 +192,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int i; int i;
unsigned long tmp; unsigned long tmp;
for (i = 0; i < 19; i++) { for (i = 0; i < 19; i++) {
if (get_user(tmp, (unsigned long *) data)) { if (get_user(tmp, datap)) {
ret = -EFAULT; ret = -EFAULT;
break; break;
} }
...@@ -204,7 +202,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -204,7 +202,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16); tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
} }
put_reg(child, i, tmp); put_reg(child, i, tmp);
data += sizeof(long); datap++;
} }
ret = 0; ret = 0;
break; break;
...@@ -213,7 +211,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -213,7 +211,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_GETFPREGS #ifdef PTRACE_GETFPREGS
case PTRACE_GETFPREGS: { /* Get the child FPU state. */ case PTRACE_GETFPREGS: { /* Get the child FPU state. */
ret = 0; ret = 0;
if (copy_to_user((void *)data, &child->thread.fp, if (copy_to_user(datap, &child->thread.fp,
sizeof(struct user_m68kfp_struct))) sizeof(struct user_m68kfp_struct)))
ret = -EFAULT; ret = -EFAULT;
break; break;
...@@ -223,7 +221,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -223,7 +221,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_SETFPREGS #ifdef PTRACE_SETFPREGS
case PTRACE_SETFPREGS: { /* Set the child FPU state. */ case PTRACE_SETFPREGS: { /* Set the child FPU state. */
ret = 0; ret = 0;
if (copy_from_user(&child->thread.fp, (void *)data, if (copy_from_user(&child->thread.fp, datap,
sizeof(struct user_m68kfp_struct))) sizeof(struct user_m68kfp_struct)))
ret = -EFAULT; ret = -EFAULT;
break; break;
...@@ -231,8 +229,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -231,8 +229,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif #endif
case PTRACE_GET_THREAD_AREA: case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value, ret = put_user(task_thread_info(child)->tp_value, datap);
(unsigned long __user *)data);
break; break;
default: default:
......
...@@ -73,7 +73,8 @@ static microblaze_reg_t *reg_save_addr(unsigned reg_offs, ...@@ -73,7 +73,8 @@ static microblaze_reg_t *reg_save_addr(unsigned reg_offs,
return (microblaze_reg_t *)((char *)regs + reg_offs); return (microblaze_reg_t *)((char *)regs + reg_offs);
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int rval; int rval;
unsigned long val = 0; unsigned long val = 0;
...@@ -99,7 +100,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -99,7 +100,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} else { } else {
rval = -EIO; rval = -EIO;
} }
} else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) { } else if (addr < PT_SIZE && (addr & 0x3) == 0) {
microblaze_reg_t *reg_addr = reg_save_addr(addr, child); microblaze_reg_t *reg_addr = reg_save_addr(addr, child);
if (request == PTRACE_PEEKUSR) if (request == PTRACE_PEEKUSR)
val = *reg_addr; val = *reg_addr;
......
...@@ -839,7 +839,7 @@ struct bridge_controller { ...@@ -839,7 +839,7 @@ struct bridge_controller {
nasid_t nasid; nasid_t nasid;
unsigned int widget_id; unsigned int widget_id;
unsigned int irq_cpu; unsigned int irq_cpu;
dma64_addr_t baddr; u64 baddr;
unsigned int pci_int[8]; unsigned int pci_int[8];
}; };
......
...@@ -255,9 +255,13 @@ int ptrace_set_watch_regs(struct task_struct *child, ...@@ -255,9 +255,13 @@ int ptrace_set_watch_regs(struct task_struct *child,
return 0; return 0;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
void __user *addrp = (void __user *) addr;
void __user *datavp = (void __user *) data;
unsigned long __user *datalp = (void __user *) data;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
...@@ -386,7 +390,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -386,7 +390,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
ret = put_user(tmp, (unsigned long __user *) data); ret = put_user(tmp, datalp);
break; break;
} }
...@@ -478,34 +482,31 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -478,34 +482,31 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
case PTRACE_GETREGS: case PTRACE_GETREGS:
ret = ptrace_getregs(child, (__s64 __user *) data); ret = ptrace_getregs(child, datavp);
break; break;
case PTRACE_SETREGS: case PTRACE_SETREGS:
ret = ptrace_setregs(child, (__s64 __user *) data); ret = ptrace_setregs(child, datavp);
break; break;
case PTRACE_GETFPREGS: case PTRACE_GETFPREGS:
ret = ptrace_getfpregs(child, (__u32 __user *) data); ret = ptrace_getfpregs(child, datavp);
break; break;
case PTRACE_SETFPREGS: case PTRACE_SETFPREGS:
ret = ptrace_setfpregs(child, (__u32 __user *) data); ret = ptrace_setfpregs(child, datavp);
break; break;
case PTRACE_GET_THREAD_AREA: case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value, ret = put_user(task_thread_info(child)->tp_value, datalp);
(unsigned long __user *) data);
break; break;
case PTRACE_GET_WATCH_REGS: case PTRACE_GET_WATCH_REGS:
ret = ptrace_get_watch_regs(child, ret = ptrace_get_watch_regs(child, addrp);
(struct pt_watch_regs __user *) addr);
break; break;
case PTRACE_SET_WATCH_REGS: case PTRACE_SET_WATCH_REGS:
ret = ptrace_set_watch_regs(child, ret = ptrace_set_watch_regs(child, addrp);
(struct pt_watch_regs __user *) addr);
break; break;
default: default:
......
...@@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr)
return; return;
} }
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
#ifdef CONFIG_DEBUG_HIGHMEM #ifdef CONFIG_DEBUG_HIGHMEM
{ {
int idx = type + KM_TYPE_NR * smp_processor_id(); int idx = type + KM_TYPE_NR * smp_processor_id();
...@@ -89,6 +89,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -89,6 +89,7 @@ void __kunmap_atomic(void *kvaddr)
local_flush_tlb_one(vaddr); local_flush_tlb_one(vaddr);
} }
#endif #endif
kmap_atomic_idx_pop();
pagefault_enable(); pagefault_enable();
} }
EXPORT_SYMBOL(__kunmap_atomic); EXPORT_SYMBOL(__kunmap_atomic);
......
...@@ -101,7 +101,7 @@ static inline void __kunmap_atomic(unsigned long vaddr) ...@@ -101,7 +101,7 @@ static inline void __kunmap_atomic(unsigned long vaddr)
return; return;
} }
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
#if HIGHMEM_DEBUG #if HIGHMEM_DEBUG
{ {
...@@ -119,6 +119,8 @@ static inline void __kunmap_atomic(unsigned long vaddr) ...@@ -119,6 +119,8 @@ static inline void __kunmap_atomic(unsigned long vaddr)
__flush_tlb_one(vaddr); __flush_tlb_one(vaddr);
} }
#endif #endif
kmap_atomic_idx_pop();
pagefault_enable(); pagefault_enable();
} }
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -295,31 +295,31 @@ void ptrace_disable(struct task_struct *child) ...@@ -295,31 +295,31 @@ void ptrace_disable(struct task_struct *child)
/* /*
* handle the arch-specific side of process tracing * handle the arch-specific side of process tracing
*/ */
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
unsigned long tmp; unsigned long tmp;
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
/* 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:
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || if ((addr & 3) || addr > sizeof(struct user) - 3)
addr > sizeof(struct user) - 3)
break; break;
tmp = 0; /* Default return condition */ tmp = 0; /* Default return condition */
if (addr < NR_PTREGS << 2) if (addr < NR_PTREGS << 2)
tmp = get_stack_long(child, tmp = get_stack_long(child,
ptrace_regid_to_frame[addr]); ptrace_regid_to_frame[addr]);
ret = put_user(tmp, (unsigned long *) data); ret = put_user(tmp, datap);
break; break;
/* write the word at location addr in the USER area */ /* write the word at location addr in the USER area */
case PTRACE_POKEUSR: case PTRACE_POKEUSR:
ret = -EIO; ret = -EIO;
if ((addr & 3) || addr < 0 || if ((addr & 3) || addr > sizeof(struct user) - 3)
addr > sizeof(struct user) - 3)
break; break;
ret = 0; ret = 0;
...@@ -332,25 +332,25 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -332,25 +332,25 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return copy_regset_to_user(child, &user_mn10300_native_view, return copy_regset_to_user(child, &user_mn10300_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, NR_PTREGS * sizeof(long), 0, NR_PTREGS * sizeof(long),
(void __user *)data); datap);
case PTRACE_SETREGS: /* Set all integer regs in the child. */ case PTRACE_SETREGS: /* Set all integer regs in the child. */
return copy_regset_from_user(child, &user_mn10300_native_view, return copy_regset_from_user(child, &user_mn10300_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, NR_PTREGS * sizeof(long), 0, NR_PTREGS * sizeof(long),
(const void __user *)data); datap);
case PTRACE_GETFPREGS: /* Get the child FPU state. */ case PTRACE_GETFPREGS: /* Get the child FPU state. */
return copy_regset_to_user(child, &user_mn10300_native_view, return copy_regset_to_user(child, &user_mn10300_native_view,
REGSET_FPU, REGSET_FPU,
0, sizeof(struct fpu_state_struct), 0, sizeof(struct fpu_state_struct),
(void __user *)data); datap);
case PTRACE_SETFPREGS: /* Set the child FPU state. */ case PTRACE_SETFPREGS: /* Set the child FPU state. */
return copy_regset_from_user(child, &user_mn10300_native_view, return copy_regset_from_user(child, &user_mn10300_native_view,
REGSET_FPU, REGSET_FPU,
0, sizeof(struct fpu_state_struct), 0, sizeof(struct fpu_state_struct),
(const void __user *)data); datap);
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
......
...@@ -110,7 +110,8 @@ void user_enable_block_step(struct task_struct *task) ...@@ -110,7 +110,8 @@ void user_enable_block_step(struct task_struct *task)
pa_psw(task)->l = 0; pa_psw(task)->l = 0;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
unsigned long tmp; unsigned long tmp;
long ret = -EIO; long ret = -EIO;
...@@ -120,11 +121,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -120,11 +121,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
/* Read the word at location addr in the USER area. For ptraced /* Read the word at location addr in the USER area. For ptraced
processes, the kernel saves all regs on a syscall. */ processes, the kernel saves all regs on a syscall. */
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
if ((addr & (sizeof(long)-1)) || if ((addr & (sizeof(unsigned long)-1)) ||
(unsigned long) addr >= sizeof(struct pt_regs)) addr >= sizeof(struct pt_regs))
break; break;
tmp = *(unsigned long *) ((char *) task_regs(child) + addr); tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
ret = put_user(tmp, (unsigned long *) data); ret = put_user(tmp, (unsigned long __user *) data);
break; break;
/* Write the word at location addr in the USER area. This will need /* Write the word at location addr in the USER area. This will need
...@@ -151,8 +152,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -151,8 +152,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
} }
if ((addr & (sizeof(long)-1)) || if ((addr & (sizeof(unsigned long)-1)) ||
(unsigned long) addr >= sizeof(struct pt_regs)) addr >= sizeof(struct pt_regs))
break; break;
if ((addr >= PT_GR1 && addr <= PT_GR31) || if ((addr >= PT_GR1 && addr <= PT_GR31) ||
addr == PT_IAOQ0 || addr == PT_IAOQ1 || addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
......
...@@ -124,23 +124,23 @@ static inline u64 cputime64_to_jiffies64(const cputime_t ct) ...@@ -124,23 +124,23 @@ static inline u64 cputime64_to_jiffies64(const cputime_t ct)
} }
/* /*
* Convert cputime <-> milliseconds * Convert cputime <-> microseconds
*/ */
extern u64 __cputime_msec_factor; extern u64 __cputime_msec_factor;
static inline unsigned long cputime_to_msecs(const cputime_t ct) static inline unsigned long cputime_to_usecs(const cputime_t ct)
{ {
return mulhdu(ct, __cputime_msec_factor); return mulhdu(ct, __cputime_msec_factor) * USEC_PER_MSEC;
} }
static inline cputime_t msecs_to_cputime(const unsigned long ms) static inline cputime_t usecs_to_cputime(const unsigned long us)
{ {
cputime_t ct; cputime_t ct;
unsigned long sec; unsigned long sec;
/* have to be a little careful about overflow */ /* have to be a little careful about overflow */
ct = ms % 1000; ct = us % 1000000;
sec = ms / 1000; sec = us / 1000000;
if (ct) { if (ct) {
ct *= tb_ticks_per_sec; ct *= tb_ticks_per_sec;
do_div(ct, 1000); do_div(ct, 1000);
......
...@@ -1406,37 +1406,42 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data) ...@@ -1406,37 +1406,42 @@ static long ppc_del_hwdebug(struct task_struct *child, long addr, long data)
* Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls,
* we mark them as obsolete now, they will be removed in a future version * we mark them as obsolete now, they will be removed in a future version
*/ */
static long arch_ptrace_old(struct task_struct *child, long request, long addr, static long arch_ptrace_old(struct task_struct *child, long request,
long data) unsigned long addr, unsigned long data)
{ {
void __user *datavp = (void __user *) data;
switch (request) { switch (request) {
case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
return copy_regset_to_user(child, &user_ppc_native_view, return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_GPR, 0, 32 * sizeof(long), REGSET_GPR, 0, 32 * sizeof(long),
(void __user *) data); datavp);
case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
return copy_regset_from_user(child, &user_ppc_native_view, return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_GPR, 0, 32 * sizeof(long), REGSET_GPR, 0, 32 * sizeof(long),
(const void __user *) data); datavp);
case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
return copy_regset_to_user(child, &user_ppc_native_view, return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_FPR, 0, 32 * sizeof(double), REGSET_FPR, 0, 32 * sizeof(double),
(void __user *) data); datavp);
case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */ case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */
return copy_regset_from_user(child, &user_ppc_native_view, return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_FPR, 0, 32 * sizeof(double), REGSET_FPR, 0, 32 * sizeof(double),
(const void __user *) data); datavp);
} }
return -EPERM; return -EPERM;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret = -EPERM; int ret = -EPERM;
void __user *datavp = (void __user *) data;
unsigned long __user *datalp = datavp;
switch (request) { switch (request) {
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
...@@ -1446,11 +1451,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1446,11 +1451,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
index = (unsigned long) addr >> 2; index = addr >> 2;
if ((addr & 3) || (index > PT_FPSCR) if ((addr & 3) || (index > PT_FPSCR)
|| (child->thread.regs == NULL)) || (child->thread.regs == NULL))
#else #else
index = (unsigned long) addr >> 3; index = addr >> 3;
if ((addr & 7) || (index > PT_FPSCR)) if ((addr & 7) || (index > PT_FPSCR))
#endif #endif
break; break;
...@@ -1463,7 +1468,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1463,7 +1468,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = ((unsigned long *)child->thread.fpr) tmp = ((unsigned long *)child->thread.fpr)
[TS_FPRWIDTH * (index - PT_FPR0)]; [TS_FPRWIDTH * (index - PT_FPR0)];
} }
ret = put_user(tmp,(unsigned long __user *) data); ret = put_user(tmp, datalp);
break; break;
} }
...@@ -1474,11 +1479,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1474,11 +1479,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
#ifdef CONFIG_PPC32 #ifdef CONFIG_PPC32
index = (unsigned long) addr >> 2; index = addr >> 2;
if ((addr & 3) || (index > PT_FPSCR) if ((addr & 3) || (index > PT_FPSCR)
|| (child->thread.regs == NULL)) || (child->thread.regs == NULL))
#else #else
index = (unsigned long) addr >> 3; index = addr >> 3;
if ((addr & 7) || (index > PT_FPSCR)) if ((addr & 7) || (index > PT_FPSCR))
#endif #endif
break; break;
...@@ -1525,11 +1530,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1525,11 +1530,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
dbginfo.features = 0; dbginfo.features = 0;
#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ #endif /* CONFIG_PPC_ADV_DEBUG_REGS */
if (!access_ok(VERIFY_WRITE, data, if (!access_ok(VERIFY_WRITE, datavp,
sizeof(struct ppc_debug_info))) sizeof(struct ppc_debug_info)))
return -EFAULT; return -EFAULT;
ret = __copy_to_user((struct ppc_debug_info __user *)data, ret = __copy_to_user(datavp, &dbginfo,
&dbginfo, sizeof(struct ppc_debug_info)) ? sizeof(struct ppc_debug_info)) ?
-EFAULT : 0; -EFAULT : 0;
break; break;
} }
...@@ -1537,11 +1542,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1537,11 +1542,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PPC_PTRACE_SETHWDEBUG: { case PPC_PTRACE_SETHWDEBUG: {
struct ppc_hw_breakpoint bp_info; struct ppc_hw_breakpoint bp_info;
if (!access_ok(VERIFY_READ, data, if (!access_ok(VERIFY_READ, datavp,
sizeof(struct ppc_hw_breakpoint))) sizeof(struct ppc_hw_breakpoint)))
return -EFAULT; return -EFAULT;
ret = __copy_from_user(&bp_info, ret = __copy_from_user(&bp_info, datavp,
(struct ppc_hw_breakpoint __user *)data,
sizeof(struct ppc_hw_breakpoint)) ? sizeof(struct ppc_hw_breakpoint)) ?
-EFAULT : 0; -EFAULT : 0;
if (!ret) if (!ret)
...@@ -1560,11 +1564,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1560,11 +1564,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (addr > 0) if (addr > 0)
break; break;
#ifdef CONFIG_PPC_ADV_DEBUG_REGS #ifdef CONFIG_PPC_ADV_DEBUG_REGS
ret = put_user(child->thread.dac1, ret = put_user(child->thread.dac1, datalp);
(unsigned long __user *)data);
#else #else
ret = put_user(child->thread.dabr, ret = put_user(child->thread.dabr, datalp);
(unsigned long __user *)data);
#endif #endif
break; break;
} }
...@@ -1580,7 +1582,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1580,7 +1582,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return copy_regset_to_user(child, &user_ppc_native_view, return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_GPR, REGSET_GPR,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(void __user *) data); datavp);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
case PTRACE_SETREGS64: case PTRACE_SETREGS64:
...@@ -1589,19 +1591,19 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1589,19 +1591,19 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return copy_regset_from_user(child, &user_ppc_native_view, return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_GPR, REGSET_GPR,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(const void __user *) data); datavp);
case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */
return copy_regset_to_user(child, &user_ppc_native_view, return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_FPR, REGSET_FPR,
0, sizeof(elf_fpregset_t), 0, sizeof(elf_fpregset_t),
(void __user *) data); datavp);
case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */ case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */
return copy_regset_from_user(child, &user_ppc_native_view, return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_FPR, REGSET_FPR,
0, sizeof(elf_fpregset_t), 0, sizeof(elf_fpregset_t),
(const void __user *) data); datavp);
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
case PTRACE_GETVRREGS: case PTRACE_GETVRREGS:
...@@ -1609,40 +1611,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1609,40 +1611,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
REGSET_VMX, REGSET_VMX,
0, (33 * sizeof(vector128) + 0, (33 * sizeof(vector128) +
sizeof(u32)), sizeof(u32)),
(void __user *) data); datavp);
case PTRACE_SETVRREGS: case PTRACE_SETVRREGS:
return copy_regset_from_user(child, &user_ppc_native_view, return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_VMX, REGSET_VMX,
0, (33 * sizeof(vector128) + 0, (33 * sizeof(vector128) +
sizeof(u32)), sizeof(u32)),
(const void __user *) data); datavp);
#endif #endif
#ifdef CONFIG_VSX #ifdef CONFIG_VSX
case PTRACE_GETVSRREGS: case PTRACE_GETVSRREGS:
return copy_regset_to_user(child, &user_ppc_native_view, return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_VSX, REGSET_VSX,
0, 32 * sizeof(double), 0, 32 * sizeof(double),
(void __user *) data); datavp);
case PTRACE_SETVSRREGS: case PTRACE_SETVSRREGS:
return copy_regset_from_user(child, &user_ppc_native_view, return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_VSX, REGSET_VSX,
0, 32 * sizeof(double), 0, 32 * sizeof(double),
(const void __user *) data); datavp);
#endif #endif
#ifdef CONFIG_SPE #ifdef CONFIG_SPE
case PTRACE_GETEVRREGS: case PTRACE_GETEVRREGS:
/* Get the child spe register state. */ /* Get the child spe register state. */
return copy_regset_to_user(child, &user_ppc_native_view, return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_SPE, 0, 35 * sizeof(u32), REGSET_SPE, 0, 35 * sizeof(u32),
(void __user *) data); datavp);
case PTRACE_SETEVRREGS: case PTRACE_SETEVRREGS:
/* Set the child spe register state. */ /* Set the child spe register state. */
return copy_regset_from_user(child, &user_ppc_native_view, return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_SPE, 0, 35 * sizeof(u32), REGSET_SPE, 0, 35 * sizeof(u32),
(const void __user *) data); datavp);
#endif #endif
/* Old reverse args ptrace callss */ /* Old reverse args ptrace callss */
......
...@@ -62,7 +62,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -62,7 +62,7 @@ void __kunmap_atomic(void *kvaddr)
return; return;
} }
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
#ifdef CONFIG_DEBUG_HIGHMEM #ifdef CONFIG_DEBUG_HIGHMEM
{ {
...@@ -79,6 +79,8 @@ void __kunmap_atomic(void *kvaddr) ...@@ -79,6 +79,8 @@ void __kunmap_atomic(void *kvaddr)
local_flush_tlb_page(NULL, vaddr); local_flush_tlb_page(NULL, vaddr);
} }
#endif #endif
kmap_atomic_idx_pop();
pagefault_enable(); pagefault_enable();
} }
EXPORT_SYMBOL(__kunmap_atomic); EXPORT_SYMBOL(__kunmap_atomic);
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#define RIO_ATMU_REGS_OFFSET 0x10c00 #define RIO_ATMU_REGS_OFFSET 0x10c00
#define RIO_P_MSG_REGS_OFFSET 0x11000 #define RIO_P_MSG_REGS_OFFSET 0x11000
#define RIO_S_MSG_REGS_OFFSET 0x13000 #define RIO_S_MSG_REGS_OFFSET 0x13000
#define RIO_GCCSR 0x13c
#define RIO_ESCSR 0x158 #define RIO_ESCSR 0x158
#define RIO_CCSR 0x15c #define RIO_CCSR 0x15c
#define RIO_LTLEDCSR 0x0608 #define RIO_LTLEDCSR 0x0608
...@@ -87,6 +88,9 @@ ...@@ -87,6 +88,9 @@
#define RIO_IPWSR_PWD 0x00000008 #define RIO_IPWSR_PWD 0x00000008
#define RIO_IPWSR_PWB 0x00000004 #define RIO_IPWSR_PWB 0x00000004
#define RIO_EPWISR_PINT 0x80000000
#define RIO_EPWISR_PW 0x00000001
#define RIO_MSG_DESC_SIZE 32 #define RIO_MSG_DESC_SIZE 32
#define RIO_MSG_BUFFER_SIZE 4096 #define RIO_MSG_BUFFER_SIZE 4096
#define RIO_MIN_TX_RING_SIZE 2 #define RIO_MIN_TX_RING_SIZE 2
...@@ -1082,18 +1086,12 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) ...@@ -1082,18 +1086,12 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
struct rio_priv *priv = port->priv; struct rio_priv *priv = port->priv;
u32 epwisr, tmp; u32 epwisr, tmp;
ipwmr = in_be32(&priv->msg_regs->pwmr);
ipwsr = in_be32(&priv->msg_regs->pwsr);
epwisr = in_be32(priv->regs_win + RIO_EPWISR); epwisr = in_be32(priv->regs_win + RIO_EPWISR);
if (epwisr & 0x80000000) { if (!(epwisr & RIO_EPWISR_PW))
tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); goto pw_done;
pr_info("RIO_LTLEDCSR = 0x%x\n", tmp);
out_be32(priv->regs_win + RIO_LTLEDCSR, 0);
}
if (!(epwisr & 0x00000001)) ipwmr = in_be32(&priv->msg_regs->pwmr);
return IRQ_HANDLED; ipwsr = in_be32(&priv->msg_regs->pwsr);
#ifdef DEBUG_PW #ifdef DEBUG_PW
pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr);
...@@ -1109,20 +1107,6 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) ...@@ -1109,20 +1107,6 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
pr_debug(" PWB"); pr_debug(" PWB");
pr_debug(" )\n"); pr_debug(" )\n");
#endif #endif
out_be32(&priv->msg_regs->pwsr,
ipwsr & (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD));
if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
priv->port_write_msg.err_count++;
pr_info("RIO: Port-Write Transaction Err (%d)\n",
priv->port_write_msg.err_count);
}
if (ipwsr & RIO_IPWSR_PWD) {
priv->port_write_msg.discard_count++;
pr_info("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
priv->port_write_msg.discard_count);
}
/* Schedule deferred processing if PW was received */ /* Schedule deferred processing if PW was received */
if (ipwsr & RIO_IPWSR_QFI) { if (ipwsr & RIO_IPWSR_QFI) {
/* Save PW message (if there is room in FIFO), /* Save PW message (if there is room in FIFO),
...@@ -1134,16 +1118,43 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) ...@@ -1134,16 +1118,43 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
RIO_PW_MSG_SIZE); RIO_PW_MSG_SIZE);
} else { } else {
priv->port_write_msg.discard_count++; priv->port_write_msg.discard_count++;
pr_info("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n",
priv->port_write_msg.discard_count); priv->port_write_msg.discard_count);
} }
/* Clear interrupt and issue Clear Queue command. This allows
* another port-write to be received.
*/
out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_QFI);
out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ);
schedule_work(&priv->pw_work); schedule_work(&priv->pw_work);
} }
/* Issue Clear Queue command. This allows another if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
* port-write to be received. priv->port_write_msg.err_count++;
*/ pr_debug("RIO: Port-Write Transaction Err (%d)\n",
out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); priv->port_write_msg.err_count);
/* Clear Transaction Error: port-write controller should be
* disabled when clearing this error
*/
out_be32(&priv->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE);
out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_TE);
out_be32(&priv->msg_regs->pwmr, ipwmr);
}
if (ipwsr & RIO_IPWSR_PWD) {
priv->port_write_msg.discard_count++;
pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n",
priv->port_write_msg.discard_count);
out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_PWD);
}
pw_done:
if (epwisr & RIO_EPWISR_PINT) {
tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
out_be32(priv->regs_win + RIO_LTLEDCSR, 0);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1461,6 +1472,7 @@ int fsl_rio_setup(struct platform_device *dev) ...@@ -1461,6 +1472,7 @@ int fsl_rio_setup(struct platform_device *dev)
port->host_deviceid = fsl_rio_get_hdid(port->id); port->host_deviceid = fsl_rio_get_hdid(port->id);
port->priv = priv; port->priv = priv;
port->phys_efptr = 0x100;
rio_register_mport(port); rio_register_mport(port);
priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
...@@ -1508,6 +1520,12 @@ int fsl_rio_setup(struct platform_device *dev) ...@@ -1508,6 +1520,12 @@ int fsl_rio_setup(struct platform_device *dev)
dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
port->sys_size ? 65536 : 256); port->sys_size ? 65536 : 256);
if (port->host_deviceid >= 0)
out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST |
RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED);
else
out_be32(priv->regs_win + RIO_GCCSR, 0x00000000);
priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win
+ RIO_ATMU_REGS_OFFSET); + RIO_ATMU_REGS_OFFSET);
priv->maint_atmu_regs = priv->atmu_regs + 1; priv->maint_atmu_regs = priv->atmu_regs + 1;
......
...@@ -73,18 +73,18 @@ cputime64_to_jiffies64(cputime64_t cputime) ...@@ -73,18 +73,18 @@ cputime64_to_jiffies64(cputime64_t cputime)
} }
/* /*
* Convert cputime to milliseconds and back. * Convert cputime to microseconds and back.
*/ */
static inline unsigned int static inline unsigned int
cputime_to_msecs(const cputime_t cputime) cputime_to_usecs(const cputime_t cputime)
{ {
return cputime_div(cputime, 4096000); return cputime_div(cputime, 4096);
} }
static inline cputime_t static inline cputime_t
msecs_to_cputime(const unsigned int m) usecs_to_cputime(const unsigned int m)
{ {
return (cputime_t) m * 4096000; return (cputime_t) m * 4096;
} }
/* /*
......
...@@ -343,7 +343,8 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) ...@@ -343,7 +343,8 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
return __poke_user(child, addr, data); return __poke_user(child, addr, data);
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
ptrace_area parea; ptrace_area parea;
int copied, ret; int copied, ret;
......
...@@ -325,7 +325,8 @@ void ptrace_disable(struct task_struct *child) ...@@ -325,7 +325,8 @@ void ptrace_disable(struct task_struct *child)
} }
long long
arch_ptrace(struct task_struct *child, long request, long addr, long data) arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned long __user *datap = (void __user *)data; unsigned long __user *datap = (void __user *)data;
...@@ -335,14 +336,14 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -335,14 +336,14 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = copy_regset_to_user(child, &user_score_native_view, ret = copy_regset_to_user(child, &user_score_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(void __user *)datap); datap);
break; break;
case PTRACE_SETREGS: case PTRACE_SETREGS:
ret = copy_regset_from_user(child, &user_score_native_view, ret = copy_regset_from_user(child, &user_score_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(const void __user *)datap); datap);
break; break;
default: default:
......
...@@ -365,9 +365,9 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) ...@@ -365,9 +365,9 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
return &user_sh_native_view; return &user_sh_native_view;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
struct user * dummy = NULL;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
int ret; int ret;
...@@ -383,17 +383,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -383,17 +383,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (addr < sizeof(struct pt_regs)) if (addr < sizeof(struct pt_regs))
tmp = get_stack_long(child, addr); tmp = get_stack_long(child, addr);
else if (addr >= (long) &dummy->fpu && else if (addr >= offsetof(struct user, fpu) &&
addr < (long) &dummy->u_fpvalid) { addr < offsetof(struct user, u_fpvalid)) {
if (!tsk_used_math(child)) { if (!tsk_used_math(child)) {
if (addr == (long)&dummy->fpu.fpscr) if (addr == offsetof(struct user, fpu.fpscr))
tmp = FPSCR_INIT; tmp = FPSCR_INIT;
else else
tmp = 0; tmp = 0;
} else } else {
tmp = ((long *)child->thread.xstate) unsigned long index;
[(addr - (long)&dummy->fpu) >> 2]; index = addr - offsetof(struct user, fpu);
} else if (addr == (long) &dummy->u_fpvalid) tmp = ((unsigned long *)child->thread.xstate)
[index >> 2];
}
} else if (addr == offsetof(struct user, u_fpvalid))
tmp = !!tsk_used_math(child); tmp = !!tsk_used_math(child);
else if (addr == PT_TEXT_ADDR) else if (addr == PT_TEXT_ADDR)
tmp = child->mm->start_code; tmp = child->mm->start_code;
...@@ -417,13 +420,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -417,13 +420,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (addr < sizeof(struct pt_regs)) if (addr < sizeof(struct pt_regs))
ret = put_stack_long(child, addr, data); ret = put_stack_long(child, addr, data);
else if (addr >= (long) &dummy->fpu && else if (addr >= offsetof(struct user, fpu) &&
addr < (long) &dummy->u_fpvalid) { addr < offsetof(struct user, u_fpvalid)) {
unsigned long index;
index = addr - offsetof(struct user, fpu);
set_stopped_child_used_math(child); set_stopped_child_used_math(child);
((long *)child->thread.xstate) ((unsigned long *)child->thread.xstate)
[(addr - (long)&dummy->fpu) >> 2] = data; [index >> 2] = data;
ret = 0; ret = 0;
} else if (addr == (long) &dummy->u_fpvalid) { } else if (addr == offsetof(struct user, u_fpvalid)) {
conditional_stopped_child_used_math(data, child); conditional_stopped_child_used_math(data, child);
ret = 0; ret = 0;
} }
...@@ -433,35 +438,35 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -433,35 +438,35 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return copy_regset_to_user(child, &user_sh_native_view, return copy_regset_to_user(child, &user_sh_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(void __user *)data); datap);
case PTRACE_SETREGS: case PTRACE_SETREGS:
return copy_regset_from_user(child, &user_sh_native_view, return copy_regset_from_user(child, &user_sh_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(const void __user *)data); datap);
#ifdef CONFIG_SH_FPU #ifdef CONFIG_SH_FPU
case PTRACE_GETFPREGS: case PTRACE_GETFPREGS:
return copy_regset_to_user(child, &user_sh_native_view, return copy_regset_to_user(child, &user_sh_native_view,
REGSET_FPU, REGSET_FPU,
0, sizeof(struct user_fpu_struct), 0, sizeof(struct user_fpu_struct),
(void __user *)data); datap);
case PTRACE_SETFPREGS: case PTRACE_SETFPREGS:
return copy_regset_from_user(child, &user_sh_native_view, return copy_regset_from_user(child, &user_sh_native_view,
REGSET_FPU, REGSET_FPU,
0, sizeof(struct user_fpu_struct), 0, sizeof(struct user_fpu_struct),
(const void __user *)data); datap);
#endif #endif
#ifdef CONFIG_SH_DSP #ifdef CONFIG_SH_DSP
case PTRACE_GETDSPREGS: case PTRACE_GETDSPREGS:
return copy_regset_to_user(child, &user_sh_native_view, return copy_regset_to_user(child, &user_sh_native_view,
REGSET_DSP, REGSET_DSP,
0, sizeof(struct pt_dspregs), 0, sizeof(struct pt_dspregs),
(void __user *)data); datap);
case PTRACE_SETDSPREGS: case PTRACE_SETDSPREGS:
return copy_regset_from_user(child, &user_sh_native_view, return copy_regset_from_user(child, &user_sh_native_view,
REGSET_DSP, REGSET_DSP,
0, sizeof(struct pt_dspregs), 0, sizeof(struct pt_dspregs),
(const void __user *)data); datap);
#endif #endif
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
......
...@@ -383,9 +383,11 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) ...@@ -383,9 +383,11 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
return &user_sh64_native_view; return &user_sh64_native_view;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) { switch (request) {
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
...@@ -400,13 +402,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -400,13 +402,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = get_stack_long(child, addr); tmp = get_stack_long(child, addr);
else if ((addr >= offsetof(struct user, fpu)) && else if ((addr >= offsetof(struct user, fpu)) &&
(addr < offsetof(struct user, u_fpvalid))) { (addr < offsetof(struct user, u_fpvalid))) {
tmp = get_fpu_long(child, addr - offsetof(struct user, fpu)); unsigned long index;
index = addr - offsetof(struct user, fpu);
tmp = get_fpu_long(child, index);
} else if (addr == offsetof(struct user, u_fpvalid)) { } else if (addr == offsetof(struct user, u_fpvalid)) {
tmp = !!tsk_used_math(child); tmp = !!tsk_used_math(child);
} else { } else {
break; break;
} }
ret = put_user(tmp, (unsigned long *)data); ret = put_user(tmp, datap);
break; break;
} }
...@@ -437,7 +441,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -437,7 +441,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
else if ((addr >= offsetof(struct user, fpu)) && else if ((addr >= offsetof(struct user, fpu)) &&
(addr < offsetof(struct user, u_fpvalid))) { (addr < offsetof(struct user, u_fpvalid))) {
ret = put_fpu_long(child, addr - offsetof(struct user, fpu), data); unsigned long index;
index = addr - offsetof(struct user, fpu);
ret = put_fpu_long(child, index, data);
} }
break; break;
...@@ -445,23 +451,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -445,23 +451,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return copy_regset_to_user(child, &user_sh64_native_view, return copy_regset_to_user(child, &user_sh64_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(void __user *)data); datap);
case PTRACE_SETREGS: case PTRACE_SETREGS:
return copy_regset_from_user(child, &user_sh64_native_view, return copy_regset_from_user(child, &user_sh64_native_view,
REGSET_GENERAL, REGSET_GENERAL,
0, sizeof(struct pt_regs), 0, sizeof(struct pt_regs),
(const void __user *)data); datap);
#ifdef CONFIG_SH_FPU #ifdef CONFIG_SH_FPU
case PTRACE_GETFPREGS: case PTRACE_GETFPREGS:
return copy_regset_to_user(child, &user_sh64_native_view, return copy_regset_to_user(child, &user_sh64_native_view,
REGSET_FPU, REGSET_FPU,
0, sizeof(struct user_fpu_struct), 0, sizeof(struct user_fpu_struct),
(void __user *)data); datap);
case PTRACE_SETFPREGS: case PTRACE_SETFPREGS:
return copy_regset_from_user(child, &user_sh64_native_view, return copy_regset_from_user(child, &user_sh64_native_view,
REGSET_FPU, REGSET_FPU,
0, sizeof(struct user_fpu_struct), 0, sizeof(struct user_fpu_struct),
(const void __user *)data); datap);
#endif #endif
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
...@@ -471,7 +477,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -471,7 +477,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
return ret; return ret;
} }
asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) asmlinkage int sh64_ptrace(long request, long pid,
unsigned long addr, unsigned long data)
{ {
#define WPC_DBRMODE 0x0d104008 #define WPC_DBRMODE 0x0d104008
static unsigned long first_call; static unsigned long first_call;
......
...@@ -207,6 +207,21 @@ _memset_io(volatile void __iomem *dst, int c, __kernel_size_t n) ...@@ -207,6 +207,21 @@ _memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
#define memset_io(d,c,sz) _memset_io(d,c,sz) #define memset_io(d,c,sz) _memset_io(d,c,sz)
static inline void
_sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
__kernel_size_t n)
{
char *d = dst;
while (n--) {
char tmp = sbus_readb(src);
*d++ = tmp;
src++;
}
}
#define sbus_memcpy_fromio(d, s, sz) _sbus_memcpy_fromio(d, s, sz)
static inline void static inline void
_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
{ {
...@@ -221,6 +236,22 @@ _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) ...@@ -221,6 +236,22 @@ _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
#define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz) #define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz)
static inline void
_sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
__kernel_size_t n)
{
const char *s = src;
volatile void __iomem *d = dst;
while (n--) {
char tmp = *s++;
sbus_writeb(tmp, d);
d++;
}
}
#define sbus_memcpy_toio(d, s, sz) _sbus_memcpy_toio(d, s, sz)
static inline void static inline void
_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n) _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
{ {
......
...@@ -418,6 +418,21 @@ _memset_io(volatile void __iomem *dst, int c, __kernel_size_t n) ...@@ -418,6 +418,21 @@ _memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
#define memset_io(d,c,sz) _memset_io(d,c,sz) #define memset_io(d,c,sz) _memset_io(d,c,sz)
static inline void
_sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
__kernel_size_t n)
{
char *d = dst;
while (n--) {
char tmp = sbus_readb(src);
*d++ = tmp;
src++;
}
}
#define sbus_memcpy_fromio(d, s, sz) _sbus_memcpy_fromio(d, s, sz)
static inline void static inline void
_memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
{ {
...@@ -432,6 +447,22 @@ _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n) ...@@ -432,6 +447,22 @@ _memcpy_fromio(void *dst, const volatile void __iomem *src, __kernel_size_t n)
#define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz) #define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz)
static inline void
_sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
__kernel_size_t n)
{
const char *s = src;
volatile void __iomem *d = dst;
while (n--) {
char tmp = *s++;
sbus_writeb(tmp, d);
d++;
}
}
#define sbus_memcpy_toio(d, s, sz) _sbus_memcpy_toio(d, s, sz)
static inline void static inline void
_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n) _memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
{ {
......
...@@ -38,7 +38,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) ...@@ -38,7 +38,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
* types on sparc64. However, it requires that the device * types on sparc64. However, it requires that the device
* can drive enough of the 64 bits. * can drive enough of the 64 bits.
*/ */
#define PCI64_REQUIRED_MASK (~(dma64_addr_t)0) #define PCI64_REQUIRED_MASK (~(u64)0)
#define PCI64_ADDR_BASE 0xfffc000000000000UL #define PCI64_ADDR_BASE 0xfffc000000000000UL
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
......
...@@ -323,18 +323,35 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) ...@@ -323,18 +323,35 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
return &user_sparc32_view; return &user_sparc32_view;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct fps {
unsigned long regs[32];
unsigned long fsr;
unsigned long flags;
unsigned long extra;
unsigned long fpqd;
struct fq {
unsigned long *insnaddr;
unsigned long insn;
} fpq[16];
};
long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
void __user *addr2p;
const struct user_regset_view *view; const struct user_regset_view *view;
struct pt_regs __user *pregs;
struct fps __user *fps;
int ret; int ret;
view = task_user_regset_view(current); view = task_user_regset_view(current);
addr2p = (void __user *) addr2;
pregs = (struct pt_regs __user *) addr;
fps = (struct fps __user *) addr;
switch(request) { switch(request) {
case PTRACE_GETREGS: { case PTRACE_GETREGS: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
ret = copy_regset_to_user(child, view, REGSET_GENERAL, ret = copy_regset_to_user(child, view, REGSET_GENERAL,
32 * sizeof(u32), 32 * sizeof(u32),
4 * sizeof(u32), 4 * sizeof(u32),
...@@ -348,8 +365,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -348,8 +365,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
case PTRACE_SETREGS: { case PTRACE_SETREGS: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
ret = copy_regset_from_user(child, view, REGSET_GENERAL, ret = copy_regset_from_user(child, view, REGSET_GENERAL,
32 * sizeof(u32), 32 * sizeof(u32),
4 * sizeof(u32), 4 * sizeof(u32),
...@@ -363,19 +378,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -363,19 +378,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
case PTRACE_GETFPREGS: { case PTRACE_GETFPREGS: {
struct fps {
unsigned long regs[32];
unsigned long fsr;
unsigned long flags;
unsigned long extra;
unsigned long fpqd;
struct fq {
unsigned long *insnaddr;
unsigned long insn;
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
ret = copy_regset_to_user(child, view, REGSET_FP, ret = copy_regset_to_user(child, view, REGSET_FP,
0 * sizeof(u32), 0 * sizeof(u32),
32 * sizeof(u32), 32 * sizeof(u32),
...@@ -397,19 +399,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -397,19 +399,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} }
case PTRACE_SETFPREGS: { case PTRACE_SETFPREGS: {
struct fps {
unsigned long regs[32];
unsigned long fsr;
unsigned long flags;
unsigned long extra;
unsigned long fpqd;
struct fq {
unsigned long *insnaddr;
unsigned long insn;
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
ret = copy_regset_from_user(child, view, REGSET_FP, ret = copy_regset_from_user(child, view, REGSET_FP,
0 * sizeof(u32), 0 * sizeof(u32),
32 * sizeof(u32), 32 * sizeof(u32),
...@@ -424,8 +413,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -424,8 +413,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_READTEXT: case PTRACE_READTEXT:
case PTRACE_READDATA: case PTRACE_READDATA:
ret = ptrace_readdata(child, addr, ret = ptrace_readdata(child, addr, addr2p, data);
(void __user *) addr2, data);
if (ret == data) if (ret == data)
ret = 0; ret = 0;
...@@ -435,8 +423,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -435,8 +423,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_WRITETEXT: case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA: case PTRACE_WRITEDATA:
ret = ptrace_writedata(child, (void __user *) addr2, ret = ptrace_writedata(child, addr2p, addr, data);
addr, data);
if (ret == data) if (ret == data)
ret = 0; ret = 0;
......
...@@ -969,16 +969,19 @@ struct fps { ...@@ -969,16 +969,19 @@ struct fps {
unsigned long fsr; unsigned long fsr;
}; };
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
const struct user_regset_view *view = task_user_regset_view(current); const struct user_regset_view *view = task_user_regset_view(current);
unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
struct pt_regs __user *pregs; struct pt_regs __user *pregs;
struct fps __user *fps; struct fps __user *fps;
void __user *addr2p;
int ret; int ret;
pregs = (struct pt_regs __user *) (unsigned long) addr; pregs = (struct pt_regs __user *) addr;
fps = (struct fps __user *) (unsigned long) addr; fps = (struct fps __user *) addr;
addr2p = (void __user *) addr2;
switch (request) { switch (request) {
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
...@@ -1029,8 +1032,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1029,8 +1032,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_READTEXT: case PTRACE_READTEXT:
case PTRACE_READDATA: case PTRACE_READDATA:
ret = ptrace_readdata(child, addr, ret = ptrace_readdata(child, addr, addr2p, data);
(char __user *)addr2, data);
if (ret == data) if (ret == data)
ret = 0; ret = 0;
else if (ret >= 0) else if (ret >= 0)
...@@ -1039,8 +1041,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1039,8 +1041,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_WRITETEXT: case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA: case PTRACE_WRITEDATA:
ret = ptrace_writedata(child, (char __user *) addr2, ret = ptrace_writedata(child, addr2p, addr, data);
addr, data);
if (ret == data) if (ret == data)
ret = 0; ret = 0;
else if (ret >= 0) else if (ret >= 0)
......
...@@ -75,7 +75,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -75,7 +75,7 @@ void __kunmap_atomic(void *kvaddr)
return; return;
} }
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
#ifdef CONFIG_DEBUG_HIGHMEM #ifdef CONFIG_DEBUG_HIGHMEM
{ {
...@@ -104,6 +104,8 @@ void __kunmap_atomic(void *kvaddr) ...@@ -104,6 +104,8 @@ void __kunmap_atomic(void *kvaddr)
#endif #endif
} }
#endif #endif
kmap_atomic_idx_pop();
pagefault_enable(); pagefault_enable();
} }
EXPORT_SYMBOL(__kunmap_atomic); EXPORT_SYMBOL(__kunmap_atomic);
......
...@@ -58,6 +58,9 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING ...@@ -58,6 +58,9 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING
config ARCH_PHYS_ADDR_T_64BIT config ARCH_PHYS_ADDR_T_64BIT
def_bool y def_bool y
config ARCH_DMA_ADDR_T_64BIT
def_bool y
config LOCKDEP_SUPPORT config LOCKDEP_SUPPORT
def_bool y def_bool y
......
...@@ -45,7 +45,8 @@ void ptrace_disable(struct task_struct *child) ...@@ -45,7 +45,8 @@ void ptrace_disable(struct task_struct *child)
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
unsigned long __user *datap = (long __user __force *)data; unsigned long __user *datap = (long __user __force *)data;
unsigned long tmp; unsigned long tmp;
...@@ -57,7 +58,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -57,7 +58,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) { switch (request) {
case PTRACE_PEEKUSR: /* Read register from pt_regs. */ case PTRACE_PEEKUSR: /* Read register from pt_regs. */
if (addr < 0 || addr >= PTREGS_SIZE) if (addr >= PTREGS_SIZE)
break; break;
childreg = (char *)task_pt_regs(child) + addr; childreg = (char *)task_pt_regs(child) + addr;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -76,7 +77,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -76,7 +77,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_POKEUSR: /* Write register in pt_regs. */ case PTRACE_POKEUSR: /* Write register in pt_regs. */
if (addr < 0 || addr >= PTREGS_SIZE) if (addr >= PTREGS_SIZE)
break; break;
childreg = (char *)task_pt_regs(child) + addr; childreg = (char *)task_pt_regs(child) + addr;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -98,7 +99,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -98,7 +99,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE))
break; break;
childregs = (long *)task_pt_regs(child); childregs = (long *)task_pt_regs(child);
for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) { for (i = 0; i < sizeof(struct pt_regs)/sizeof(unsigned long);
++i) {
ret = __put_user(childregs[i], &datap[i]); ret = __put_user(childregs[i], &datap[i]);
if (ret != 0) if (ret != 0)
break; break;
...@@ -109,7 +111,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -109,7 +111,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE))
break; break;
childregs = (long *)task_pt_regs(child); childregs = (long *)task_pt_regs(child);
for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) { for (i = 0; i < sizeof(struct pt_regs)/sizeof(unsigned long);
++i) {
ret = __get_user(childregs[i], &datap[i]); ret = __get_user(childregs[i], &datap[i]);
if (ret != 0) if (ret != 0)
break; break;
......
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#include <linux/timex.h> #include <linux/timex.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/sections.h>
#include <asm/cacheflush.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
......
...@@ -241,7 +241,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -241,7 +241,7 @@ void __kunmap_atomic(void *kvaddr)
pte_t pteval = *pte; pte_t pteval = *pte;
int idx, type; int idx, type;
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
idx = type + KM_TYPE_NR*smp_processor_id(); idx = type + KM_TYPE_NR*smp_processor_id();
/* /*
...@@ -252,6 +252,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -252,6 +252,7 @@ void __kunmap_atomic(void *kvaddr)
BUG_ON(!pte_present(pteval) && !pte_migrating(pteval)); BUG_ON(!pte_present(pteval) && !pte_migrating(pteval));
kmap_atomic_unregister(pte_page(pteval), vaddr); kmap_atomic_unregister(pte_page(pteval), vaddr);
kpte_clear_flush(pte, vaddr); kpte_clear_flush(pte, vaddr);
kmap_atomic_idx_pop();
} else { } else {
/* Must be a lowmem page */ /* Must be a lowmem page */
BUG_ON(vaddr < PAGE_OFFSET); BUG_ON(vaddr < PAGE_OFFSET);
......
...@@ -42,10 +42,12 @@ void ptrace_disable(struct task_struct *child) ...@@ -42,10 +42,12 @@ void ptrace_disable(struct task_struct *child)
extern int peek_user(struct task_struct * child, long addr, long data); extern int peek_user(struct task_struct * child, long addr, long data);
extern int poke_user(struct task_struct * child, long addr, long data); extern int poke_user(struct task_struct * child, long addr, long data);
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int i, ret; int i, ret;
unsigned long __user *p = (void __user *)(unsigned long)data; unsigned long __user *p = (void __user *)data;
void __user *vp = p;
switch (request) { switch (request) {
/* read word at location addr. */ /* read word at location addr. */
...@@ -107,24 +109,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -107,24 +109,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif #endif
#ifdef PTRACE_GETFPREGS #ifdef PTRACE_GETFPREGS
case PTRACE_GETFPREGS: /* Get the child FPU state. */ case PTRACE_GETFPREGS: /* Get the child FPU state. */
ret = get_fpregs((struct user_i387_struct __user *) data, ret = get_fpregs(vp, child);
child);
break; break;
#endif #endif
#ifdef PTRACE_SETFPREGS #ifdef PTRACE_SETFPREGS
case PTRACE_SETFPREGS: /* Set the child FPU state. */ case PTRACE_SETFPREGS: /* Set the child FPU state. */
ret = set_fpregs((struct user_i387_struct __user *) data, ret = set_fpregs(vp, child);
child);
break; break;
#endif #endif
case PTRACE_GET_THREAD_AREA: case PTRACE_GET_THREAD_AREA:
ret = ptrace_get_thread_area(child, addr, ret = ptrace_get_thread_area(child, addr, vp);
(struct user_desc __user *) data);
break; break;
case PTRACE_SET_THREAD_AREA: case PTRACE_SET_THREAD_AREA:
ret = ptrace_set_thread_area(child, addr, ret = ptrace_set_thread_area(child, addr, datavp);
(struct user_desc __user *) data);
break; break;
case PTRACE_FAULTINFO: { case PTRACE_FAULTINFO: {
...@@ -134,7 +132,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -134,7 +132,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* On i386, ptrace_faultinfo is smaller! * On i386, ptrace_faultinfo is smaller!
*/ */
ret = copy_to_user(p, &child->thread.arch.faultinfo, ret = copy_to_user(p, &child->thread.arch.faultinfo,
sizeof(struct ptrace_faultinfo)); sizeof(struct ptrace_faultinfo)) ?
-EIO : 0;
break; break;
} }
...@@ -158,7 +157,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -158,7 +157,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_ARCH_PRCTL #ifdef PTRACE_ARCH_PRCTL
case PTRACE_ARCH_PRCTL: case PTRACE_ARCH_PRCTL:
/* XXX Calls ptrace on the host - needs some SMP thinking */ /* XXX Calls ptrace on the host - needs some SMP thinking */
ret = arch_prctl(child, data, (void *) addr); ret = arch_prctl(child, data, (void __user *) addr);
break; break;
#endif #endif
default: default:
......
...@@ -203,8 +203,8 @@ int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) ...@@ -203,8 +203,8 @@ int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
(unsigned long *) &fpregs); (unsigned long *) &fpregs);
} }
long subarch_ptrace(struct task_struct *child, long request, long addr, long subarch_ptrace(struct task_struct *child, long request,
long data) unsigned long addr, unsigned long data)
{ {
return -EIO; return -EIO;
} }
...@@ -175,19 +175,18 @@ int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) ...@@ -175,19 +175,18 @@ int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
return restore_fp_registers(userspace_pid[cpu], fpregs); return restore_fp_registers(userspace_pid[cpu], fpregs);
} }
long subarch_ptrace(struct task_struct *child, long request, long addr, long subarch_ptrace(struct task_struct *child, long request,
long data) unsigned long addr, unsigned long data)
{ {
int ret = -EIO; int ret = -EIO;
void __user *datap = (void __user *) data;
switch (request) { switch (request) {
case PTRACE_GETFPXREGS: /* Get the child FPU state. */ case PTRACE_GETFPXREGS: /* Get the child FPU state. */
ret = get_fpregs((struct user_i387_struct __user *) data, ret = get_fpregs(datap, child);
child);
break; break;
case PTRACE_SETFPXREGS: /* Set the child FPU state. */ case PTRACE_SETFPXREGS: /* Set the child FPU state. */
ret = set_fpregs((struct user_i387_struct __user *) data, ret = set_fpregs(datap, child);
child);
break; break;
} }
......
...@@ -801,7 +801,8 @@ void ptrace_disable(struct task_struct *child) ...@@ -801,7 +801,8 @@ void ptrace_disable(struct task_struct *child)
static const struct user_regset_view user_x86_32_view; /* Initialized below. */ static const struct user_regset_view user_x86_32_view; /* Initialized below. */
#endif #endif
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
...@@ -812,8 +813,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -812,8 +813,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp; unsigned long tmp;
ret = -EIO; ret = -EIO;
if ((addr & (sizeof(data) - 1)) || addr < 0 || if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
addr >= sizeof(struct user))
break; break;
tmp = 0; /* Default return condition */ tmp = 0; /* Default return condition */
...@@ -830,8 +830,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -830,8 +830,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
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 & (sizeof(data) - 1)) || addr < 0 || if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
addr >= sizeof(struct user))
break; break;
if (addr < sizeof(struct user_regs_struct)) if (addr < sizeof(struct user_regs_struct))
...@@ -888,17 +887,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -888,17 +887,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
case PTRACE_GET_THREAD_AREA: case PTRACE_GET_THREAD_AREA:
if (addr < 0) if ((int) addr < 0)
return -EIO; return -EIO;
ret = do_get_thread_area(child, addr, ret = do_get_thread_area(child, addr,
(struct user_desc __user *) data); (struct user_desc __user *)data);
break; break;
case PTRACE_SET_THREAD_AREA: case PTRACE_SET_THREAD_AREA:
if (addr < 0) if ((int) addr < 0)
return -EIO; return -EIO;
ret = do_set_thread_area(child, addr, ret = do_set_thread_area(child, addr,
(struct user_desc __user *) data, 0); (struct user_desc __user *)data, 0);
break; break;
#endif #endif
......
...@@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr)
vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) { vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
int idx, type; int idx, type;
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
idx = type + KM_TYPE_NR * smp_processor_id(); idx = type + KM_TYPE_NR * smp_processor_id();
#ifdef CONFIG_DEBUG_HIGHMEM #ifdef CONFIG_DEBUG_HIGHMEM
...@@ -87,6 +87,7 @@ void __kunmap_atomic(void *kvaddr) ...@@ -87,6 +87,7 @@ void __kunmap_atomic(void *kvaddr)
* attributes or becomes a protected page in a hypervisor. * attributes or becomes a protected page in a hypervisor.
*/ */
kpte_clear_flush(kmap_pte-idx, vaddr); kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
} }
#ifdef CONFIG_DEBUG_HIGHMEM #ifdef CONFIG_DEBUG_HIGHMEM
else { else {
......
...@@ -51,7 +51,6 @@ ...@@ -51,7 +51,6 @@
#include <asm/numa.h> #include <asm/numa.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/init.h> #include <asm/init.h>
#include <linux/bootmem.h>
static int __init parse_direct_gbpages_off(char *arg) static int __init parse_direct_gbpages_off(char *arg)
{ {
......
...@@ -98,7 +98,7 @@ iounmap_atomic(void __iomem *kvaddr) ...@@ -98,7 +98,7 @@ iounmap_atomic(void __iomem *kvaddr)
vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) { vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
int idx, type; int idx, type;
type = kmap_atomic_idx_pop(); type = kmap_atomic_idx();
idx = type + KM_TYPE_NR * smp_processor_id(); idx = type + KM_TYPE_NR * smp_processor_id();
#ifdef CONFIG_DEBUG_HIGHMEM #ifdef CONFIG_DEBUG_HIGHMEM
...@@ -111,6 +111,7 @@ iounmap_atomic(void __iomem *kvaddr) ...@@ -111,6 +111,7 @@ iounmap_atomic(void __iomem *kvaddr)
* attributes or becomes a protected page in a hypervisor. * attributes or becomes a protected page in a hypervisor.
*/ */
kpte_clear_flush(kmap_pte-idx, vaddr); kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
} }
pagefault_enable(); pagefault_enable();
......
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/setup.h>
#include <asm/stackprotector.h> #include <asm/stackprotector.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
......
...@@ -256,9 +256,11 @@ int ptrace_pokeusr(struct task_struct *child, long regno, long val) ...@@ -256,9 +256,11 @@ int ptrace_pokeusr(struct task_struct *child, long regno, long val)
return 0; return 0;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) long arch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{ {
int ret = -EPERM; int ret = -EPERM;
void __user *datap = (void __user *) data;
switch (request) { switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
...@@ -267,7 +269,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -267,7 +269,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_PEEKUSR: /* read register specified by addr. */ case PTRACE_PEEKUSR: /* read register specified by addr. */
ret = ptrace_peekusr(child, addr, (void __user *) data); ret = ptrace_peekusr(child, addr, datap);
break; break;
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
...@@ -280,19 +282,19 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -280,19 +282,19 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
case PTRACE_GETREGS: case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *) data); ret = ptrace_getregs(child, datap);
break; break;
case PTRACE_SETREGS: case PTRACE_SETREGS:
ret = ptrace_setregs(child, (void __user *) data); ret = ptrace_setregs(child, datap);
break; break;
case PTRACE_GETXTREGS: case PTRACE_GETXTREGS:
ret = ptrace_getxregs(child, (void __user *) data); ret = ptrace_getxregs(child, datap);
break; break;
case PTRACE_SETXTREGS: case PTRACE_SETXTREGS:
ret = ptrace_setxregs(child, (void __user *) data); ret = ptrace_setxregs(child, datap);
break; break;
default: default:
......
...@@ -566,6 +566,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_ ...@@ -566,6 +566,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_
struct mailbox mailbox; struct mailbox mailbox;
/* Got a packet for us */ /* Got a packet for us */
memset(&st_loc, 0, sizeof(st_loc));
ret = do_ac_read(i, buf, &st_loc, &mailbox); ret = do_ac_read(i, buf, &st_loc, &mailbox);
spin_unlock_irqrestore(&apbs[i].mutex, flags); spin_unlock_irqrestore(&apbs[i].mutex, flags);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
......
...@@ -713,7 +713,6 @@ static int khvcd(void *unused) ...@@ -713,7 +713,6 @@ static int khvcd(void *unused)
struct hvc_struct *hp; struct hvc_struct *hp;
set_freezable(); set_freezable();
__set_current_state(TASK_RUNNING);
do { do {
poll_mask = 0; poll_mask = 0;
hvc_kicked = 0; hvc_kicked = 0;
......
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
obj-$(CONFIG_COMPUTONE) += ip2.o obj-$(CONFIG_COMPUTONE) += ip2.o
ip2-objs := ip2main.o ip2-y := ip2main.o
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for the ipmi drivers. # Makefile for the ipmi drivers.
# #
ipmi_si-objs := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o
obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
......
...@@ -916,7 +916,7 @@ static struct ipmi_smi_watcher smi_watcher = ...@@ -916,7 +916,7 @@ static struct ipmi_smi_watcher smi_watcher =
.smi_gone = ipmi_smi_gone, .smi_gone = ipmi_smi_gone,
}; };
static __init int init_ipmi_devintf(void) static int __init init_ipmi_devintf(void)
{ {
int rv; int rv;
...@@ -954,7 +954,7 @@ static __init int init_ipmi_devintf(void) ...@@ -954,7 +954,7 @@ static __init int init_ipmi_devintf(void)
} }
module_init(init_ipmi_devintf); module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void) static void __exit cleanup_ipmi(void)
{ {
struct ipmi_reg_list *entry, *entry2; struct ipmi_reg_list *entry, *entry2;
mutex_lock(&reg_list_mutex); mutex_lock(&reg_list_mutex);
......
...@@ -4442,13 +4442,13 @@ static int ipmi_init_msghandler(void) ...@@ -4442,13 +4442,13 @@ static int ipmi_init_msghandler(void)
return 0; return 0;
} }
static __init int ipmi_init_msghandler_mod(void) static int __init ipmi_init_msghandler_mod(void)
{ {
ipmi_init_msghandler(); ipmi_init_msghandler();
return 0; return 0;
} }
static __exit void cleanup_ipmi(void) static void __exit cleanup_ipmi(void)
{ {
int count; int count;
......
...@@ -1846,7 +1846,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) ...@@ -1846,7 +1846,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
return rv; return rv;
} }
static __devinit void hardcode_find_bmc(void) static void __devinit hardcode_find_bmc(void)
{ {
int i; int i;
struct smi_info *info; struct smi_info *info;
...@@ -2029,7 +2029,7 @@ struct SPMITable { ...@@ -2029,7 +2029,7 @@ struct SPMITable {
s8 spmi_id[1]; /* A '\0' terminated array starts here. */ s8 spmi_id[1]; /* A '\0' terminated array starts here. */
}; };
static __devinit int try_init_spmi(struct SPMITable *spmi) static int __devinit try_init_spmi(struct SPMITable *spmi)
{ {
struct smi_info *info; struct smi_info *info;
...@@ -2112,7 +2112,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) ...@@ -2112,7 +2112,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
return 0; return 0;
} }
static __devinit void spmi_find_bmc(void) static void __devinit spmi_find_bmc(void)
{ {
acpi_status status; acpi_status status;
struct SPMITable *spmi; struct SPMITable *spmi;
...@@ -2325,7 +2325,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm, ...@@ -2325,7 +2325,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
return 0; return 0;
} }
static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data)
{ {
struct smi_info *info; struct smi_info *info;
...@@ -3012,7 +3012,7 @@ static __devinitdata struct ipmi_default_vals ...@@ -3012,7 +3012,7 @@ static __devinitdata struct ipmi_default_vals
{ .port = 0 } { .port = 0 }
}; };
static __devinit void default_find_bmc(void) static void __devinit default_find_bmc(void)
{ {
struct smi_info *info; struct smi_info *info;
int i; int i;
...@@ -3312,7 +3312,7 @@ static int try_smi_init(struct smi_info *new_smi) ...@@ -3312,7 +3312,7 @@ static int try_smi_init(struct smi_info *new_smi)
return rv; return rv;
} }
static __devinit int init_ipmi_si(void) static int __devinit init_ipmi_si(void)
{ {
int i; int i;
char *str; char *str;
...@@ -3525,7 +3525,7 @@ static void cleanup_one_si(struct smi_info *to_clean) ...@@ -3525,7 +3525,7 @@ static void cleanup_one_si(struct smi_info *to_clean)
kfree(to_clean); kfree(to_clean);
} }
static __exit void cleanup_ipmi_si(void) static void __exit cleanup_ipmi_si(void)
{ {
struct smi_info *e, *tmp_e; struct smi_info *e, *tmp_e;
......
...@@ -176,9 +176,9 @@ static void mmtimer_setup_int_2(int cpu, u64 expires) ...@@ -176,9 +176,9 @@ static void mmtimer_setup_int_2(int cpu, u64 expires)
* in order to insure that the setup succeeds in a deterministic time frame. * in order to insure that the setup succeeds in a deterministic time frame.
* It will check if the interrupt setup succeeded. * It will check if the interrupt setup succeeded.
*/ */
static int mmtimer_setup(int cpu, int comparator, unsigned long expires) static int mmtimer_setup(int cpu, int comparator, unsigned long expires,
u64 *set_completion_time)
{ {
switch (comparator) { switch (comparator) {
case 0: case 0:
mmtimer_setup_int_0(cpu, expires); mmtimer_setup_int_0(cpu, expires);
...@@ -191,7 +191,8 @@ static int mmtimer_setup(int cpu, int comparator, unsigned long expires) ...@@ -191,7 +191,8 @@ static int mmtimer_setup(int cpu, int comparator, unsigned long expires)
break; break;
} }
/* We might've missed our expiration time */ /* We might've missed our expiration time */
if (rtc_time() <= expires) *set_completion_time = rtc_time();
if (*set_completion_time <= expires)
return 1; return 1;
/* /*
...@@ -227,6 +228,8 @@ static int mmtimer_disable_int(long nasid, int comparator) ...@@ -227,6 +228,8 @@ static int mmtimer_disable_int(long nasid, int comparator)
#define TIMER_OFF 0xbadcabLL /* Timer is not setup */ #define TIMER_OFF 0xbadcabLL /* Timer is not setup */
#define TIMER_SET 0 /* Comparator is set for this timer */ #define TIMER_SET 0 /* Comparator is set for this timer */
#define MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT 40
/* There is one of these for each timer */ /* There is one of these for each timer */
struct mmtimer { struct mmtimer {
struct rb_node list; struct rb_node list;
...@@ -242,6 +245,11 @@ struct mmtimer_node { ...@@ -242,6 +245,11 @@ struct mmtimer_node {
}; };
static struct mmtimer_node *timers; static struct mmtimer_node *timers;
static unsigned mmtimer_interval_retry_increment =
MMTIMER_INTERVAL_RETRY_INCREMENT_DEFAULT;
module_param(mmtimer_interval_retry_increment, uint, 0644);
MODULE_PARM_DESC(mmtimer_interval_retry_increment,
"RTC ticks to add to expiration on interval retry (default 40)");
/* /*
* Add a new mmtimer struct to the node's mmtimer list. * Add a new mmtimer struct to the node's mmtimer list.
...@@ -289,7 +297,8 @@ static void mmtimer_set_next_timer(int nodeid) ...@@ -289,7 +297,8 @@ static void mmtimer_set_next_timer(int nodeid)
struct mmtimer_node *n = &timers[nodeid]; struct mmtimer_node *n = &timers[nodeid];
struct mmtimer *x; struct mmtimer *x;
struct k_itimer *t; struct k_itimer *t;
int o; u64 expires, exp, set_completion_time;
int i;
restart: restart:
if (n->next == NULL) if (n->next == NULL)
...@@ -300,7 +309,8 @@ static void mmtimer_set_next_timer(int nodeid) ...@@ -300,7 +309,8 @@ static void mmtimer_set_next_timer(int nodeid)
if (!t->it.mmtimer.incr) { if (!t->it.mmtimer.incr) {
/* Not an interval timer */ /* Not an interval timer */
if (!mmtimer_setup(x->cpu, COMPARATOR, if (!mmtimer_setup(x->cpu, COMPARATOR,
t->it.mmtimer.expires)) { t->it.mmtimer.expires,
&set_completion_time)) {
/* Late setup, fire now */ /* Late setup, fire now */
tasklet_schedule(&n->tasklet); tasklet_schedule(&n->tasklet);
} }
...@@ -308,14 +318,23 @@ static void mmtimer_set_next_timer(int nodeid) ...@@ -308,14 +318,23 @@ static void mmtimer_set_next_timer(int nodeid)
} }
/* Interval timer */ /* Interval timer */
o = 0; i = 0;
while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) { expires = exp = t->it.mmtimer.expires;
unsigned long e, e1; while (!mmtimer_setup(x->cpu, COMPARATOR, expires,
struct rb_node *next; &set_completion_time)) {
t->it.mmtimer.expires += t->it.mmtimer.incr << o; int to;
t->it_overrun += 1 << o;
o++; i++;
if (o > 20) { expires = set_completion_time +
mmtimer_interval_retry_increment + (1 << i);
/* Calculate overruns as we go. */
to = ((u64)(expires - exp) / t->it.mmtimer.incr);
if (to) {
t->it_overrun += to;
t->it.mmtimer.expires += t->it.mmtimer.incr * to;
exp = t->it.mmtimer.expires;
}
if (i > 20) {
printk(KERN_ALERT "mmtimer: cannot reschedule timer\n"); printk(KERN_ALERT "mmtimer: cannot reschedule timer\n");
t->it.mmtimer.clock = TIMER_OFF; t->it.mmtimer.clock = TIMER_OFF;
n->next = rb_next(&x->list); n->next = rb_next(&x->list);
...@@ -323,21 +342,6 @@ static void mmtimer_set_next_timer(int nodeid) ...@@ -323,21 +342,6 @@ static void mmtimer_set_next_timer(int nodeid)
kfree(x); kfree(x);
goto restart; goto restart;
} }
e = t->it.mmtimer.expires;
next = rb_next(&x->list);
if (next == NULL)
continue;
e1 = rb_entry(next, struct mmtimer, list)->
timer->it.mmtimer.expires;
if (e > e1) {
n->next = next;
rb_erase(&x->list, &n->timer_head);
mmtimer_add_list(x);
goto restart;
}
} }
} }
......
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
obj-$(CONFIG_MWAVE) += mwave.o obj-$(CONFIG_MWAVE) += mwave.o
mwave-objs := mwavedd.o smapi.o tp3780i.o 3780i.o mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o
# To have the mwave driver disable other uarts if necessary # To have the mwave driver disable other uarts if necessary
# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES # EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES
# To compile in lots (~20 KiB) of run-time enablable printk()s for debugging: # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging:
EXTRA_CFLAGS += -DMW_TRACE ccflags-y := -DMW_TRACE
...@@ -303,6 +303,7 @@ static void mxser_enable_must_enchance_mode(unsigned long baseio) ...@@ -303,6 +303,7 @@ static void mxser_enable_must_enchance_mode(unsigned long baseio)
outb(oldlcr, baseio + UART_LCR); outb(oldlcr, baseio + UART_LCR);
} }
#ifdef CONFIG_PCI
static void mxser_disable_must_enchance_mode(unsigned long baseio) static void mxser_disable_must_enchance_mode(unsigned long baseio)
{ {
u8 oldlcr; u8 oldlcr;
...@@ -317,6 +318,7 @@ static void mxser_disable_must_enchance_mode(unsigned long baseio) ...@@ -317,6 +318,7 @@ static void mxser_disable_must_enchance_mode(unsigned long baseio)
outb(efr, baseio + MOXA_MUST_EFR_REGISTER); outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
outb(oldlcr, baseio + UART_LCR); outb(oldlcr, baseio + UART_LCR);
} }
#endif
static void mxser_set_must_xon1_value(unsigned long baseio, u8 value) static void mxser_set_must_xon1_value(unsigned long baseio, u8 value)
{ {
...@@ -388,6 +390,7 @@ static void mxser_set_must_enum_value(unsigned long baseio, u8 value) ...@@ -388,6 +390,7 @@ static void mxser_set_must_enum_value(unsigned long baseio, u8 value)
outb(oldlcr, baseio + UART_LCR); outb(oldlcr, baseio + UART_LCR);
} }
#ifdef CONFIG_PCI
static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
{ {
u8 oldlcr; u8 oldlcr;
...@@ -404,6 +407,7 @@ static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId) ...@@ -404,6 +407,7 @@ static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
*pId = inb(baseio + MOXA_MUST_HWID_REGISTER); *pId = inb(baseio + MOXA_MUST_HWID_REGISTER);
outb(oldlcr, baseio + UART_LCR); outb(oldlcr, baseio + UART_LCR);
} }
#endif
static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio) static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio)
{ {
......
...@@ -6,5 +6,5 @@ ...@@ -6,5 +6,5 @@
obj-$(CONFIG_IPWIRELESS) += ipwireless.o obj-$(CONFIG_IPWIRELESS) += ipwireless.o
ipwireless-objs := hardware.o main.o network.o tty.o ipwireless-y := hardware.o main.o network.o tty.o
...@@ -613,6 +613,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -613,6 +613,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case PPGETTIME: case PPGETTIME:
to_jiffies = pp->pdev->timeout; to_jiffies = pp->pdev->timeout;
memset(&par_timeout, 0, sizeof(par_timeout));
par_timeout.tv_sec = to_jiffies / HZ; par_timeout.tv_sec = to_jiffies / HZ;
par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ);
if (copy_to_user (argp, &par_timeout, sizeof(struct timeval))) if (copy_to_user (argp, &par_timeout, sizeof(struct timeval)))
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <linux/time.h> #include <linux/time.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/ramoops.h>
#define RAMOOPS_KERNMSG_HDR "====" #define RAMOOPS_KERNMSG_HDR "===="
#define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval)) #define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval))
...@@ -91,11 +93,17 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, ...@@ -91,11 +93,17 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
cxt->count = (cxt->count + 1) % cxt->max_count; cxt->count = (cxt->count + 1) % cxt->max_count;
} }
static int __init ramoops_init(void) static int __init ramoops_probe(struct platform_device *pdev)
{ {
struct ramoops_platform_data *pdata = pdev->dev.platform_data;
struct ramoops_context *cxt = &oops_cxt; struct ramoops_context *cxt = &oops_cxt;
int err = -EINVAL; int err = -EINVAL;
if (pdata) {
mem_size = pdata->mem_size;
mem_address = pdata->mem_address;
}
if (!mem_size) { if (!mem_size) {
printk(KERN_ERR "ramoops: invalid size specification"); printk(KERN_ERR "ramoops: invalid size specification");
goto fail3; goto fail3;
...@@ -142,7 +150,7 @@ static int __init ramoops_init(void) ...@@ -142,7 +150,7 @@ static int __init ramoops_init(void)
return err; return err;
} }
static void __exit ramoops_exit(void) static int __exit ramoops_remove(struct platform_device *pdev)
{ {
struct ramoops_context *cxt = &oops_cxt; struct ramoops_context *cxt = &oops_cxt;
...@@ -151,8 +159,26 @@ static void __exit ramoops_exit(void) ...@@ -151,8 +159,26 @@ static void __exit ramoops_exit(void)
iounmap(cxt->virt_addr); iounmap(cxt->virt_addr);
release_mem_region(cxt->phys_addr, cxt->size); release_mem_region(cxt->phys_addr, cxt->size);
return 0;
} }
static struct platform_driver ramoops_driver = {
.remove = __exit_p(ramoops_remove),
.driver = {
.name = "ramoops",
.owner = THIS_MODULE,
},
};
static int __init ramoops_init(void)
{
return platform_driver_probe(&ramoops_driver, ramoops_probe);
}
static void __exit ramoops_exit(void)
{
platform_driver_unregister(&ramoops_driver);
}
module_init(ramoops_init); module_init(ramoops_init);
module_exit(ramoops_exit); module_exit(ramoops_exit);
......
...@@ -8,5 +8,5 @@ ...@@ -8,5 +8,5 @@
obj-$(CONFIG_RIO) += rio.o obj-$(CONFIG_RIO) += rio.o
rio-objs := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \ rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
rioparam.o rioroute.o riotable.o riotty.o rioparam.o rioroute.o riotable.o riotty.o
...@@ -2345,7 +2345,7 @@ static int __init rp_init(void) ...@@ -2345,7 +2345,7 @@ static int __init rp_init(void)
ret = tty_register_driver(rocket_driver); ret = tty_register_driver(rocket_driver);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "Couldn't install tty RocketPort driver\n"); printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
goto err_tty; goto err_controller;
} }
#ifdef ROCKET_DEBUG_OPEN #ifdef ROCKET_DEBUG_OPEN
...@@ -2380,6 +2380,9 @@ static int __init rp_init(void) ...@@ -2380,6 +2380,9 @@ static int __init rp_init(void)
return 0; return 0;
err_ttyu: err_ttyu:
tty_unregister_driver(rocket_driver); tty_unregister_driver(rocket_driver);
err_controller:
if (controller)
release_region(controller, 4);
err_tty: err_tty:
put_tty_driver(rocket_driver); put_tty_driver(rocket_driver);
err: err:
......
...@@ -301,6 +301,8 @@ struct slgt_info { ...@@ -301,6 +301,8 @@ struct slgt_info {
unsigned int rx_pio; unsigned int rx_pio;
unsigned int if_mode; unsigned int if_mode;
unsigned int base_clock; unsigned int base_clock;
unsigned int xsync;
unsigned int xctrl;
/* device status */ /* device status */
...@@ -405,6 +407,8 @@ static MGSL_PARAMS default_params = { ...@@ -405,6 +407,8 @@ static MGSL_PARAMS default_params = {
#define TDCSR 0x94 /* tx DMA control/status */ #define TDCSR 0x94 /* tx DMA control/status */
#define RDDAR 0x98 /* rx DMA descriptor address */ #define RDDAR 0x98 /* rx DMA descriptor address */
#define TDDAR 0x9c /* tx DMA descriptor address */ #define TDDAR 0x9c /* tx DMA descriptor address */
#define XSR 0x40 /* extended sync pattern */
#define XCR 0x44 /* extended control */
#define RXIDLE BIT14 #define RXIDLE BIT14
#define RXBREAK BIT14 #define RXBREAK BIT14
...@@ -517,6 +521,10 @@ static int set_interface(struct slgt_info *info, int if_mode); ...@@ -517,6 +521,10 @@ static int set_interface(struct slgt_info *info, int if_mode);
static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
static int get_xsync(struct slgt_info *info, int __user *if_mode);
static int set_xsync(struct slgt_info *info, int if_mode);
static int get_xctrl(struct slgt_info *info, int __user *if_mode);
static int set_xctrl(struct slgt_info *info, int if_mode);
/* /*
* driver functions * driver functions
...@@ -1056,6 +1064,14 @@ static int ioctl(struct tty_struct *tty, struct file *file, ...@@ -1056,6 +1064,14 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return get_gpio(info, argp); return get_gpio(info, argp);
case MGSL_IOCWAITGPIO: case MGSL_IOCWAITGPIO:
return wait_gpio(info, argp); return wait_gpio(info, argp);
case MGSL_IOCGXSYNC:
return get_xsync(info, argp);
case MGSL_IOCSXSYNC:
return set_xsync(info, (int)arg);
case MGSL_IOCGXCTRL:
return get_xctrl(info, argp);
case MGSL_IOCSXCTRL:
return set_xctrl(info, (int)arg);
} }
mutex_lock(&info->port.mutex); mutex_lock(&info->port.mutex);
switch (cmd) { switch (cmd) {
...@@ -1132,6 +1148,7 @@ static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *us ...@@ -1132,6 +1148,7 @@ static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *us
struct MGSL_PARAMS32 tmp_params; struct MGSL_PARAMS32 tmp_params;
DBGINFO(("%s get_params32\n", info->device_name)); DBGINFO(("%s get_params32\n", info->device_name));
memset(&tmp_params, 0, sizeof(tmp_params));
tmp_params.mode = (compat_ulong_t)info->params.mode; tmp_params.mode = (compat_ulong_t)info->params.mode;
tmp_params.loopback = info->params.loopback; tmp_params.loopback = info->params.loopback;
tmp_params.flags = info->params.flags; tmp_params.flags = info->params.flags;
...@@ -1212,12 +1229,16 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1212,12 +1229,16 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCSGPIO: case MGSL_IOCSGPIO:
case MGSL_IOCGGPIO: case MGSL_IOCGGPIO:
case MGSL_IOCWAITGPIO: case MGSL_IOCWAITGPIO:
case MGSL_IOCGXSYNC:
case MGSL_IOCGXCTRL:
case MGSL_IOCSTXIDLE: case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE: case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE: case MGSL_IOCRXENABLE:
case MGSL_IOCTXABORT: case MGSL_IOCTXABORT:
case TIOCMIWAIT: case TIOCMIWAIT:
case MGSL_IOCSIF: case MGSL_IOCSIF:
case MGSL_IOCSXSYNC:
case MGSL_IOCSXCTRL:
rc = ioctl(tty, file, cmd, arg); rc = ioctl(tty, file, cmd, arg);
break; break;
} }
...@@ -1617,6 +1638,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -1617,6 +1638,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (cmd != SIOCWANDEV) if (cmd != SIOCWANDEV)
return hdlc_ioctl(dev, ifr, cmd); return hdlc_ioctl(dev, ifr, cmd);
memset(&new_line, 0, sizeof(new_line));
switch(ifr->ifr_settings.type) { switch(ifr->ifr_settings.type) {
case IF_GET_IFACE: /* return current sync_serial_settings */ case IF_GET_IFACE: /* return current sync_serial_settings */
...@@ -1958,6 +1981,7 @@ static void bh_handler(struct work_struct *work) ...@@ -1958,6 +1981,7 @@ static void bh_handler(struct work_struct *work)
case MGSL_MODE_RAW: case MGSL_MODE_RAW:
case MGSL_MODE_MONOSYNC: case MGSL_MODE_MONOSYNC:
case MGSL_MODE_BISYNC: case MGSL_MODE_BISYNC:
case MGSL_MODE_XSYNC:
while(rx_get_buf(info)); while(rx_get_buf(info));
break; break;
} }
...@@ -2357,26 +2381,27 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id) ...@@ -2357,26 +2381,27 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level)); DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
spin_lock(&info->lock);
while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
info->irq_occurred = true; info->irq_occurred = true;
for(i=0; i < info->port_count ; i++) { for(i=0; i < info->port_count ; i++) {
if (info->port_array[i] == NULL) if (info->port_array[i] == NULL)
continue; continue;
spin_lock(&info->port_array[i]->lock);
if (gsr & (BIT8 << i)) if (gsr & (BIT8 << i))
isr_serial(info->port_array[i]); isr_serial(info->port_array[i]);
if (gsr & (BIT16 << (i*2))) if (gsr & (BIT16 << (i*2)))
isr_rdma(info->port_array[i]); isr_rdma(info->port_array[i]);
if (gsr & (BIT17 << (i*2))) if (gsr & (BIT17 << (i*2)))
isr_tdma(info->port_array[i]); isr_tdma(info->port_array[i]);
spin_unlock(&info->port_array[i]->lock);
} }
} }
if (info->gpio_present) { if (info->gpio_present) {
unsigned int state; unsigned int state;
unsigned int changed; unsigned int changed;
spin_lock(&info->lock);
while ((changed = rd_reg32(info, IOSR)) != 0) { while ((changed = rd_reg32(info, IOSR)) != 0) {
DBGISR(("%s iosr=%08x\n", info->device_name, changed)); DBGISR(("%s iosr=%08x\n", info->device_name, changed));
/* read latched state of GPIO signals */ /* read latched state of GPIO signals */
...@@ -2388,22 +2413,24 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id) ...@@ -2388,22 +2413,24 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
isr_gpio(info->port_array[i], changed, state); isr_gpio(info->port_array[i], changed, state);
} }
} }
spin_unlock(&info->lock);
} }
for(i=0; i < info->port_count ; i++) { for(i=0; i < info->port_count ; i++) {
struct slgt_info *port = info->port_array[i]; struct slgt_info *port = info->port_array[i];
if (port == NULL)
if (port && (port->port.count || port->netcount) && continue;
spin_lock(&port->lock);
if ((port->port.count || port->netcount) &&
port->pending_bh && !port->bh_running && port->pending_bh && !port->bh_running &&
!port->bh_requested) { !port->bh_requested) {
DBGISR(("%s bh queued\n", port->device_name)); DBGISR(("%s bh queued\n", port->device_name));
schedule_work(&port->task); schedule_work(&port->task);
port->bh_requested = true; port->bh_requested = true;
} }
spin_unlock(&port->lock);
} }
spin_unlock(&info->lock);
DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level)); DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2883,6 +2910,69 @@ static int set_interface(struct slgt_info *info, int if_mode) ...@@ -2883,6 +2910,69 @@ static int set_interface(struct slgt_info *info, int if_mode)
return 0; return 0;
} }
static int get_xsync(struct slgt_info *info, int __user *xsync)
{
DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync));
if (put_user(info->xsync, xsync))
return -EFAULT;
return 0;
}
/*
* set extended sync pattern (1 to 4 bytes) for extended sync mode
*
* sync pattern is contained in least significant bytes of value
* most significant byte of sync pattern is oldest (1st sent/detected)
*/
static int set_xsync(struct slgt_info *info, int xsync)
{
unsigned long flags;
DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync));
spin_lock_irqsave(&info->lock, flags);
info->xsync = xsync;
wr_reg32(info, XSR, xsync);
spin_unlock_irqrestore(&info->lock, flags);
return 0;
}
static int get_xctrl(struct slgt_info *info, int __user *xctrl)
{
DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl));
if (put_user(info->xctrl, xctrl))
return -EFAULT;
return 0;
}
/*
* set extended control options
*
* xctrl[31:19] reserved, must be zero
* xctrl[18:17] extended sync pattern length in bytes
* 00 = 1 byte in xsr[7:0]
* 01 = 2 bytes in xsr[15:0]
* 10 = 3 bytes in xsr[23:0]
* 11 = 4 bytes in xsr[31:0]
* xctrl[16] 1 = enable terminal count, 0=disabled
* xctrl[15:0] receive terminal count for fixed length packets
* value is count minus one (0 = 1 byte packet)
* when terminal count is reached, receiver
* automatically returns to hunt mode and receive
* FIFO contents are flushed to DMA buffers with
* end of frame (EOF) status
*/
static int set_xctrl(struct slgt_info *info, int xctrl)
{
unsigned long flags;
DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl));
spin_lock_irqsave(&info->lock, flags);
info->xctrl = xctrl;
wr_reg32(info, XCR, xctrl);
spin_unlock_irqrestore(&info->lock, flags);
return 0;
}
/* /*
* set general purpose IO pin state and direction * set general purpose IO pin state and direction
* *
...@@ -2906,7 +2996,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) ...@@ -2906,7 +2996,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
info->device_name, gpio.state, gpio.smask, info->device_name, gpio.state, gpio.smask,
gpio.dir, gpio.dmask)); gpio.dir, gpio.dmask));
spin_lock_irqsave(&info->lock,flags); spin_lock_irqsave(&info->port_array[0]->lock, flags);
if (gpio.dmask) { if (gpio.dmask) {
data = rd_reg32(info, IODR); data = rd_reg32(info, IODR);
data |= gpio.dmask & gpio.dir; data |= gpio.dmask & gpio.dir;
...@@ -2919,7 +3009,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) ...@@ -2919,7 +3009,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
data &= ~(gpio.smask & ~gpio.state); data &= ~(gpio.smask & ~gpio.state);
wr_reg32(info, IOVR, data); wr_reg32(info, IOVR, data);
} }
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
return 0; return 0;
} }
...@@ -3020,7 +3110,7 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) ...@@ -3020,7 +3110,7 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
return -EINVAL; return -EINVAL;
init_cond_wait(&wait, gpio.smask); init_cond_wait(&wait, gpio.smask);
spin_lock_irqsave(&info->lock, flags); spin_lock_irqsave(&info->port_array[0]->lock, flags);
/* enable interrupts for watched pins */ /* enable interrupts for watched pins */
wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
/* get current pin states */ /* get current pin states */
...@@ -3032,20 +3122,20 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) ...@@ -3032,20 +3122,20 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
} else { } else {
/* wait for target state */ /* wait for target state */
add_cond_wait(&info->gpio_wait_q, &wait); add_cond_wait(&info->gpio_wait_q, &wait);
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
schedule(); schedule();
if (signal_pending(current)) if (signal_pending(current))
rc = -ERESTARTSYS; rc = -ERESTARTSYS;
else else
gpio.state = wait.data; gpio.state = wait.data;
spin_lock_irqsave(&info->lock, flags); spin_lock_irqsave(&info->port_array[0]->lock, flags);
remove_cond_wait(&info->gpio_wait_q, &wait); remove_cond_wait(&info->gpio_wait_q, &wait);
} }
/* disable all GPIO interrupts if no waiting processes */ /* disable all GPIO interrupts if no waiting processes */
if (info->gpio_wait_q == NULL) if (info->gpio_wait_q == NULL)
wr_reg32(info, IOER, 0); wr_reg32(info, IOER, 0);
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
rc = -EFAULT; rc = -EFAULT;
...@@ -3578,7 +3668,6 @@ static void device_init(int adapter_num, struct pci_dev *pdev) ...@@ -3578,7 +3668,6 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
/* copy resource information from first port to others */ /* copy resource information from first port to others */
for (i = 1; i < port_count; ++i) { for (i = 1; i < port_count; ++i) {
port_array[i]->lock = port_array[0]->lock;
port_array[i]->irq_level = port_array[0]->irq_level; port_array[i]->irq_level = port_array[0]->irq_level;
port_array[i]->reg_addr = port_array[0]->reg_addr; port_array[i]->reg_addr = port_array[0]->reg_addr;
alloc_dma_bufs(port_array[i]); alloc_dma_bufs(port_array[i]);
...@@ -3763,7 +3852,9 @@ module_exit(slgt_exit); ...@@ -3763,7 +3852,9 @@ module_exit(slgt_exit);
#define CALC_REGADDR() \ #define CALC_REGADDR() \
unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
if (addr >= 0x80) \ if (addr >= 0x80) \
reg_addr += (info->port_num) * 32; reg_addr += (info->port_num) * 32; \
else if (addr >= 0x40) \
reg_addr += (info->port_num) * 16;
static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) static __u8 rd_reg8(struct slgt_info *info, unsigned int addr)
{ {
...@@ -4182,7 +4273,13 @@ static void sync_mode(struct slgt_info *info) ...@@ -4182,7 +4273,13 @@ static void sync_mode(struct slgt_info *info)
/* TCR (tx control) /* TCR (tx control)
* *
* 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync * 15..13 mode
* 000=HDLC/SDLC
* 001=raw bit synchronous
* 010=asynchronous/isochronous
* 011=monosync byte synchronous
* 100=bisync byte synchronous
* 101=xsync byte synchronous
* 12..10 encoding * 12..10 encoding
* 09 CRC enable * 09 CRC enable
* 08 CRC32 * 08 CRC32
...@@ -4197,6 +4294,9 @@ static void sync_mode(struct slgt_info *info) ...@@ -4197,6 +4294,9 @@ static void sync_mode(struct slgt_info *info)
val = BIT2; val = BIT2;
switch(info->params.mode) { switch(info->params.mode) {
case MGSL_MODE_XSYNC:
val |= BIT15 + BIT13;
break;
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
case MGSL_MODE_BISYNC: val |= BIT15; break; case MGSL_MODE_BISYNC: val |= BIT15; break;
case MGSL_MODE_RAW: val |= BIT13; break; case MGSL_MODE_RAW: val |= BIT13; break;
...@@ -4251,7 +4351,13 @@ static void sync_mode(struct slgt_info *info) ...@@ -4251,7 +4351,13 @@ static void sync_mode(struct slgt_info *info)
/* RCR (rx control) /* RCR (rx control)
* *
* 15..13 mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync * 15..13 mode
* 000=HDLC/SDLC
* 001=raw bit synchronous
* 010=asynchronous/isochronous
* 011=monosync byte synchronous
* 100=bisync byte synchronous
* 101=xsync byte synchronous
* 12..10 encoding * 12..10 encoding
* 09 CRC enable * 09 CRC enable
* 08 CRC32 * 08 CRC32
...@@ -4263,6 +4369,9 @@ static void sync_mode(struct slgt_info *info) ...@@ -4263,6 +4369,9 @@ static void sync_mode(struct slgt_info *info)
val = 0; val = 0;
switch(info->params.mode) { switch(info->params.mode) {
case MGSL_MODE_XSYNC:
val |= BIT15 + BIT13;
break;
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
case MGSL_MODE_BISYNC: val |= BIT15; break; case MGSL_MODE_BISYNC: val |= BIT15; break;
case MGSL_MODE_RAW: val |= BIT13; break; case MGSL_MODE_RAW: val |= BIT13; break;
...@@ -4679,6 +4788,7 @@ static bool rx_get_buf(struct slgt_info *info) ...@@ -4679,6 +4788,7 @@ static bool rx_get_buf(struct slgt_info *info)
switch(info->params.mode) { switch(info->params.mode) {
case MGSL_MODE_MONOSYNC: case MGSL_MODE_MONOSYNC:
case MGSL_MODE_BISYNC: case MGSL_MODE_BISYNC:
case MGSL_MODE_XSYNC:
/* ignore residue in byte synchronous modes */ /* ignore residue in byte synchronous modes */
if (desc_residue(info->rbufs[i])) if (desc_residue(info->rbufs[i]))
count--; count--;
......
...@@ -503,6 +503,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -503,6 +503,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
struct kbd_struct * kbd; struct kbd_struct * kbd;
unsigned int console; unsigned int console;
unsigned char ucval; unsigned char ucval;
unsigned int uival;
void __user *up = (void __user *)arg; void __user *up = (void __user *)arg;
int i, perm; int i, perm;
int ret = 0; int ret = 0;
...@@ -657,7 +658,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -657,7 +658,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
break; break;
case KDGETMODE: case KDGETMODE:
ucval = vc->vc_mode; uival = vc->vc_mode;
goto setint; goto setint;
case KDMAPDISP: case KDMAPDISP:
...@@ -695,7 +696,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -695,7 +696,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
break; break;
case KDGKBMODE: case KDGKBMODE:
ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : uival = ((kbd->kbdmode == VC_RAW) ? K_RAW :
(kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
(kbd->kbdmode == VC_UNICODE) ? K_UNICODE : (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
K_XLATE); K_XLATE);
...@@ -717,9 +718,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -717,9 +718,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
break; break;
case KDGKBMETA: case KDGKBMETA:
ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); uival = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
setint: setint:
ret = put_user(ucval, (int __user *)arg); ret = put_user(uival, (int __user *)arg);
break; break;
case KDGETKEYCODE: case KDGETKEYCODE:
...@@ -949,7 +950,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -949,7 +950,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
for (i = 0; i < MAX_NR_CONSOLES; ++i) for (i = 0; i < MAX_NR_CONSOLES; ++i)
if (! VT_IS_IN_USE(i)) if (! VT_IS_IN_USE(i))
break; break;
ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; uival = i < MAX_NR_CONSOLES ? (i+1) : -1;
goto setint; goto setint;
/* /*
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ctype.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
...@@ -361,6 +362,33 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy) ...@@ -361,6 +362,33 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
} }
} }
static void __init print_filtered(const char *info)
{
const char *p;
if (!info)
return;
for (p = info; *p; p++)
if (isprint(*p))
printk(KERN_CONT "%c", *p);
else
printk(KERN_CONT "\\x%02x", *p & 0xff);
}
static void __init dmi_dump_ids(void)
{
printk(KERN_DEBUG "DMI: ");
print_filtered(dmi_get_system_info(DMI_BOARD_NAME));
printk(KERN_CONT "/");
print_filtered(dmi_get_system_info(DMI_PRODUCT_NAME));
printk(KERN_CONT ", BIOS ");
print_filtered(dmi_get_system_info(DMI_BIOS_VERSION));
printk(KERN_CONT " ");
print_filtered(dmi_get_system_info(DMI_BIOS_DATE));
printk(KERN_CONT "\n");
}
static int __init dmi_present(const char __iomem *p) static int __init dmi_present(const char __iomem *p)
{ {
u8 buf[15]; u8 buf[15];
...@@ -381,8 +409,10 @@ static int __init dmi_present(const char __iomem *p) ...@@ -381,8 +409,10 @@ static int __init dmi_present(const char __iomem *p)
buf[14] >> 4, buf[14] & 0xF); buf[14] >> 4, buf[14] & 0xF);
else else
printk(KERN_INFO "DMI present.\n"); printk(KERN_INFO "DMI present.\n");
if (dmi_walk_early(dmi_decode) == 0) if (dmi_walk_early(dmi_decode) == 0) {
dmi_dump_ids();
return 0; return 0;
}
} }
return 1; return 1;
} }
......
/*
* 74Hx164 - Generic serial-in/parallel-out 8-bits shift register GPIO driver
*
* Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2010 Miguel Gaio <miguel.gaio@efixo.com>
*
* 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/init.h>
#include <linux/mutex.h>
#include <linux/spi/spi.h>
#include <linux/spi/74x164.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#define GEN_74X164_GPIO_COUNT 8
struct gen_74x164_chip {
struct spi_device *spi;
struct gpio_chip gpio_chip;
struct mutex lock;
u8 port_config;
};
static void gen_74x164_set_value(struct gpio_chip *, unsigned, int);
static struct gen_74x164_chip *gpio_to_chip(struct gpio_chip *gc)
{
return container_of(gc, struct gen_74x164_chip, gpio_chip);
}
static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
{
return spi_write(chip->spi,
&chip->port_config, sizeof(chip->port_config));
}
static int gen_74x164_direction_output(struct gpio_chip *gc,
unsigned offset, int val)
{
gen_74x164_set_value(gc, offset, val);
return 0;
}
static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
{
struct gen_74x164_chip *chip = gpio_to_chip(gc);
int ret;
mutex_lock(&chip->lock);
ret = (chip->port_config >> offset) & 0x1;
mutex_unlock(&chip->lock);
return ret;
}
static void gen_74x164_set_value(struct gpio_chip *gc,
unsigned offset, int val)
{
struct gen_74x164_chip *chip = gpio_to_chip(gc);
mutex_lock(&chip->lock);
if (val)
chip->port_config |= (1 << offset);
else
chip->port_config &= ~(1 << offset);
__gen_74x164_write_config(chip);
mutex_unlock(&chip->lock);
}
static int __devinit gen_74x164_probe(struct spi_device *spi)
{
struct gen_74x164_chip *chip;
struct gen_74x164_chip_platform_data *pdata;
int ret;
pdata = spi->dev.platform_data;
if (!pdata || !pdata->base) {
dev_dbg(&spi->dev, "incorrect or missing platform data\n");
return -EINVAL;
}
/*
* bits_per_word cannot be configured in platform data
*/
spi->bits_per_word = 8;
ret = spi_setup(spi);
if (ret < 0)
return ret;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
mutex_init(&chip->lock);
dev_set_drvdata(&spi->dev, chip);
chip->spi = spi;
chip->gpio_chip.label = GEN_74X164_DRIVER_NAME,
chip->gpio_chip.direction_output = gen_74x164_direction_output;
chip->gpio_chip.get = gen_74x164_get_value;
chip->gpio_chip.set = gen_74x164_set_value;
chip->gpio_chip.base = pdata->base;
chip->gpio_chip.ngpio = GEN_74X164_GPIO_COUNT;
chip->gpio_chip.can_sleep = 1;
chip->gpio_chip.dev = &spi->dev;
chip->gpio_chip.owner = THIS_MODULE;
ret = __gen_74x164_write_config(chip);
if (ret) {
dev_err(&spi->dev, "Failed writing: %d\n", ret);
goto exit_destroy;
}
ret = gpiochip_add(&chip->gpio_chip);
if (ret)
goto exit_destroy;
return ret;
exit_destroy:
dev_set_drvdata(&spi->dev, NULL);
mutex_destroy(&chip->lock);
kfree(chip);
return ret;
}
static int gen_74x164_remove(struct spi_device *spi)
{
struct gen_74x164_chip *chip;
int ret;
chip = dev_get_drvdata(&spi->dev);
if (chip == NULL)
return -ENODEV;
dev_set_drvdata(&spi->dev, NULL);
ret = gpiochip_remove(&chip->gpio_chip);
if (!ret) {
mutex_destroy(&chip->lock);
kfree(chip);
} else
dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
ret);
return ret;
}
static struct spi_driver gen_74x164_driver = {
.driver = {
.name = GEN_74X164_DRIVER_NAME,
.owner = THIS_MODULE,
},
.probe = gen_74x164_probe,
.remove = __devexit_p(gen_74x164_remove),
};
static int __init gen_74x164_init(void)
{
return spi_register_driver(&gen_74x164_driver);
}
subsys_initcall(gen_74x164_init);
static void __exit gen_74x164_exit(void)
{
spi_unregister_driver(&gen_74x164_driver);
}
module_exit(gen_74x164_exit);
MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
MODULE_DESCRIPTION("GPIO expander driver for 74X164 8-bits shift register");
MODULE_LICENSE("GPL v2");
...@@ -70,6 +70,11 @@ config GPIO_MAX730X ...@@ -70,6 +70,11 @@ config GPIO_MAX730X
comment "Memory mapped GPIO expanders:" comment "Memory mapped GPIO expanders:"
config GPIO_BASIC_MMIO
tristate "Basic memory-mapped GPIO controllers support"
help
Say yes here to support basic memory-mapped GPIO controllers.
config GPIO_IT8761E config GPIO_IT8761E
tristate "IT8761E GPIO support" tristate "IT8761E GPIO support"
depends on GPIOLIB depends on GPIOLIB
...@@ -267,6 +272,13 @@ config GPIO_ADP5588 ...@@ -267,6 +272,13 @@ config GPIO_ADP5588
To compile this driver as a module, choose M here: the module will be To compile this driver as a module, choose M here: the module will be
called adp5588-gpio. called adp5588-gpio.
config GPIO_ADP5588_IRQ
bool "Interrupt controller support for ADP5588"
depends on GPIO_ADP5588=y
help
Say yes here to enable the adp5588 to be used as an interrupt
controller. It requires the driver to be built in the kernel.
comment "PCI GPIO expanders:" comment "PCI GPIO expanders:"
config GPIO_CS5535 config GPIO_CS5535
...@@ -301,6 +313,14 @@ config GPIO_LANGWELL ...@@ -301,6 +313,14 @@ config GPIO_LANGWELL
help help
Say Y here to support Intel Langwell/Penwell GPIO. Say Y here to support Intel Langwell/Penwell GPIO.
config GPIO_PCH
tristate "PCH GPIO of Intel Topcliff"
depends on PCI
help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH GPIO device.
config GPIO_TIMBERDALE config GPIO_TIMBERDALE
bool "Support for timberdale GPIO IP" bool "Support for timberdale GPIO IP"
depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM
...@@ -339,6 +359,14 @@ config GPIO_MC33880 ...@@ -339,6 +359,14 @@ config GPIO_MC33880
SPI driver for Freescale MC33880 high-side/low-side switch. SPI driver for Freescale MC33880 high-side/low-side switch.
This provides GPIO interface supporting inputs and outputs. This provides GPIO interface supporting inputs and outputs.
config GPIO_74X164
tristate "74x164 serial-in/parallel-out 8-bits shift register"
depends on SPI_MASTER
help
Platform driver for 74x164 compatible serial-in/parallel-out
8-outputs shift registers. This driver can be used to provide access
to more gpio outputs.
comment "AC97 GPIO expanders:" comment "AC97 GPIO expanders:"
config GPIO_UCB1400 config GPIO_UCB1400
......
...@@ -10,6 +10,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o ...@@ -10,6 +10,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o
obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
obj-$(CONFIG_GPIO_BASIC_MMIO) += basic_mmio_gpio.o
obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o
obj-$(CONFIG_GPIO_MAX730X) += max730x.o obj-$(CONFIG_GPIO_MAX730X) += max730x.o
obj-$(CONFIG_GPIO_MAX7300) += max7300.o obj-$(CONFIG_GPIO_MAX7300) += max7300.o
...@@ -17,8 +18,10 @@ obj-$(CONFIG_GPIO_MAX7301) += max7301.o ...@@ -17,8 +18,10 @@ obj-$(CONFIG_GPIO_MAX7301) += max7301.o
obj-$(CONFIG_GPIO_MAX732X) += max732x.o obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MC33880) += mc33880.o obj-$(CONFIG_GPIO_MC33880) += mc33880.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_74X164) += 74x164.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
obj-$(CONFIG_GPIO_PL061) += pl061.o obj-$(CONFIG_GPIO_PL061) += pl061.o
obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o
......
/* /*
* GPIO Chip driver for Analog Devices * GPIO Chip driver for Analog Devices
* ADP5588 I/O Expander and QWERTY Keypad Controller * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller
* *
* Copyright 2009 Analog Devices Inc. * Copyright 2009-2010 Analog Devices Inc.
* *
* Licensed under the GPL-2 or later. * Licensed under the GPL-2 or later.
*/ */
...@@ -13,21 +13,34 @@ ...@@ -13,21 +13,34 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/i2c/adp5588.h> #include <linux/i2c/adp5588.h>
#define DRV_NAME "adp5588-gpio" #define DRV_NAME "adp5588-gpio"
#define MAXGPIO 18
#define ADP_BANK(offs) ((offs) >> 3) /*
#define ADP_BIT(offs) (1u << ((offs) & 0x7)) * Early pre 4.0 Silicon required to delay readout by at least 25ms,
* since the Event Counter Register updated 25ms after the interrupt
* asserted.
*/
#define WA_DELAYED_READOUT_REVID(rev) ((rev) < 4)
struct adp5588_gpio { struct adp5588_gpio {
struct i2c_client *client; struct i2c_client *client;
struct gpio_chip gpio_chip; struct gpio_chip gpio_chip;
struct mutex lock; /* protect cached dir, dat_out */ struct mutex lock; /* protect cached dir, dat_out */
/* protect serialized access to the interrupt controller bus */
struct mutex irq_lock;
unsigned gpio_start; unsigned gpio_start;
unsigned irq_base;
uint8_t dat_out[3]; uint8_t dat_out[3];
uint8_t dir[3]; uint8_t dir[3];
uint8_t int_lvl[3];
uint8_t int_en[3];
uint8_t irq_mask[3];
uint8_t irq_stat[3];
}; };
static int adp5588_gpio_read(struct i2c_client *client, u8 reg) static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
...@@ -55,8 +68,8 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) ...@@ -55,8 +68,8 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
struct adp5588_gpio *dev = struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip); container_of(chip, struct adp5588_gpio, gpio_chip);
return !!(adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + ADP_BANK(off)) return !!(adp5588_gpio_read(dev->client,
& ADP_BIT(off)); GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
} }
static void adp5588_gpio_set_value(struct gpio_chip *chip, static void adp5588_gpio_set_value(struct gpio_chip *chip,
...@@ -66,8 +79,8 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip, ...@@ -66,8 +79,8 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
struct adp5588_gpio *dev = struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip); container_of(chip, struct adp5588_gpio, gpio_chip);
bank = ADP_BANK(off); bank = ADP5588_BANK(off);
bit = ADP_BIT(off); bit = ADP5588_BIT(off);
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
if (val) if (val)
...@@ -87,10 +100,10 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) ...@@ -87,10 +100,10 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
struct adp5588_gpio *dev = struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip); container_of(chip, struct adp5588_gpio, gpio_chip);
bank = ADP_BANK(off); bank = ADP5588_BANK(off);
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
dev->dir[bank] &= ~ADP_BIT(off); dev->dir[bank] &= ~ADP5588_BIT(off);
ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]); ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
...@@ -105,8 +118,8 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, ...@@ -105,8 +118,8 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
struct adp5588_gpio *dev = struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip); container_of(chip, struct adp5588_gpio, gpio_chip);
bank = ADP_BANK(off); bank = ADP5588_BANK(off);
bit = ADP_BIT(off); bit = ADP5588_BIT(off);
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
dev->dir[bank] |= bit; dev->dir[bank] |= bit;
...@@ -125,6 +138,213 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, ...@@ -125,6 +138,213 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
return ret; return ret;
} }
#ifdef CONFIG_GPIO_ADP5588_IRQ
static int adp5588_gpio_to_irq(struct gpio_chip *chip, unsigned off)
{
struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip);
return dev->irq_base + off;
}
static void adp5588_irq_bus_lock(unsigned int irq)
{
struct adp5588_gpio *dev = get_irq_chip_data(irq);
mutex_lock(&dev->irq_lock);
}
/*
* genirq core code can issue chip->mask/unmask from atomic context.
* This doesn't work for slow busses where an access needs to sleep.
* bus_sync_unlock() is therefore called outside the atomic context,
* syncs the current irq mask state with the slow external controller
* and unlocks the bus.
*/
static void adp5588_irq_bus_sync_unlock(unsigned int irq)
{
struct adp5588_gpio *dev = get_irq_chip_data(irq);
int i;
for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
if (dev->int_en[i] ^ dev->irq_mask[i]) {
dev->int_en[i] = dev->irq_mask[i];
adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
dev->int_en[i]);
}
mutex_unlock(&dev->irq_lock);
}
static void adp5588_irq_mask(unsigned int irq)
{
struct adp5588_gpio *dev = get_irq_chip_data(irq);
unsigned gpio = irq - dev->irq_base;
dev->irq_mask[ADP5588_BANK(gpio)] &= ~ADP5588_BIT(gpio);
}
static void adp5588_irq_unmask(unsigned int irq)
{
struct adp5588_gpio *dev = get_irq_chip_data(irq);
unsigned gpio = irq - dev->irq_base;
dev->irq_mask[ADP5588_BANK(gpio)] |= ADP5588_BIT(gpio);
}
static int adp5588_irq_set_type(unsigned int irq, unsigned int type)
{
struct adp5588_gpio *dev = get_irq_chip_data(irq);
uint16_t gpio = irq - dev->irq_base;
unsigned bank, bit;
if ((type & IRQ_TYPE_EDGE_BOTH)) {
dev_err(&dev->client->dev, "irq %d: unsupported type %d\n",
irq, type);
return -EINVAL;
}
bank = ADP5588_BANK(gpio);
bit = ADP5588_BIT(gpio);
if (type & IRQ_TYPE_LEVEL_HIGH)
dev->int_lvl[bank] |= bit;
else if (type & IRQ_TYPE_LEVEL_LOW)
dev->int_lvl[bank] &= ~bit;
else
return -EINVAL;
adp5588_gpio_direction_input(&dev->gpio_chip, gpio);
adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
dev->int_lvl[bank]);
return 0;
}
static struct irq_chip adp5588_irq_chip = {
.name = "adp5588",
.mask = adp5588_irq_mask,
.unmask = adp5588_irq_unmask,
.bus_lock = adp5588_irq_bus_lock,
.bus_sync_unlock = adp5588_irq_bus_sync_unlock,
.set_type = adp5588_irq_set_type,
};
static int adp5588_gpio_read_intstat(struct i2c_client *client, u8 *buf)
{
int ret = i2c_smbus_read_i2c_block_data(client, GPIO_INT_STAT1, 3, buf);
if (ret < 0)
dev_err(&client->dev, "Read INT_STAT Error\n");
return ret;
}
static irqreturn_t adp5588_irq_handler(int irq, void *devid)
{
struct adp5588_gpio *dev = devid;
unsigned status, bank, bit, pending;
int ret;
status = adp5588_gpio_read(dev->client, INT_STAT);
if (status & ADP5588_GPI_INT) {
ret = adp5588_gpio_read_intstat(dev->client, dev->irq_stat);
if (ret < 0)
memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
bank++, bit = 0) {
pending = dev->irq_stat[bank] & dev->irq_mask[bank];
while (pending) {
if (pending & (1 << bit)) {
handle_nested_irq(dev->irq_base +
(bank << 3) + bit);
pending &= ~(1 << bit);
}
bit++;
}
}
}
adp5588_gpio_write(dev->client, INT_STAT, status); /* Status is W1C */
return IRQ_HANDLED;
}
static int adp5588_irq_setup(struct adp5588_gpio *dev)
{
struct i2c_client *client = dev->client;
struct adp5588_gpio_platform_data *pdata = client->dev.platform_data;
unsigned gpio;
int ret;
adp5588_gpio_write(client, CFG, ADP5588_AUTO_INC);
adp5588_gpio_write(client, INT_STAT, -1); /* status is W1C */
adp5588_gpio_read_intstat(client, dev->irq_stat); /* read to clear */
dev->irq_base = pdata->irq_base;
mutex_init(&dev->irq_lock);
for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) {
int irq = gpio + dev->irq_base;
set_irq_chip_data(irq, dev);
set_irq_chip_and_handler(irq, &adp5588_irq_chip,
handle_level_irq);
set_irq_nested_thread(irq, 1);
#ifdef CONFIG_ARM
/*
* ARM needs us to explicitly flag the IRQ as VALID,
* once we do so, it will also set the noprobe.
*/
set_irq_flags(irq, IRQF_VALID);
#else
set_irq_noprobe(irq);
#endif
}
ret = request_threaded_irq(client->irq,
NULL,
adp5588_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
dev_name(&client->dev), dev);
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
client->irq);
goto out;
}
dev->gpio_chip.to_irq = adp5588_gpio_to_irq;
adp5588_gpio_write(client, CFG,
ADP5588_AUTO_INC | ADP5588_INT_CFG | ADP5588_GPI_INT);
return 0;
out:
dev->irq_base = 0;
return ret;
}
static void adp5588_irq_teardown(struct adp5588_gpio *dev)
{
if (dev->irq_base)
free_irq(dev->client->irq, dev);
}
#else
static int adp5588_irq_setup(struct adp5588_gpio *dev)
{
struct i2c_client *client = dev->client;
dev_warn(&client->dev, "interrupt support not compiled in\n");
return 0;
}
static void adp5588_irq_teardown(struct adp5588_gpio *dev)
{
}
#endif /* CONFIG_GPIO_ADP5588_IRQ */
static int __devinit adp5588_gpio_probe(struct i2c_client *client, static int __devinit adp5588_gpio_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -160,37 +380,46 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client, ...@@ -160,37 +380,46 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client,
gc->can_sleep = 1; gc->can_sleep = 1;
gc->base = pdata->gpio_start; gc->base = pdata->gpio_start;
gc->ngpio = MAXGPIO; gc->ngpio = ADP5588_MAXGPIO;
gc->label = client->name; gc->label = client->name;
gc->owner = THIS_MODULE; gc->owner = THIS_MODULE;
mutex_init(&dev->lock); mutex_init(&dev->lock);
ret = adp5588_gpio_read(dev->client, DEV_ID); ret = adp5588_gpio_read(dev->client, DEV_ID);
if (ret < 0) if (ret < 0)
goto err; goto err;
revid = ret & ADP5588_DEVICE_ID_MASK; revid = ret & ADP5588_DEVICE_ID_MASK;
for (i = 0, ret = 0; i <= ADP_BANK(MAXGPIO); i++) { for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i); dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i);
dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i); dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0); ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
ret |= adp5588_gpio_write(client, GPIO_PULL1 + i, ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
(pdata->pullup_dis_mask >> (8 * i)) & 0xFF); (pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
if (ret) if (ret)
goto err; goto err;
} }
if (pdata->irq_base) {
if (WA_DELAYED_READOUT_REVID(revid)) {
dev_warn(&client->dev, "GPIO int not supported\n");
} else {
ret = adp5588_irq_setup(dev);
if (ret)
goto err;
}
}
ret = gpiochip_add(&dev->gpio_chip); ret = gpiochip_add(&dev->gpio_chip);
if (ret) if (ret)
goto err; goto err_irq;
dev_info(&client->dev, "gpios %d..%d on a %s Rev. %d\n", dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n",
gc->base, gc->base + gc->ngpio - 1, gc->base, gc->base + gc->ngpio - 1,
client->name, revid); pdata->irq_base, client->name, revid);
if (pdata->setup) { if (pdata->setup) {
ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
...@@ -199,8 +428,11 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client, ...@@ -199,8 +428,11 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client,
} }
i2c_set_clientdata(client, dev); i2c_set_clientdata(client, dev);
return 0; return 0;
err_irq:
adp5588_irq_teardown(dev);
err: err:
kfree(dev); kfree(dev);
return ret; return ret;
...@@ -222,6 +454,9 @@ static int __devexit adp5588_gpio_remove(struct i2c_client *client) ...@@ -222,6 +454,9 @@ static int __devexit adp5588_gpio_remove(struct i2c_client *client)
} }
} }
if (dev->irq_base)
free_irq(dev->client->irq, dev);
ret = gpiochip_remove(&dev->gpio_chip); ret = gpiochip_remove(&dev->gpio_chip);
if (ret) { if (ret) {
dev_err(&client->dev, "gpiochip_remove failed %d\n", ret); dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);
......
/*
* Driver for basic memory-mapped GPIO controllers.
*
* Copyright 2008 MontaVista Software, Inc.
* Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
*
* 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 the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`.......
* ...`` ```````..
* ..The simplest form of a GPIO controller that the driver supports is``
* `.just a single "data" register, where GPIO state can be read and/or `
* `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.```````
* `````````
___
_/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,...
__________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO .
o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
`....trivial..'~`.```.```
* ```````
* .```````~~~~`..`.``.``.
* . The driver supports `... ,..```.`~~~```````````````....````.``,,
* . big-endian notation, just`. .. A bit more sophisticated controllers ,
* . register the device with -be`. .with a pair of set/clear-bit registers ,
* `.. suffix. ```~~`````....`.` . affecting the data register and the .`
* ``.`.``...``` ```.. output pins are also supported.`
* ^^ `````.`````````.,``~``~``~~``````
* . ^^
* ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`..
* .. The expectation is that in at least some cases . ,-~~~-,
* .this will be used with roll-your-own ASIC/FPGA .` \ /
* .logic in Verilog or VHDL. ~~~`````````..`````~~` \ /
* ..````````......``````````` \o_
* |
* ^^ / \
*
* ...`````~~`.....``.`..........``````.`.``.```........``.
* ` 8, 16, 32 and 64 bits registers are supported, and``.
* . the number of GPIOs is determined by the width of ~
* .. the registers. ,............```.`.`..`.`.~~~.`.`.`~
* `.......````.```
*/
#include <linux/init.h>
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/log2.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/basic_mmio_gpio.h>
struct bgpio_chip {
struct gpio_chip gc;
void __iomem *reg_dat;
void __iomem *reg_set;
void __iomem *reg_clr;
/* Number of bits (GPIOs): <register width> * 8. */
int bits;
/*
* Some GPIO controllers work with the big-endian bits notation,
* e.g. in a 8-bits register, GPIO7 is the least significant bit.
*/
int big_endian_bits;
/*
* Used to lock bgpio_chip->data. Also, this is needed to keep
* shadowed and real data registers writes together.
*/
spinlock_t lock;
/* Shadowed data register to clear/set bits safely. */
unsigned long data;
};
static struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc)
{
return container_of(gc, struct bgpio_chip, gc);
}
static unsigned long bgpio_in(struct bgpio_chip *bgc)
{
switch (bgc->bits) {
case 8:
return __raw_readb(bgc->reg_dat);
case 16:
return __raw_readw(bgc->reg_dat);
case 32:
return __raw_readl(bgc->reg_dat);
#if BITS_PER_LONG >= 64
case 64:
return __raw_readq(bgc->reg_dat);
#endif
}
return -EINVAL;
}
static void bgpio_out(struct bgpio_chip *bgc, void __iomem *reg,
unsigned long data)
{
switch (bgc->bits) {
case 8:
__raw_writeb(data, reg);
return;
case 16:
__raw_writew(data, reg);
return;
case 32:
__raw_writel(data, reg);
return;
#if BITS_PER_LONG >= 64
case 64:
__raw_writeq(data, reg);
return;
#endif
}
}
static unsigned long bgpio_pin2mask(struct bgpio_chip *bgc, unsigned int pin)
{
if (bgc->big_endian_bits)
return 1 << (bgc->bits - 1 - pin);
else
return 1 << pin;
}
static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
return bgpio_in(bgc) & bgpio_pin2mask(bgc, gpio);
}
static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct bgpio_chip *bgc = to_bgpio_chip(gc);
unsigned long mask = bgpio_pin2mask(bgc, gpio);
unsigned long flags;
if (bgc->reg_set) {
if (val)
bgpio_out(bgc, bgc->reg_set, mask);
else
bgpio_out(bgc, bgc->reg_clr, mask);
return;
}
spin_lock_irqsave(&bgc->lock, flags);
if (val)
bgc->data |= mask;
else
bgc->data &= ~mask;
bgpio_out(bgc, bgc->reg_dat, bgc->data);
spin_unlock_irqrestore(&bgc->lock, flags);
}
static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
return 0;
}
static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{
bgpio_set(gc, gpio, val);
return 0;
}
static int __devinit bgpio_probe(struct platform_device *pdev)
{
const struct platform_device_id *platid = platform_get_device_id(pdev);
struct device *dev = &pdev->dev;
struct bgpio_pdata *pdata = dev_get_platdata(dev);
struct bgpio_chip *bgc;
struct resource *res_dat;
struct resource *res_set;
struct resource *res_clr;
resource_size_t dat_sz;
int bits;
int ret;
res_dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
if (!res_dat)
return -EINVAL;
dat_sz = resource_size(res_dat);
if (!is_power_of_2(dat_sz))
return -EINVAL;
bits = dat_sz * 8;
if (bits > BITS_PER_LONG)
return -EINVAL;
bgc = devm_kzalloc(dev, sizeof(*bgc), GFP_KERNEL);
if (!bgc)
return -ENOMEM;
bgc->reg_dat = devm_ioremap(dev, res_dat->start, dat_sz);
if (!bgc->reg_dat)
return -ENOMEM;
res_set = platform_get_resource_byname(pdev, IORESOURCE_MEM, "set");
res_clr = platform_get_resource_byname(pdev, IORESOURCE_MEM, "clr");
if (res_set && res_clr) {
if (resource_size(res_set) != resource_size(res_clr) ||
resource_size(res_set) != dat_sz)
return -EINVAL;
bgc->reg_set = devm_ioremap(dev, res_set->start, dat_sz);
bgc->reg_clr = devm_ioremap(dev, res_clr->start, dat_sz);
if (!bgc->reg_set || !bgc->reg_clr)
return -ENOMEM;
} else if (res_set || res_clr) {
return -EINVAL;
}
spin_lock_init(&bgc->lock);
bgc->bits = bits;
bgc->big_endian_bits = !strcmp(platid->name, "basic-mmio-gpio-be");
bgc->data = bgpio_in(bgc);
bgc->gc.ngpio = bits;
bgc->gc.direction_input = bgpio_dir_in;
bgc->gc.direction_output = bgpio_dir_out;
bgc->gc.get = bgpio_get;
bgc->gc.set = bgpio_set;
bgc->gc.dev = dev;
bgc->gc.label = dev_name(dev);
if (pdata)
bgc->gc.base = pdata->base;
else
bgc->gc.base = -1;
dev_set_drvdata(dev, bgc);
ret = gpiochip_add(&bgc->gc);
if (ret)
dev_err(dev, "gpiochip_add() failed: %d\n", ret);
return ret;
}
static int __devexit bgpio_remove(struct platform_device *pdev)
{
struct bgpio_chip *bgc = dev_get_drvdata(&pdev->dev);
return gpiochip_remove(&bgc->gc);
}
static const struct platform_device_id bgpio_id_table[] = {
{ "basic-mmio-gpio", },
{ "basic-mmio-gpio-be", },
{},
};
MODULE_DEVICE_TABLE(platform, bgpio_id_table);
static struct platform_driver bgpio_driver = {
.driver = {
.name = "basic-mmio-gpio",
},
.id_table = bgpio_id_table,
.probe = bgpio_probe,
.remove = __devexit_p(bgpio_remove),
};
static int __init bgpio_init(void)
{
return platform_driver_register(&bgpio_driver);
}
module_init(bgpio_init);
static void __exit bgpio_exit(void)
{
platform_driver_unregister(&bgpio_driver);
}
module_exit(bgpio_exit);
MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
MODULE_LICENSE("GPL");
...@@ -18,10 +18,12 @@ ...@@ -18,10 +18,12 @@
/* Supports: /* Supports:
* Moorestown platform Langwell chip. * Moorestown platform Langwell chip.
* Medfield platform Penwell chip. * Medfield platform Penwell chip.
* Whitney point.
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/stddef.h> #include <linux/stddef.h>
...@@ -158,15 +160,15 @@ static int lnw_irq_type(unsigned irq, unsigned type) ...@@ -158,15 +160,15 @@ static int lnw_irq_type(unsigned irq, unsigned type)
spin_unlock_irqrestore(&lnw->lock, flags); spin_unlock_irqrestore(&lnw->lock, flags);
return 0; return 0;
}; }
static void lnw_irq_unmask(unsigned irq) static void lnw_irq_unmask(unsigned irq)
{ {
}; }
static void lnw_irq_mask(unsigned irq) static void lnw_irq_mask(unsigned irq)
{ {
}; }
static struct irq_chip lnw_irqchip = { static struct irq_chip lnw_irqchip = {
.name = "LNW-GPIO", .name = "LNW-GPIO",
...@@ -300,9 +302,88 @@ static struct pci_driver lnw_gpio_driver = { ...@@ -300,9 +302,88 @@ static struct pci_driver lnw_gpio_driver = {
.probe = lnw_gpio_probe, .probe = lnw_gpio_probe,
}; };
static int __devinit wp_gpio_probe(struct platform_device *pdev)
{
struct lnw_gpio *lnw;
struct gpio_chip *gc;
struct resource *rc;
int retval = 0;
rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!rc)
return -EINVAL;
lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL);
if (!lnw) {
dev_err(&pdev->dev,
"can't allocate whitneypoint_gpio chip data\n");
return -ENOMEM;
}
lnw->reg_base = ioremap_nocache(rc->start, resource_size(rc));
if (lnw->reg_base == NULL) {
retval = -EINVAL;
goto err_kmalloc;
}
spin_lock_init(&lnw->lock);
gc = &lnw->chip;
gc->label = dev_name(&pdev->dev);
gc->owner = THIS_MODULE;
gc->direction_input = lnw_gpio_direction_input;
gc->direction_output = lnw_gpio_direction_output;
gc->get = lnw_gpio_get;
gc->set = lnw_gpio_set;
gc->to_irq = NULL;
gc->base = 0;
gc->ngpio = 64;
gc->can_sleep = 0;
retval = gpiochip_add(gc);
if (retval) {
dev_err(&pdev->dev, "whitneypoint gpiochip_add error %d\n",
retval);
goto err_ioremap;
}
platform_set_drvdata(pdev, lnw);
return 0;
err_ioremap:
iounmap(lnw->reg_base);
err_kmalloc:
kfree(lnw);
return retval;
}
static int __devexit wp_gpio_remove(struct platform_device *pdev)
{
struct lnw_gpio *lnw = platform_get_drvdata(pdev);
int err;
err = gpiochip_remove(&lnw->chip);
if (err)
dev_err(&pdev->dev, "failed to remove gpio_chip.\n");
iounmap(lnw->reg_base);
kfree(lnw);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver wp_gpio_driver = {
.probe = wp_gpio_probe,
.remove = __devexit_p(wp_gpio_remove),
.driver = {
.name = "wp_gpio",
.owner = THIS_MODULE,
},
};
static int __init lnw_gpio_init(void) static int __init lnw_gpio_init(void)
{ {
return pci_register_driver(&lnw_gpio_driver); int ret;
ret = pci_register_driver(&lnw_gpio_driver);
if (ret < 0)
return ret;
ret = platform_driver_register(&wp_gpio_driver);
if (ret < 0)
pci_unregister_driver(&lnw_gpio_driver);
return ret;
} }
device_initcall(lnw_gpio_init); device_initcall(lnw_gpio_init);
/*
* Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
*
* 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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#define PCH_GPIO_ALL_PINS 0xfff /* Mask for GPIO pins 0 to 11 */
#define GPIO_NUM_PINS 12 /* Specifies number of GPIO PINS GPIO0-GPIO11 */
struct pch_regs {
u32 ien;
u32 istatus;
u32 idisp;
u32 iclr;
u32 imask;
u32 imaskclr;
u32 po;
u32 pi;
u32 pm;
u32 im0;
u32 im1;
u32 reserved[4];
u32 reset;
};
/**
* struct pch_gpio_reg_data - The register store data.
* @po_reg: To store contents of PO register.
* @pm_reg: To store contents of PM register.
*/
struct pch_gpio_reg_data {
u32 po_reg;
u32 pm_reg;
};
/**
* struct pch_gpio - GPIO private data structure.
* @base: PCI base address of Memory mapped I/O register.
* @reg: Memory mapped PCH GPIO register list.
* @dev: Pointer to device structure.
* @gpio: Data for GPIO infrastructure.
* @pch_gpio_reg: Memory mapped Register data is saved here
* when suspend.
*/
struct pch_gpio {
void __iomem *base;
struct pch_regs __iomem *reg;
struct device *dev;
struct gpio_chip gpio;
struct pch_gpio_reg_data pch_gpio_reg;
struct mutex lock;
};
static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
{
u32 reg_val;
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
mutex_lock(&chip->lock);
reg_val = ioread32(&chip->reg->po);
if (val)
reg_val |= (1 << nr);
else
reg_val &= ~(1 << nr);
iowrite32(reg_val, &chip->reg->po);
mutex_unlock(&chip->lock);
}
static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
{
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
return ioread32(&chip->reg->pi) & (1 << nr);
}
static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
int val)
{
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
u32 pm;
u32 reg_val;
mutex_lock(&chip->lock);
pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS;
pm |= (1 << nr);
iowrite32(pm, &chip->reg->pm);
reg_val = ioread32(&chip->reg->po);
if (val)
reg_val |= (1 << nr);
else
reg_val &= ~(1 << nr);
mutex_unlock(&chip->lock);
return 0;
}
static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
{
struct pch_gpio *chip = container_of(gpio, struct pch_gpio, gpio);
u32 pm;
mutex_lock(&chip->lock);
pm = ioread32(&chip->reg->pm) & PCH_GPIO_ALL_PINS; /*bits 0-11*/
pm &= ~(1 << nr);
iowrite32(pm, &chip->reg->pm);
mutex_unlock(&chip->lock);
return 0;
}
/*
* Save register configuration and disable interrupts.
*/
static void pch_gpio_save_reg_conf(struct pch_gpio *chip)
{
chip->pch_gpio_reg.po_reg = ioread32(&chip->reg->po);
chip->pch_gpio_reg.pm_reg = ioread32(&chip->reg->pm);
}
/*
* This function restores the register configuration of the GPIO device.
*/
static void pch_gpio_restore_reg_conf(struct pch_gpio *chip)
{
/* to store contents of PO register */
iowrite32(chip->pch_gpio_reg.po_reg, &chip->reg->po);
/* to store contents of PM register */
iowrite32(chip->pch_gpio_reg.pm_reg, &chip->reg->pm);
}
static void pch_gpio_setup(struct pch_gpio *chip)
{
struct gpio_chip *gpio = &chip->gpio;
gpio->label = dev_name(chip->dev);
gpio->owner = THIS_MODULE;
gpio->direction_input = pch_gpio_direction_input;
gpio->get = pch_gpio_get;
gpio->direction_output = pch_gpio_direction_output;
gpio->set = pch_gpio_set;
gpio->dbg_show = NULL;
gpio->base = -1;
gpio->ngpio = GPIO_NUM_PINS;
gpio->can_sleep = 0;
}
static int __devinit pch_gpio_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
s32 ret;
struct pch_gpio *chip;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
chip->dev = &pdev->dev;
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "%s : pci_enable_device FAILED", __func__);
goto err_pci_enable;
}
ret = pci_request_regions(pdev, KBUILD_MODNAME);
if (ret) {
dev_err(&pdev->dev, "pci_request_regions FAILED-%d", ret);
goto err_request_regions;
}
chip->base = pci_iomap(pdev, 1, 0);
if (chip->base == 0) {
dev_err(&pdev->dev, "%s : pci_iomap FAILED", __func__);
ret = -ENOMEM;
goto err_iomap;
}
chip->reg = chip->base;
pci_set_drvdata(pdev, chip);
mutex_init(&chip->lock);
pch_gpio_setup(chip);
ret = gpiochip_add(&chip->gpio);
if (ret) {
dev_err(&pdev->dev, "PCH gpio: Failed to register GPIO\n");
goto err_gpiochip_add;
}
return 0;
err_gpiochip_add:
pci_iounmap(pdev, chip->base);
err_iomap:
pci_release_regions(pdev);
err_request_regions:
pci_disable_device(pdev);
err_pci_enable:
kfree(chip);
dev_err(&pdev->dev, "%s Failed returns %d\n", __func__, ret);
return ret;
}
static void __devexit pch_gpio_remove(struct pci_dev *pdev)
{
int err;
struct pch_gpio *chip = pci_get_drvdata(pdev);
err = gpiochip_remove(&chip->gpio);
if (err)
dev_err(&pdev->dev, "Failed gpiochip_remove\n");
pci_iounmap(pdev, chip->base);
pci_release_regions(pdev);
pci_disable_device(pdev);
kfree(chip);
}
#ifdef CONFIG_PM
static int pch_gpio_suspend(struct pci_dev *pdev, pm_message_t state)
{
s32 ret;
struct pch_gpio *chip = pci_get_drvdata(pdev);
pch_gpio_save_reg_conf(chip);
pch_gpio_restore_reg_conf(chip);
ret = pci_save_state(pdev);
if (ret) {
dev_err(&pdev->dev, "pci_save_state Failed-%d\n", ret);
return ret;
}
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D0);
ret = pci_enable_wake(pdev, PCI_D0, 1);
if (ret)
dev_err(&pdev->dev, "pci_enable_wake Failed -%d\n", ret);
return 0;
}
static int pch_gpio_resume(struct pci_dev *pdev)
{
s32 ret;
struct pch_gpio *chip = pci_get_drvdata(pdev);
ret = pci_enable_wake(pdev, PCI_D0, 0);
pci_set_power_state(pdev, PCI_D0);
ret = pci_enable_device(pdev);
if (ret) {
dev_err(&pdev->dev, "pci_enable_device Failed-%d ", ret);
return ret;
}
pci_restore_state(pdev);
iowrite32(0x01, &chip->reg->reset);
iowrite32(0x00, &chip->reg->reset);
pch_gpio_restore_reg_conf(chip);
return 0;
}
#else
#define pch_gpio_suspend NULL
#define pch_gpio_resume NULL
#endif
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ 0, }
};
static struct pci_driver pch_gpio_driver = {
.name = "pch_gpio",
.id_table = pch_gpio_pcidev_id,
.probe = pch_gpio_probe,
.remove = __devexit_p(pch_gpio_remove),
.suspend = pch_gpio_suspend,
.resume = pch_gpio_resume
};
static int __init pch_gpio_pci_init(void)
{
return pci_register_driver(&pch_gpio_driver);
}
module_init(pch_gpio_pci_init);
static void __exit pch_gpio_pci_exit(void)
{
pci_unregister_driver(&pch_gpio_driver);
}
module_exit(pch_gpio_pci_exit);
MODULE_DESCRIPTION("PCH GPIO PCI Driver");
MODULE_LICENSE("GPL");
...@@ -47,6 +47,7 @@ struct timbgpio { ...@@ -47,6 +47,7 @@ struct timbgpio {
spinlock_t lock; /* mutual exclusion */ spinlock_t lock; /* mutual exclusion */
struct gpio_chip gpio; struct gpio_chip gpio;
int irq_base; int irq_base;
unsigned long last_ier;
}; };
static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
...@@ -112,16 +113,24 @@ static void timbgpio_irq_disable(unsigned irq) ...@@ -112,16 +113,24 @@ static void timbgpio_irq_disable(unsigned irq)
{ {
struct timbgpio *tgpio = get_irq_chip_data(irq); struct timbgpio *tgpio = get_irq_chip_data(irq);
int offset = irq - tgpio->irq_base; int offset = irq - tgpio->irq_base;
unsigned long flags;
timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 0); spin_lock_irqsave(&tgpio->lock, flags);
tgpio->last_ier &= ~(1 << offset);
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
spin_unlock_irqrestore(&tgpio->lock, flags);
} }
static void timbgpio_irq_enable(unsigned irq) static void timbgpio_irq_enable(unsigned irq)
{ {
struct timbgpio *tgpio = get_irq_chip_data(irq); struct timbgpio *tgpio = get_irq_chip_data(irq);
int offset = irq - tgpio->irq_base; int offset = irq - tgpio->irq_base;
unsigned long flags;
timbgpio_update_bit(&tgpio->gpio, offset, TGPIO_IER, 1); spin_lock_irqsave(&tgpio->lock, flags);
tgpio->last_ier |= 1 << offset;
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
spin_unlock_irqrestore(&tgpio->lock, flags);
} }
static int timbgpio_irq_type(unsigned irq, unsigned trigger) static int timbgpio_irq_type(unsigned irq, unsigned trigger)
...@@ -194,8 +203,16 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) ...@@ -194,8 +203,16 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
ipr = ioread32(tgpio->membase + TGPIO_IPR); ipr = ioread32(tgpio->membase + TGPIO_IPR);
iowrite32(ipr, tgpio->membase + TGPIO_ICR); iowrite32(ipr, tgpio->membase + TGPIO_ICR);
/*
* Some versions of the hardware trash the IER register if more than
* one interrupt is received simultaneously.
*/
iowrite32(0, tgpio->membase + TGPIO_IER);
for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio) for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset)); generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
} }
static struct irq_chip timbgpio_irqchip = { static struct irq_chip timbgpio_irqchip = {
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/errno.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/unistd.h> #include <linux/unistd.h>
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/interrupt.h>
#include <asm/intel_scu_ipc.h> #include <asm/intel_scu_ipc.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/intel_pmic_gpio.h> #include <linux/intel_pmic_gpio.h>
......
...@@ -192,7 +192,7 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv) ...@@ -192,7 +192,7 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv)
out:return 0; out:return 0;
} }
static struct device rio_bus = { struct device rio_bus = {
.init_name = "rapidio", .init_name = "rapidio",
}; };
......
...@@ -48,7 +48,7 @@ DEFINE_SPINLOCK(rio_global_list_lock); ...@@ -48,7 +48,7 @@ DEFINE_SPINLOCK(rio_global_list_lock);
static int next_destid = 0; static int next_destid = 0;
static int next_switchid = 0; static int next_switchid = 0;
static int next_net = 0; static int next_net = 0;
static int next_comptag; static int next_comptag = 1;
static struct timer_list rio_enum_timer = static struct timer_list rio_enum_timer =
TIMER_INITIALIZER(rio_enum_timeout, 0, 0); TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
...@@ -121,27 +121,6 @@ static int rio_clear_locks(struct rio_mport *port) ...@@ -121,27 +121,6 @@ static int rio_clear_locks(struct rio_mport *port)
u32 result; u32 result;
int ret = 0; int ret = 0;
/* Assign component tag to all devices */
next_comptag = 1;
rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++);
list_for_each_entry(rdev, &rio_devices, global_list) {
/* Mark device as discovered */
rio_read_config_32(rdev,
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
&result);
rio_write_config_32(rdev,
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
result | RIO_PORT_GEN_DISCOVERED);
rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag);
rdev->comp_tag = next_comptag++;
if (next_comptag >= 0x10000) {
pr_err("RIO: Component Tag Counter Overflow\n");
break;
}
}
/* Release host device id locks */ /* Release host device id locks */
rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
port->host_deviceid); port->host_deviceid);
...@@ -162,6 +141,15 @@ static int rio_clear_locks(struct rio_mport *port) ...@@ -162,6 +141,15 @@ static int rio_clear_locks(struct rio_mport *port)
rdev->vid, rdev->did); rdev->vid, rdev->did);
ret = -EINVAL; ret = -EINVAL;
} }
/* Mark device as discovered and enable master */
rio_read_config_32(rdev,
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
&result);
result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER;
rio_write_config_32(rdev,
rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
result);
} }
return ret; return ret;
...@@ -420,11 +408,27 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, ...@@ -420,11 +408,27 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
hopcount, RIO_EFB_ERR_MGMNT); hopcount, RIO_EFB_ERR_MGMNT);
} }
if (rdev->pef & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) {
rio_mport_read_config_32(port, destid, hopcount,
RIO_SWP_INFO_CAR, &rdev->swpinfo);
}
rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
&rdev->src_ops); &rdev->src_ops);
rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR, rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
&rdev->dst_ops); &rdev->dst_ops);
if (do_enum) {
/* Assign component tag to device */
if (next_comptag >= 0x10000) {
pr_err("RIO: Component Tag Counter Overflow\n");
goto cleanup;
}
rio_mport_write_config_32(port, destid, hopcount,
RIO_COMPONENT_TAG_CSR, next_comptag);
rdev->comp_tag = next_comptag++;
}
if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
if (do_enum) { if (do_enum) {
rio_set_device_id(port, destid, hopcount, next_destid); rio_set_device_id(port, destid, hopcount, next_destid);
...@@ -439,9 +443,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, ...@@ -439,9 +443,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
/* If a PE has both switch and other functions, show it as a switch */ /* If a PE has both switch and other functions, show it as a switch */
if (rio_is_switch(rdev)) { if (rio_is_switch(rdev)) {
rio_mport_read_config_32(port, destid, hopcount, rswitch = kzalloc(sizeof(*rswitch) +
RIO_SWP_INFO_CAR, &rdev->swpinfo); RIO_GET_TOTAL_PORTS(rdev->swpinfo) *
rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); sizeof(rswitch->nextdev[0]),
GFP_KERNEL);
if (!rswitch) if (!rswitch)
goto cleanup; goto cleanup;
rswitch->switchid = next_switchid; rswitch->switchid = next_switchid;
...@@ -458,6 +463,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, ...@@ -458,6 +463,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
rdid++) rdid++)
rswitch->route_table[rdid] = RIO_INVALID_ROUTE; rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
rdev->rswitch = rswitch; rdev->rswitch = rswitch;
rswitch->rdev = rdev;
dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
rdev->rswitch->switchid); rdev->rswitch->switchid);
rio_switch_init(rdev, do_enum); rio_switch_init(rdev, do_enum);
...@@ -478,6 +484,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, ...@@ -478,6 +484,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
} }
rdev->dev.bus = &rio_bus_type; rdev->dev.bus = &rio_bus_type;
rdev->dev.parent = &rio_bus;
device_initialize(&rdev->dev); device_initialize(&rdev->dev);
rdev->dev.release = rio_release_dev; rdev->dev.release = rio_release_dev;
...@@ -717,87 +724,54 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) ...@@ -717,87 +724,54 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
return (u16) (result & 0xffff); return (u16) (result & 0xffff);
} }
/**
* rio_get_swpinfo_inport- Gets the ingress port number
* @mport: Master port to send transaction
* @destid: Destination ID associated with the switch
* @hopcount: Number of hops to the device
*
* Returns port number being used to access the switch device.
*/
static u8
rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount)
{
u32 result;
rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR,
&result);
return (u8) (result & 0xff);
}
/**
* rio_get_swpinfo_tports- Gets total number of ports on the switch
* @mport: Master port to send transaction
* @destid: Destination ID associated with the switch
* @hopcount: Number of hops to the device
*
* Returns total numbers of ports implemented by the switch device.
*/
static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid,
u8 hopcount)
{
u32 result;
rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR,
&result);
return RIO_GET_TOTAL_PORTS(result);
}
/**
* rio_net_add_mport- Add a master port to a RIO network
* @net: RIO network
* @port: Master port to add
*
* Adds a master port to the network list of associated master
* ports..
*/
static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port)
{
spin_lock(&rio_global_list_lock);
list_add_tail(&port->nnode, &net->mports);
spin_unlock(&rio_global_list_lock);
}
/** /**
* rio_enum_peer- Recursively enumerate a RIO network through a master port * rio_enum_peer- Recursively enumerate a RIO network through a master port
* @net: RIO network being enumerated * @net: RIO network being enumerated
* @port: Master port to send transactions * @port: Master port to send transactions
* @hopcount: Number of hops into the network * @hopcount: Number of hops into the network
* @prev: Previous RIO device connected to the enumerated one
* @prev_port: Port on previous RIO device
* *
* Recursively enumerates a RIO network. Transactions are sent via the * Recursively enumerates a RIO network. Transactions are sent via the
* master port passed in @port. * master port passed in @port.
*/ */
static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
u8 hopcount) u8 hopcount, struct rio_dev *prev, int prev_port)
{ {
int port_num; int port_num;
int num_ports;
int cur_destid; int cur_destid;
int sw_destid; int sw_destid;
int sw_inport; int sw_inport;
struct rio_dev *rdev; struct rio_dev *rdev;
u16 destid; u16 destid;
u32 regval;
int tmp; int tmp;
if (rio_mport_chk_dev_access(port,
RIO_ANY_DESTID(port->sys_size), hopcount)) {
pr_debug("RIO: device access check failed\n");
return -1;
}
if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) { if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) {
pr_debug("RIO: PE already discovered by this host\n"); pr_debug("RIO: PE already discovered by this host\n");
/* /*
* Already discovered by this host. Add it as another * Already discovered by this host. Add it as another
* master port for the current network. * link to the existing device.
*/ */
rio_net_add_mport(net, port); rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size),
hopcount, RIO_COMPONENT_TAG_CSR, &regval);
if (regval) {
rdev = rio_get_comptag((regval & 0xffff), NULL);
if (rdev && prev && rio_is_switch(prev)) {
pr_debug("RIO: redundant path to %s\n",
rio_name(rdev));
prev->rswitch->nextdev[prev_port] = rdev;
}
}
return 0; return 0;
} }
...@@ -828,13 +802,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, ...@@ -828,13 +802,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
if (rdev) { if (rdev) {
/* Add device to the global and bus/net specific list. */ /* Add device to the global and bus/net specific list. */
list_add_tail(&rdev->net_list, &net->devices); list_add_tail(&rdev->net_list, &net->devices);
rdev->prev = prev;
if (prev && rio_is_switch(prev))
prev->rswitch->nextdev[prev_port] = rdev;
} else } else
return -1; return -1;
if (rio_is_switch(rdev)) { if (rio_is_switch(rdev)) {
next_switchid++; next_switchid++;
sw_inport = rio_get_swpinfo_inport(port, sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo);
RIO_ANY_DESTID(port->sys_size), hopcount);
rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
port->host_deviceid, sw_inport, 0); port->host_deviceid, sw_inport, 0);
rdev->rswitch->route_table[port->host_deviceid] = sw_inport; rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
...@@ -847,14 +823,14 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, ...@@ -847,14 +823,14 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
rdev->rswitch->route_table[destid] = sw_inport; rdev->rswitch->route_table[destid] = sw_inport;
} }
num_ports =
rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size),
hopcount);
pr_debug( pr_debug(
"RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
rio_name(rdev), rdev->vid, rdev->did, num_ports); rio_name(rdev), rdev->vid, rdev->did,
RIO_GET_TOTAL_PORTS(rdev->swpinfo));
sw_destid = next_destid; sw_destid = next_destid;
for (port_num = 0; port_num < num_ports; port_num++) { for (port_num = 0;
port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo);
port_num++) {
/*Enable Input Output Port (transmitter reviever)*/ /*Enable Input Output Port (transmitter reviever)*/
rio_enable_rx_tx_port(port, 0, rio_enable_rx_tx_port(port, 0,
RIO_ANY_DESTID(port->sys_size), RIO_ANY_DESTID(port->sys_size),
...@@ -879,7 +855,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, ...@@ -879,7 +855,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
RIO_ANY_DESTID(port->sys_size), RIO_ANY_DESTID(port->sys_size),
port_num, 0); port_num, 0);
if (rio_enum_peer(net, port, hopcount + 1) < 0) if (rio_enum_peer(net, port, hopcount + 1,
rdev, port_num) < 0)
return -1; return -1;
/* Update routing tables */ /* Update routing tables */
...@@ -945,10 +922,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, ...@@ -945,10 +922,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
*/ */
static int rio_enum_complete(struct rio_mport *port) static int rio_enum_complete(struct rio_mport *port)
{ {
u32 tag_csr; u32 regval;
rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
return (tag_csr & 0xffff) ? 1 : 0; &regval);
return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0;
} }
/** /**
...@@ -966,7 +944,6 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, ...@@ -966,7 +944,6 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
u8 hopcount) u8 hopcount)
{ {
u8 port_num, route_port; u8 port_num, route_port;
int num_ports;
struct rio_dev *rdev; struct rio_dev *rdev;
u16 ndestid; u16 ndestid;
...@@ -983,13 +960,14 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, ...@@ -983,13 +960,14 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
/* Associated destid is how we accessed this switch */ /* Associated destid is how we accessed this switch */
rdev->rswitch->destid = destid; rdev->rswitch->destid = destid;
num_ports = rio_get_swpinfo_tports(port, destid, hopcount);
pr_debug( pr_debug(
"RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
rio_name(rdev), rdev->vid, rdev->did, num_ports); rio_name(rdev), rdev->vid, rdev->did,
for (port_num = 0; port_num < num_ports; port_num++) { RIO_GET_TOTAL_PORTS(rdev->swpinfo));
if (rio_get_swpinfo_inport(port, destid, hopcount) == for (port_num = 0;
port_num) port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo);
port_num++) {
if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num)
continue; continue;
if (rio_sport_is_active if (rio_sport_is_active
...@@ -1011,6 +989,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, ...@@ -1011,6 +989,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
break; break;
} }
if (ndestid == RIO_ANY_DESTID(port->sys_size))
continue;
rio_unlock_device(port, destid, hopcount); rio_unlock_device(port, destid, hopcount);
if (rio_disc_peer if (rio_disc_peer
(net, port, ndestid, hopcount + 1) < 0) (net, port, ndestid, hopcount + 1) < 0)
...@@ -1108,8 +1088,7 @@ static void rio_update_route_tables(struct rio_mport *port) ...@@ -1108,8 +1088,7 @@ static void rio_update_route_tables(struct rio_mport *port)
if (rswitch->destid == destid) if (rswitch->destid == destid)
continue; continue;
sport = rio_get_swpinfo_inport(port, sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo);
rswitch->destid, rswitch->hopcount);
if (rswitch->add_entry) { if (rswitch->add_entry) {
rio_route_add_entry(port, rswitch, rio_route_add_entry(port, rswitch,
...@@ -1184,7 +1163,11 @@ int __devinit rio_enum_mport(struct rio_mport *mport) ...@@ -1184,7 +1163,11 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
/* Enable Input Output Port (transmitter reviever) */ /* Enable Input Output Port (transmitter reviever) */
rio_enable_rx_tx_port(mport, 1, 0, 0, 0); rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
if (rio_enum_peer(net, mport, 0) < 0) { /* Set component tag for host */
rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR,
next_comptag++);
if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) {
/* A higher priority host won enumeration, bail. */ /* A higher priority host won enumeration, bail. */
printk(KERN_INFO printk(KERN_INFO
"RIO: master port %d device has lost enumeration to a remote host\n", "RIO: master port %d device has lost enumeration to a remote host\n",
......
...@@ -40,9 +40,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch ...@@ -40,9 +40,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
char *str = buf; char *str = buf;
int i; int i;
if (!rdev->rswitch)
goto out;
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
i++) { i++) {
if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE) if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
...@@ -52,7 +49,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch ...@@ -52,7 +49,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
rdev->rswitch->route_table[i]); rdev->rswitch->route_table[i]);
} }
out:
return (str - buf); return (str - buf);
} }
...@@ -63,10 +59,11 @@ struct device_attribute rio_dev_attrs[] = { ...@@ -63,10 +59,11 @@ struct device_attribute rio_dev_attrs[] = {
__ATTR_RO(asm_did), __ATTR_RO(asm_did),
__ATTR_RO(asm_vid), __ATTR_RO(asm_vid),
__ATTR_RO(asm_rev), __ATTR_RO(asm_rev),
__ATTR_RO(routes),
__ATTR_NULL, __ATTR_NULL,
}; };
static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL);
static ssize_t static ssize_t
rio_read_config(struct file *filp, struct kobject *kobj, rio_read_config(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, struct bin_attribute *bin_attr,
...@@ -218,7 +215,17 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) ...@@ -218,7 +215,17 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev)
{ {
int err = 0; int err = 0;
err = sysfs_create_bin_file(&rdev->dev.kobj, &rio_config_attr); err = device_create_bin_file(&rdev->dev, &rio_config_attr);
if (!err && rdev->rswitch) {
err = device_create_file(&rdev->dev, &dev_attr_routes);
if (!err && rdev->rswitch->sw_sysfs)
err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE);
}
if (err)
pr_warning("RIO: Failed to create attribute file(s) for %s\n",
rio_name(rdev));
return err; return err;
} }
...@@ -231,5 +238,10 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev) ...@@ -231,5 +238,10 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev)
*/ */
void rio_remove_sysfs_dev_files(struct rio_dev *rdev) void rio_remove_sysfs_dev_files(struct rio_dev *rdev)
{ {
sysfs_remove_bin_file(&rdev->dev.kobj, &rio_config_attr); device_remove_bin_file(&rdev->dev, &rio_config_attr);
if (rdev->rswitch) {
device_remove_file(&rdev->dev, &dev_attr_routes);
if (rdev->rswitch->sw_sysfs)
rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE);
}
} }
此差异已折叠。
此差异已折叠。
此差异已折叠。
...@@ -6,6 +6,7 @@ obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o ...@@ -6,6 +6,7 @@ obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o
obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o
obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o
obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o
obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o
ifeq ($(CONFIG_RAPIDIO_DEBUG),y) ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册