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
  ...
This commit is contained in:
Linus Torvalds 2010-10-27 18:42:52 -07:00
commit 17bb51d56c
165 changed files with 4766 additions and 1299 deletions

View File

@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <linux/genetlink.h>
@ -266,11 +267,13 @@ int main(int argc, char *argv[])
int containerset = 0;
char containerpath[1024];
int cfd = 0;
int forking = 0;
sigset_t sigset;
struct msgtemplate msg;
while (1) {
c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:");
while (!forking) {
c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
if (c < 0)
break;
@ -319,6 +322,28 @@ int main(int argc, char *argv[])
err(1, "Invalid pid\n");
cmd_type = TASKSTATS_CMD_ATTR_PID;
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':
printf("debug on\n");
dbg = 1;
@ -370,6 +395,15 @@ int main(int argc, char *argv[])
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) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
cmd_type, &tid, sizeof(__u32));

View File

@ -18,7 +18,8 @@ CONTENTS:
1.2 Why are cgroups needed ?
1.3 How are cgroups implemented ?
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.1 Basic Usage
2.2 Attaching processes
@ -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
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

View File

@ -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
When: 2.6.40
Why: Hareware scan is the prefer method for iwlwifi devices for

View File

@ -136,6 +136,7 @@ Table 1-1: Process specific entries in /proc
statm Process memory status information
status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
pagemap Page table
stack Report full stack trace, enable via CONFIG_STACKTRACE
smaps a extension based on maps, showing the memory consumption of
each mapping
@ -370,6 +371,7 @@ Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 0 kB
Referenced: 892 kB
Anonymous: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
@ -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
(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
dirty shared pages in the mapping, and the number of clean and dirty private
pages in the mapping. The "Referenced" indicates the amount of memory
currently marked as referenced or accessed.
dirty private pages in the mapping. Note that even a page which is part of a
MAP_SHARED mapping, but has only a single pte mapped, i.e. is currently used
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
enabled.
@ -397,6 +405,9 @@ To clear the bits for the file mapped pages associated with the process
> echo 3 > /proc/PID/clear_refs
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
---------------

View File

@ -80,8 +80,10 @@ dirty_background_bytes
Contains the amount of dirty memory at which the pdflush background writeback
daemon will start writeback.
If dirty_background_bytes is written, dirty_background_ratio becomes a function
of its value (dirty_background_bytes / the amount of dirtyable system memory).
Note: dirty_background_bytes is the counterpart of dirty_background_ratio. Only
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
Contains the amount of dirty memory at which a process generating disk writes
will itself start writeback.
If dirty_bytes is written, dirty_ratio becomes a function of its value
(dirty_bytes / the amount of dirtyable system memory).
Note: dirty_bytes is the counterpart of dirty_ratio. Only 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.
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

View File

@ -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)
{
dma64_addr_t dac_offset = alpha_mv.pci_dac_offset;
dma_addr_t dac_offset = alpha_mv.pci_dac_offset;
int ok = 1;
/* 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,
spin_lock_irqsave(&arena->lock, flags);
for (end = sg + nents; sg < end; ++sg) {
dma64_addr_t addr;
dma_addr_t addr;
size_t size;
long npages, ofs;
dma_addr_t tend;

View File

@ -269,7 +269,8 @@ void ptrace_disable(struct task_struct *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;
size_t copied;
@ -292,7 +293,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_PEEKUSR:
force_successful_syscall_return();
ret = get_reg(child, addr);
DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret));
DBG(DBG_MEM, ("peek $%lu->%#lx\n", addr, ret));
break;
/* 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)
break;
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);
break;
default:

View File

@ -1075,13 +1075,15 @@ out:
}
#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;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
case PTRACE_PEEKUSR:
ret = ptrace_read_user(child, addr, (unsigned long __user *)data);
ret = ptrace_read_user(child, addr, datap);
break;
case PTRACE_POKEUSR:
@ -1089,34 +1091,34 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data);
ret = ptrace_getregs(child, datap);
break;
case PTRACE_SETREGS:
ret = ptrace_setregs(child, (void __user *)data);
ret = ptrace_setregs(child, datap);
break;
case PTRACE_GETFPREGS:
ret = ptrace_getfpregs(child, (void __user *)data);
ret = ptrace_getfpregs(child, datap);
break;
case PTRACE_SETFPREGS:
ret = ptrace_setfpregs(child, (void __user *)data);
ret = ptrace_setfpregs(child, datap);
break;
#ifdef CONFIG_IWMMXT
case PTRACE_GETWMMXREGS:
ret = ptrace_getwmmxregs(child, (void __user *)data);
ret = ptrace_getwmmxregs(child, datap);
break;
case PTRACE_SETWMMXREGS:
ret = ptrace_setwmmxregs(child, (void __user *)data);
ret = ptrace_setwmmxregs(child, datap);
break;
#endif
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) data);
datap);
break;
case PTRACE_SET_SYSCALL:
@ -1126,21 +1128,21 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef CONFIG_CRUNCH
case PTRACE_GETCRUNCHREGS:
ret = ptrace_getcrunchregs(child, (void __user *)data);
ret = ptrace_getcrunchregs(child, datap);
break;
case PTRACE_SETCRUNCHREGS:
ret = ptrace_setcrunchregs(child, (void __user *)data);
ret = ptrace_setcrunchregs(child, datap);
break;
#endif
#ifdef CONFIG_VFP
case PTRACE_GETVFPREGS:
ret = ptrace_getvfpregs(child, (void __user *)data);
ret = ptrace_getvfpregs(child, datap);
break;
case PTRACE_SETVFPREGS:
ret = ptrace_setvfpregs(child, (void __user *)data);
ret = ptrace_setvfpregs(child, datap);
break;
#endif

View File

@ -27,7 +27,6 @@
#include <linux/io.h>
#include <linux/cnt32_to_63.h>
#include <asm/mach/time.h>
#include <asm/mach/time.h>
#include <asm/localtimer.h>

View File

@ -89,7 +89,7 @@ void __kunmap_atomic(void *kvaddr)
int idx, type;
if (kvaddr >= (void *)FIXADDR_START) {
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
idx = type + KM_TYPE_NR * smp_processor_id();
if (cache_is_vivt())
@ -101,6 +101,7 @@ void __kunmap_atomic(void *kvaddr)
#else
(void) idx; /* to kill a warning */
#endif
kmap_atomic_idx_pop();
} else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) {
/* this address was obtained through kmap_high_get() */
kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));

View File

@ -14,7 +14,6 @@
#include <linux/dmaengine.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/dmaengine.h>
/* dev types for memcpy */
#define STEDMA40_DEV_DST_MEMORY (-1)

View File

@ -146,9 +146,11 @@ static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs)
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;
void __user *datap = (void __user *) data;
switch (request) {
/* 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)
break;
case PTRACE_PEEKUSR:
ret = ptrace_read_user(child, addr,
(unsigned long __user *)data);
ret = ptrace_read_user(child, addr, datap);
break;
/* 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)
break;
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data);
ret = ptrace_getregs(child, datap);
break;
case PTRACE_SETREGS:
ret = ptrace_setregs(child, (const void __user *)data);
ret = ptrace_setregs(child, datap);
break;
default:

View File

@ -38,12 +38,13 @@
* Get contents of register REGNO in task TASK.
*/
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;
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;
switch (regno) {
@ -74,11 +75,11 @@ get_reg(struct task_struct *task, long regno, unsigned long __user *datap)
* Write contents of register REGNO in task TASK.
*/
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);
if (regno & 3 || regno > PT_LAST_PSEUDO || regno < 0)
if (regno & 3 || regno > PT_LAST_PSEUDO)
return -EIO;
switch (regno) {
@ -240,7 +241,8 @@ void user_disable_single_step(struct task_struct *child)
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;
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)
return copy_regset_to_user(child, &user_bfin_native_view,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(void __user *)data);
datap);
case PTRACE_SETREGS:
pr_debug("ptrace: PTRACE_SETREGS\n");
return copy_regset_from_user(child, &user_bfin_native_view,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(const void __user *)data);
datap);
case_default:
default:

View File

@ -76,9 +76,11 @@ ptrace_disable(struct task_struct *child)
* (in user space) where the result of the ptrace call is written (instead of
* 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;
unsigned int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *)data;
switch (request) {
@ -93,10 +95,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp;
ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2)
if ((addr & 3) || regno > PT_MAX)
break;
tmp = get_reg(child, addr >> 2);
tmp = get_reg(child, regno);
ret = put_user(tmp, datap);
break;
}
@ -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. */
case PTRACE_POKEUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2)
if ((addr & 3) || regno > PT_MAX)
break;
addr >>= 2;
if (addr == PT_DCCR) {
if (regno == PT_DCCR) {
/* don't allow the tracing process to change stuff like
* interrupt enable, kernel/user bit, dma enables etc.
*/
data &= DCCR_MASK;
data |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
}
if (put_reg(child, addr, data))
if (put_reg(child, regno, data))
break;
ret = 0;
break;
@ -141,7 +141,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
}
data += sizeof(long);
datap++;
}
break;
@ -165,7 +165,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
put_reg(child, i, tmp);
data += sizeof(long);
datap++;
}
break;

View File

@ -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;
unsigned int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *)data;
switch (request) {
@ -163,10 +165,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp;
ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2)
if ((addr & 3) || regno > PT_MAX)
break;
tmp = get_reg(child, addr >> 2);
tmp = get_reg(child, regno);
ret = put_user(tmp, datap);
break;
}
@ -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. */
case PTRACE_POKEUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 || addr > PT_MAX << 2)
if ((addr & 3) || regno > PT_MAX)
break;
addr >>= 2;
if (addr == PT_CCS) {
if (regno == PT_CCS) {
/* don't allow the tracing process to change stuff like
* interrupt enable, kernel/user bit, dma enables etc.
*/
data &= CCS_MASK;
data |= get_reg(child, PT_CCS) & ~CCS_MASK;
}
if (put_reg(child, addr, data))
if (put_reg(child, regno, data))
break;
ret = 0;
break;

View File

@ -254,23 +254,26 @@ void ptrace_disable(struct task_struct *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;
int ret;
int regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
tmp = 0;
ret = -EIO;
if ((addr & 3) || addr < 0)
if (addr & 3)
break;
ret = 0;
switch (addr >> 2) {
switch (regno) {
case 0 ... PT__END - 1:
tmp = get_reg(child, addr >> 2);
tmp = get_reg(child, regno);
break;
case PT__END + 0:
@ -299,23 +302,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
if (ret == 0)
ret = put_user(tmp, (unsigned long *) data);
ret = put_user(tmp, datap);
break;
}
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
if ((addr & 3) || addr < 0)
if (addr & 3)
break;
ret = 0;
switch (addr >> 2) {
switch (regno) {
case 0 ... PT__END - 1:
ret = put_reg(child, addr >> 2, data);
break;
default:
ret = -EIO;
ret = put_reg(child, regno, data);
break;
}
break;
@ -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,
REGSET_GENERAL,
0, sizeof(child->thread.user->i),
(void __user *)data);
datap);
case PTRACE_SETREGS: /* Set all integer regs in the child. */
return copy_regset_from_user(child, &user_frv_native_view,
REGSET_GENERAL,
0, sizeof(child->thread.user->i),
(const void __user *)data);
datap);
case PTRACE_GETFPREGS: /* Get the child FP/Media state. */
return copy_regset_to_user(child, &user_frv_native_view,
REGSET_FPMEDIA,
0, sizeof(child->thread.user->f),
(void __user *)data);
datap);
case PTRACE_SETFPREGS: /* Set the child FP/Media state. */
return copy_regset_from_user(child, &user_frv_native_view,
REGSET_FPMEDIA,
0, sizeof(child->thread.user->f),
(const void __user *)data);
datap);
default:
ret = ptrace_request(child, request, addr, data);

View File

@ -68,7 +68,7 @@ EXPORT_SYMBOL(__kmap_atomic);
void __kunmap_atomic(void *kvaddr)
{
int type = kmap_atomic_idx_pop();
int type = kmap_atomic_idx();
switch (type) {
case 0: __kunmap_atomic_primary(4, 6); break;
case 1: __kunmap_atomic_primary(5, 7); break;
@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr)
default:
BUG();
}
kmap_atomic_idx_pop();
pagefault_enable();
}
EXPORT_SYMBOL(__kunmap_atomic);

View File

@ -50,27 +50,29 @@ void ptrace_disable(struct task_struct *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 regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp = 0;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
if ((addr & 3) || addr >= sizeof(struct user)) {
ret = -EIO;
break ;
}
ret = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
if (addr < H8300_REGS_NO)
tmp = h8300_get_reg(child, addr);
if (regno < H8300_REGS_NO)
tmp = h8300_get_reg(child, regno);
else {
switch(addr) {
switch (regno) {
case 49:
tmp = child->mm->start_code;
break ;
@ -88,24 +90,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
}
if (!ret)
ret = put_user(tmp,(unsigned long *) data);
ret = put_user(tmp, datap);
break ;
}
/* 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 */
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
if ((addr & 3) || addr >= sizeof(struct user)) {
ret = -EIO;
break ;
}
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_ER0) {
if (regno == PT_ORIG_ER0) {
ret = -EIO;
break ;
}
if (addr < H8300_REGS_NO) {
ret = h8300_put_reg(child, addr, data);
if (regno < H8300_REGS_NO) {
ret = h8300_put_reg(child, regno, data);
break ;
}
ret = -EIO;
@ -116,11 +117,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
unsigned long tmp;
for (i = 0; i < H8300_REGS_NO; i++) {
tmp = h8300_get_reg(child, i);
if (put_user(tmp, (unsigned long *) data)) {
if (put_user(tmp, datap)) {
ret = -EFAULT;
break;
}
data += sizeof(long);
datap++;
}
ret = 0;
break;
@ -130,12 +131,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int i;
unsigned long tmp;
for (i = 0; i < H8300_REGS_NO; i++) {
if (get_user(tmp, (unsigned long *) data)) {
if (get_user(tmp, datap)) {
ret = -EFAULT;
break;
}
h8300_put_reg(child, i, tmp);
data += sizeof(long);
datap++;
}
ret = 0;
break;

View File

@ -56,10 +56,10 @@ typedef u64 cputime64_t;
#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 msecs_to_cputime(__msecs) ((__msecs) * NSEC_PER_MSEC)
#define cputime_to_usecs(__ct) ((__ct) / NSEC_PER_USEC)
#define usecs_to_cputime(__usecs) ((__usecs) * NSEC_PER_USEC)
/*
* Convert cputime <-> seconds

View File

@ -1177,7 +1177,8 @@ ptrace_disable (struct task_struct *child)
}
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) {
case PTRACE_PEEKTEXT:

View File

@ -622,9 +622,11 @@ void ptrace_disable(struct task_struct *child)
}
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;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
/*
@ -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.
*/
case PTRACE_PEEKUSR:
ret = ptrace_read_user(child, addr,
(unsigned long __user *)data);
ret = ptrace_read_user(child, addr, datap);
break;
/*
@ -661,11 +662,11 @@ arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *)data);
ret = ptrace_getregs(child, datap);
break;
case PTRACE_SETREGS:
ret = ptrace_setregs(child, (void __user *)data);
ret = ptrace_setregs(child, datap);
break;
default:

View File

@ -156,55 +156,57 @@ void user_disable_single_step(struct task_struct *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;
int i, ret = 0;
int regno = addr >> 2; /* temporary hack. */
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR:
if (addr & 3)
goto out_eio;
addr >>= 2; /* temporary hack. */
if (addr >= 0 && addr < 19) {
tmp = get_reg(child, addr);
} else if (addr >= 21 && addr < 49) {
tmp = child->thread.fp[addr - 21];
if (regno >= 0 && regno < 19) {
tmp = get_reg(child, regno);
} else if (regno >= 21 && regno < 49) {
tmp = child->thread.fp[regno - 21];
/* Convert internal fpu reg representation
* 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 & 0x0000ffff) << 16);
} else
goto out_eio;
ret = put_user(tmp, (unsigned long *)data);
ret = put_user(tmp, datap);
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)
goto out_eio;
addr >>= 2; /* temporary hack. */
if (addr == PT_SR) {
if (regno == PT_SR) {
data &= SR_MASK;
data |= get_reg(child, PT_SR) & ~SR_MASK;
}
if (addr >= 0 && addr < 19) {
if (put_reg(child, addr, data))
if (regno >= 0 && regno < 19) {
if (put_reg(child, regno, data))
goto out_eio;
} else if (addr >= 21 && addr < 48) {
} else if (regno >= 21 && regno < 48) {
/* Convert long double format
* into internal fpu reg representation
*/
if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
data = (unsigned long)data << 15;
if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
data <<= 15;
data = (data & 0xffff0000) |
((data & 0x0000ffff) >> 1);
}
child->thread.fp[addr - 21] = data;
child->thread.fp[regno - 21] = data;
} else
goto out_eio;
break;
@ -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. */
for (i = 0; i < 19; i++) {
tmp = get_reg(child, i);
ret = put_user(tmp, (unsigned long *)data);
ret = put_user(tmp, datap);
if (ret)
break;
data += sizeof(long);
datap++;
}
break;
case PTRACE_SETREGS: /* Set all gp regs in the child. */
for (i = 0; i < 19; i++) {
ret = get_user(tmp, (unsigned long *)data);
ret = get_user(tmp, datap);
if (ret)
break;
if (i == PT_SR) {
@ -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;
}
put_reg(child, i, tmp);
data += sizeof(long);
datap++;
}
break;
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)))
ret = -EFAULT;
break;
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)))
ret = -EFAULT;
break;
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *)data);
ret = put_user(task_thread_info(child)->tp_value, datap);
break;
default:

View File

@ -112,9 +112,12 @@ void ptrace_disable(struct task_struct *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 regno = addr >> 2;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
/* 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)
unsigned long tmp;
ret = -EIO;
if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
if ((addr & 3) || addr > sizeof(struct user) - 3)
break;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
ret = -EIO;
if (addr < 19) {
tmp = get_reg(child, addr);
if (addr == PT_SR)
if (regno < 19) {
tmp = get_reg(child, regno);
if (regno == PT_SR)
tmp >>= 16;
} else if (addr >= 21 && addr < 49) {
tmp = child->thread.fp[addr - 21];
} else if (addr == 49) {
} else if (regno >= 21 && regno < 49) {
tmp = child->thread.fp[regno - 21];
} else if (regno == 49) {
tmp = child->mm->start_code;
} else if (addr == 50) {
} else if (regno == 50) {
tmp = child->mm->start_data;
} else if (addr == 51) {
} else if (regno == 51) {
tmp = child->mm->end_code;
} else
break;
ret = put_user(tmp,(unsigned long *) data);
ret = put_user(tmp, datap);
break;
}
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
if ((addr & 3) || addr > sizeof(struct user) - 3)
break;
addr = addr >> 2; /* temporary hack. */
if (addr == PT_SR) {
if (regno == PT_SR) {
data &= SR_MASK;
data <<= 16;
data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
}
if (addr < 19) {
if (put_reg(child, addr, data))
if (regno < 19) {
if (put_reg(child, regno, data))
break;
ret = 0;
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;
}
break;
@ -180,11 +178,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = get_reg(child, i);
if (i == PT_SR)
tmp >>= 16;
if (put_user(tmp, (unsigned long *) data)) {
if (put_user(tmp, datap)) {
ret = -EFAULT;
break;
}
data += sizeof(long);
datap++;
}
ret = 0;
break;
@ -194,7 +192,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int i;
unsigned long tmp;
for (i = 0; i < 19; i++) {
if (get_user(tmp, (unsigned long *) data)) {
if (get_user(tmp, datap)) {
ret = -EFAULT;
break;
}
@ -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);
}
put_reg(child, i, tmp);
data += sizeof(long);
datap++;
}
ret = 0;
break;
@ -213,7 +211,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_GETFPREGS
case PTRACE_GETFPREGS: { /* Get the child FPU state. */
ret = 0;
if (copy_to_user((void *)data, &child->thread.fp,
if (copy_to_user(datap, &child->thread.fp,
sizeof(struct user_m68kfp_struct)))
ret = -EFAULT;
break;
@ -223,7 +221,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_SETFPREGS
case PTRACE_SETFPREGS: { /* Set the child FPU state. */
ret = 0;
if (copy_from_user(&child->thread.fp, (void *)data,
if (copy_from_user(&child->thread.fp, datap,
sizeof(struct user_m68kfp_struct)))
ret = -EFAULT;
break;
@ -231,8 +229,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *)data);
ret = put_user(task_thread_info(child)->tp_value, datap);
break;
default:

View File

@ -73,7 +73,8 @@ static microblaze_reg_t *reg_save_addr(unsigned 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;
unsigned long val = 0;
@ -99,7 +100,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
} else {
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);
if (request == PTRACE_PEEKUSR)
val = *reg_addr;

View File

@ -839,7 +839,7 @@ struct bridge_controller {
nasid_t nasid;
unsigned int widget_id;
unsigned int irq_cpu;
dma64_addr_t baddr;
u64 baddr;
unsigned int pci_int[8];
};

View File

@ -255,9 +255,13 @@ int ptrace_set_watch_regs(struct task_struct *child,
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;
void __user *addrp = (void __user *) addr;
void __user *datavp = (void __user *) data;
unsigned long __user *datalp = (void __user *) data;
switch (request) {
/* 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)
ret = -EIO;
goto out;
}
ret = put_user(tmp, (unsigned long __user *) data);
ret = put_user(tmp, datalp);
break;
}
@ -478,34 +482,31 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (__s64 __user *) data);
ret = ptrace_getregs(child, datavp);
break;
case PTRACE_SETREGS:
ret = ptrace_setregs(child, (__s64 __user *) data);
ret = ptrace_setregs(child, datavp);
break;
case PTRACE_GETFPREGS:
ret = ptrace_getfpregs(child, (__u32 __user *) data);
ret = ptrace_getfpregs(child, datavp);
break;
case PTRACE_SETFPREGS:
ret = ptrace_setfpregs(child, (__u32 __user *) data);
ret = ptrace_setfpregs(child, datavp);
break;
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value,
(unsigned long __user *) data);
ret = put_user(task_thread_info(child)->tp_value, datalp);
break;
case PTRACE_GET_WATCH_REGS:
ret = ptrace_get_watch_regs(child,
(struct pt_watch_regs __user *) addr);
ret = ptrace_get_watch_regs(child, addrp);
break;
case PTRACE_SET_WATCH_REGS:
ret = ptrace_set_watch_regs(child,
(struct pt_watch_regs __user *) addr);
ret = ptrace_set_watch_regs(child, addrp);
break;
default:

View File

@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr)
return;
}
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
#ifdef CONFIG_DEBUG_HIGHMEM
{
int idx = type + KM_TYPE_NR * smp_processor_id();
@ -89,6 +89,7 @@ void __kunmap_atomic(void *kvaddr)
local_flush_tlb_one(vaddr);
}
#endif
kmap_atomic_idx_pop();
pagefault_enable();
}
EXPORT_SYMBOL(__kunmap_atomic);

View File

@ -101,7 +101,7 @@ static inline void __kunmap_atomic(unsigned long vaddr)
return;
}
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
#if HIGHMEM_DEBUG
{
@ -119,6 +119,8 @@ static inline void __kunmap_atomic(unsigned long vaddr)
__flush_tlb_one(vaddr);
}
#endif
kmap_atomic_idx_pop();
pagefault_enable();
}
#endif /* __KERNEL__ */

View File

@ -295,31 +295,31 @@ void ptrace_disable(struct task_struct *child)
/*
* 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;
int ret;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
if ((addr & 3) || addr > sizeof(struct user) - 3)
break;
tmp = 0; /* Default return condition */
if (addr < NR_PTREGS << 2)
tmp = get_stack_long(child,
ptrace_regid_to_frame[addr]);
ret = put_user(tmp, (unsigned long *) data);
ret = put_user(tmp, datap);
break;
/* write the word at location addr in the USER area */
case PTRACE_POKEUSR:
ret = -EIO;
if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
if ((addr & 3) || addr > sizeof(struct user) - 3)
break;
ret = 0;
@ -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,
REGSET_GENERAL,
0, NR_PTREGS * sizeof(long),
(void __user *)data);
datap);
case PTRACE_SETREGS: /* Set all integer regs in the child. */
return copy_regset_from_user(child, &user_mn10300_native_view,
REGSET_GENERAL,
0, NR_PTREGS * sizeof(long),
(const void __user *)data);
datap);
case PTRACE_GETFPREGS: /* Get the child FPU state. */
return copy_regset_to_user(child, &user_mn10300_native_view,
REGSET_FPU,
0, sizeof(struct fpu_state_struct),
(void __user *)data);
datap);
case PTRACE_SETFPREGS: /* Set the child FPU state. */
return copy_regset_from_user(child, &user_mn10300_native_view,
REGSET_FPU,
0, sizeof(struct fpu_state_struct),
(const void __user *)data);
datap);
default:
ret = ptrace_request(child, request, addr, data);

View File

@ -110,7 +110,8 @@ void user_enable_block_step(struct task_struct *task)
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;
long ret = -EIO;
@ -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
processes, the kernel saves all regs on a syscall. */
case PTRACE_PEEKUSR:
if ((addr & (sizeof(long)-1)) ||
(unsigned long) addr >= sizeof(struct pt_regs))
if ((addr & (sizeof(unsigned long)-1)) ||
addr >= sizeof(struct pt_regs))
break;
tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
ret = put_user(tmp, (unsigned long *) data);
ret = put_user(tmp, (unsigned long __user *) data);
break;
/* 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)
break;
}
if ((addr & (sizeof(long)-1)) ||
(unsigned long) addr >= sizeof(struct pt_regs))
if ((addr & (sizeof(unsigned long)-1)) ||
addr >= sizeof(struct pt_regs))
break;
if ((addr >= PT_GR1 && addr <= PT_GR31) ||
addr == PT_IAOQ0 || addr == PT_IAOQ1 ||

View File

@ -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;
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;
unsigned long sec;
/* have to be a little careful about overflow */
ct = ms % 1000;
sec = ms / 1000;
ct = us % 1000000;
sec = us / 1000000;
if (ct) {
ct *= tb_ticks_per_sec;
do_div(ct, 1000);

View File

@ -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,
* 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,
long data)
static long arch_ptrace_old(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
void __user *datavp = (void __user *) data;
switch (request) {
case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_GPR, 0, 32 * sizeof(long),
(void __user *) data);
datavp);
case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_GPR, 0, 32 * sizeof(long),
(const void __user *) data);
datavp);
case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */
return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_FPR, 0, 32 * sizeof(double),
(void __user *) data);
datavp);
case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */
return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_FPR, 0, 32 * sizeof(double),
(const void __user *) data);
datavp);
}
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;
void __user *datavp = (void __user *) data;
unsigned long __user *datalp = datavp;
switch (request) {
/* 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)
ret = -EIO;
/* convert to index and check */
#ifdef CONFIG_PPC32
index = (unsigned long) addr >> 2;
index = addr >> 2;
if ((addr & 3) || (index > PT_FPSCR)
|| (child->thread.regs == NULL))
#else
index = (unsigned long) addr >> 3;
index = addr >> 3;
if ((addr & 7) || (index > PT_FPSCR))
#endif
break;
@ -1463,7 +1468,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
tmp = ((unsigned long *)child->thread.fpr)
[TS_FPRWIDTH * (index - PT_FPR0)];
}
ret = put_user(tmp,(unsigned long __user *) data);
ret = put_user(tmp, datalp);
break;
}
@ -1474,11 +1479,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO;
/* convert to index and check */
#ifdef CONFIG_PPC32
index = (unsigned long) addr >> 2;
index = addr >> 2;
if ((addr & 3) || (index > PT_FPSCR)
|| (child->thread.regs == NULL))
#else
index = (unsigned long) addr >> 3;
index = addr >> 3;
if ((addr & 7) || (index > PT_FPSCR))
#endif
break;
@ -1525,11 +1530,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
dbginfo.features = 0;
#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
if (!access_ok(VERIFY_WRITE, data,
if (!access_ok(VERIFY_WRITE, datavp,
sizeof(struct ppc_debug_info)))
return -EFAULT;
ret = __copy_to_user((struct ppc_debug_info __user *)data,
&dbginfo, sizeof(struct ppc_debug_info)) ?
ret = __copy_to_user(datavp, &dbginfo,
sizeof(struct ppc_debug_info)) ?
-EFAULT : 0;
break;
}
@ -1537,11 +1542,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PPC_PTRACE_SETHWDEBUG: {
struct ppc_hw_breakpoint bp_info;
if (!access_ok(VERIFY_READ, data,
if (!access_ok(VERIFY_READ, datavp,
sizeof(struct ppc_hw_breakpoint)))
return -EFAULT;
ret = __copy_from_user(&bp_info,
(struct ppc_hw_breakpoint __user *)data,
ret = __copy_from_user(&bp_info, datavp,
sizeof(struct ppc_hw_breakpoint)) ?
-EFAULT : 0;
if (!ret)
@ -1560,11 +1564,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (addr > 0)
break;
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
ret = put_user(child->thread.dac1,
(unsigned long __user *)data);
ret = put_user(child->thread.dac1, datalp);
#else
ret = put_user(child->thread.dabr,
(unsigned long __user *)data);
ret = put_user(child->thread.dabr, datalp);
#endif
break;
}
@ -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,
REGSET_GPR,
0, sizeof(struct pt_regs),
(void __user *) data);
datavp);
#ifdef CONFIG_PPC64
case PTRACE_SETREGS64:
@ -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,
REGSET_GPR,
0, sizeof(struct pt_regs),
(const void __user *) data);
datavp);
case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */
return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_FPR,
0, sizeof(elf_fpregset_t),
(void __user *) data);
datavp);
case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */
return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_FPR,
0, sizeof(elf_fpregset_t),
(const void __user *) data);
datavp);
#ifdef CONFIG_ALTIVEC
case PTRACE_GETVRREGS:
@ -1609,40 +1611,40 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
REGSET_VMX,
0, (33 * sizeof(vector128) +
sizeof(u32)),
(void __user *) data);
datavp);
case PTRACE_SETVRREGS:
return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_VMX,
0, (33 * sizeof(vector128) +
sizeof(u32)),
(const void __user *) data);
datavp);
#endif
#ifdef CONFIG_VSX
case PTRACE_GETVSRREGS:
return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_VSX,
0, 32 * sizeof(double),
(void __user *) data);
datavp);
case PTRACE_SETVSRREGS:
return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_VSX,
0, 32 * sizeof(double),
(const void __user *) data);
datavp);
#endif
#ifdef CONFIG_SPE
case PTRACE_GETEVRREGS:
/* Get the child spe register state. */
return copy_regset_to_user(child, &user_ppc_native_view,
REGSET_SPE, 0, 35 * sizeof(u32),
(void __user *) data);
datavp);
case PTRACE_SETEVRREGS:
/* Set the child spe register state. */
return copy_regset_from_user(child, &user_ppc_native_view,
REGSET_SPE, 0, 35 * sizeof(u32),
(const void __user *) data);
datavp);
#endif
/* Old reverse args ptrace callss */

View File

@ -62,7 +62,7 @@ void __kunmap_atomic(void *kvaddr)
return;
}
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
#ifdef CONFIG_DEBUG_HIGHMEM
{
@ -79,6 +79,8 @@ void __kunmap_atomic(void *kvaddr)
local_flush_tlb_page(NULL, vaddr);
}
#endif
kmap_atomic_idx_pop();
pagefault_enable();
}
EXPORT_SYMBOL(__kunmap_atomic);

View File

@ -50,6 +50,7 @@
#define RIO_ATMU_REGS_OFFSET 0x10c00
#define RIO_P_MSG_REGS_OFFSET 0x11000
#define RIO_S_MSG_REGS_OFFSET 0x13000
#define RIO_GCCSR 0x13c
#define RIO_ESCSR 0x158
#define RIO_CCSR 0x15c
#define RIO_LTLEDCSR 0x0608
@ -87,6 +88,9 @@
#define RIO_IPWSR_PWD 0x00000008
#define RIO_IPWSR_PWB 0x00000004
#define RIO_EPWISR_PINT 0x80000000
#define RIO_EPWISR_PW 0x00000001
#define RIO_MSG_DESC_SIZE 32
#define RIO_MSG_BUFFER_SIZE 4096
#define RIO_MIN_TX_RING_SIZE 2
@ -1082,19 +1086,13 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
struct rio_priv *priv = port->priv;
u32 epwisr, tmp;
epwisr = in_be32(priv->regs_win + RIO_EPWISR);
if (!(epwisr & RIO_EPWISR_PW))
goto pw_done;
ipwmr = in_be32(&priv->msg_regs->pwmr);
ipwsr = in_be32(&priv->msg_regs->pwsr);
epwisr = in_be32(priv->regs_win + RIO_EPWISR);
if (epwisr & 0x80000000) {
tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
pr_info("RIO_LTLEDCSR = 0x%x\n", tmp);
out_be32(priv->regs_win + RIO_LTLEDCSR, 0);
}
if (!(epwisr & 0x00000001))
return IRQ_HANDLED;
#ifdef DEBUG_PW
pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr);
if (ipwsr & RIO_IPWSR_QF)
@ -1109,20 +1107,6 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
pr_debug(" PWB");
pr_debug(" )\n");
#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 */
if (ipwsr & RIO_IPWSR_QFI) {
/* Save PW message (if there is room in FIFO),
@ -1134,16 +1118,43 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
RIO_PW_MSG_SIZE);
} else {
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);
}
/* 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);
}
/* Issue Clear Queue command. This allows another
* port-write to be received.
*/
out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ);
if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) {
priv->port_write_msg.err_count++;
pr_debug("RIO: Port-Write Transaction Err (%d)\n",
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;
}
@ -1461,6 +1472,7 @@ int fsl_rio_setup(struct platform_device *dev)
port->host_deviceid = fsl_rio_get_hdid(port->id);
port->priv = priv;
port->phys_efptr = 0x100;
rio_register_mport(port);
priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
@ -1508,6 +1520,12 @@ int fsl_rio_setup(struct platform_device *dev)
dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
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
+ RIO_ATMU_REGS_OFFSET);
priv->maint_atmu_regs = priv->atmu_regs + 1;

View File

@ -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
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
msecs_to_cputime(const unsigned int m)
usecs_to_cputime(const unsigned int m)
{
return (cputime_t) m * 4096000;
return (cputime_t) m * 4096;
}
/*

View File

@ -343,7 +343,8 @@ poke_user(struct task_struct *child, addr_t addr, addr_t 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;
int copied, ret;

View File

@ -325,7 +325,8 @@ void ptrace_disable(struct task_struct *child)
}
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;
unsigned long __user *datap = (void __user *)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,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(void __user *)datap);
datap);
break;
case PTRACE_SETREGS:
ret = copy_regset_from_user(child, &user_score_native_view,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(const void __user *)datap);
datap);
break;
default:

View File

@ -365,9 +365,9 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
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;
int ret;
@ -383,17 +383,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (addr < sizeof(struct pt_regs))
tmp = get_stack_long(child, addr);
else if (addr >= (long) &dummy->fpu &&
addr < (long) &dummy->u_fpvalid) {
else if (addr >= offsetof(struct user, fpu) &&
addr < offsetof(struct user, u_fpvalid)) {
if (!tsk_used_math(child)) {
if (addr == (long)&dummy->fpu.fpscr)
if (addr == offsetof(struct user, fpu.fpscr))
tmp = FPSCR_INIT;
else
tmp = 0;
} else
tmp = ((long *)child->thread.xstate)
[(addr - (long)&dummy->fpu) >> 2];
} else if (addr == (long) &dummy->u_fpvalid)
} else {
unsigned long index;
index = addr - offsetof(struct user, fpu);
tmp = ((unsigned long *)child->thread.xstate)
[index >> 2];
}
} else if (addr == offsetof(struct user, u_fpvalid))
tmp = !!tsk_used_math(child);
else if (addr == PT_TEXT_ADDR)
tmp = child->mm->start_code;
@ -417,13 +420,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if (addr < sizeof(struct pt_regs))
ret = put_stack_long(child, addr, data);
else if (addr >= (long) &dummy->fpu &&
addr < (long) &dummy->u_fpvalid) {
else if (addr >= offsetof(struct user, fpu) &&
addr < offsetof(struct user, u_fpvalid)) {
unsigned long index;
index = addr - offsetof(struct user, fpu);
set_stopped_child_used_math(child);
((long *)child->thread.xstate)
[(addr - (long)&dummy->fpu) >> 2] = data;
((unsigned long *)child->thread.xstate)
[index >> 2] = data;
ret = 0;
} else if (addr == (long) &dummy->u_fpvalid) {
} else if (addr == offsetof(struct user, u_fpvalid)) {
conditional_stopped_child_used_math(data, child);
ret = 0;
}
@ -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,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(void __user *)data);
datap);
case PTRACE_SETREGS:
return copy_regset_from_user(child, &user_sh_native_view,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(const void __user *)data);
datap);
#ifdef CONFIG_SH_FPU
case PTRACE_GETFPREGS:
return copy_regset_to_user(child, &user_sh_native_view,
REGSET_FPU,
0, sizeof(struct user_fpu_struct),
(void __user *)data);
datap);
case PTRACE_SETFPREGS:
return copy_regset_from_user(child, &user_sh_native_view,
REGSET_FPU,
0, sizeof(struct user_fpu_struct),
(const void __user *)data);
datap);
#endif
#ifdef CONFIG_SH_DSP
case PTRACE_GETDSPREGS:
return copy_regset_to_user(child, &user_sh_native_view,
REGSET_DSP,
0, sizeof(struct pt_dspregs),
(void __user *)data);
datap);
case PTRACE_SETDSPREGS:
return copy_regset_from_user(child, &user_sh_native_view,
REGSET_DSP,
0, sizeof(struct pt_dspregs),
(const void __user *)data);
datap);
#endif
default:
ret = ptrace_request(child, request, addr, data);

View File

@ -383,9 +383,11 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
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;
unsigned long __user *datap = (unsigned long __user *) data;
switch (request) {
/* 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)
tmp = get_stack_long(child, addr);
else if ((addr >= offsetof(struct user, fpu)) &&
(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)) {
tmp = !!tsk_used_math(child);
} else {
break;
}
ret = put_user(tmp, (unsigned long *)data);
ret = put_user(tmp, datap);
break;
}
@ -437,7 +441,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
else if ((addr >= offsetof(struct user, fpu)) &&
(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;
@ -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,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(void __user *)data);
datap);
case PTRACE_SETREGS:
return copy_regset_from_user(child, &user_sh64_native_view,
REGSET_GENERAL,
0, sizeof(struct pt_regs),
(const void __user *)data);
datap);
#ifdef CONFIG_SH_FPU
case PTRACE_GETFPREGS:
return copy_regset_to_user(child, &user_sh64_native_view,
REGSET_FPU,
0, sizeof(struct user_fpu_struct),
(void __user *)data);
datap);
case PTRACE_SETFPREGS:
return copy_regset_from_user(child, &user_sh64_native_view,
REGSET_FPU,
0, sizeof(struct user_fpu_struct),
(const void __user *)data);
datap);
#endif
default:
ret = ptrace_request(child, request, addr, data);
@ -471,7 +477,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
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
static unsigned long first_call;

View File

@ -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)
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
_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)
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
_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
{

View File

@ -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)
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
_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)
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
_memcpy_toio(volatile void __iomem *dst, const void *src, __kernel_size_t n)
{

View File

@ -38,7 +38,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
* types on sparc64. However, it requires that the device
* 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
#ifdef CONFIG_PCI

View File

@ -323,18 +323,35 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
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];
void __user *addr2p;
const struct user_regset_view *view;
struct pt_regs __user *pregs;
struct fps __user *fps;
int ret;
view = task_user_regset_view(current);
addr2p = (void __user *) addr2;
pregs = (struct pt_regs __user *) addr;
fps = (struct fps __user *) addr;
switch(request) {
case PTRACE_GETREGS: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
32 * sizeof(u32),
4 * sizeof(u32),
@ -348,8 +365,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
case PTRACE_SETREGS: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
32 * sizeof(u32),
4 * sizeof(u32),
@ -363,19 +378,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
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,
0 * sizeof(u32),
32 * sizeof(u32),
@ -397,19 +399,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
}
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,
0 * sizeof(u32),
32 * sizeof(u32),
@ -424,8 +413,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_READTEXT:
case PTRACE_READDATA:
ret = ptrace_readdata(child, addr,
(void __user *) addr2, data);
ret = ptrace_readdata(child, addr, addr2p, data);
if (ret == data)
ret = 0;
@ -435,8 +423,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA:
ret = ptrace_writedata(child, (void __user *) addr2,
addr, data);
ret = ptrace_writedata(child, addr2p, addr, data);
if (ret == data)
ret = 0;

View File

@ -969,16 +969,19 @@ struct fps {
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);
unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
struct pt_regs __user *pregs;
struct fps __user *fps;
void __user *addr2p;
int ret;
pregs = (struct pt_regs __user *) (unsigned long) addr;
fps = (struct fps __user *) (unsigned long) addr;
pregs = (struct pt_regs __user *) addr;
fps = (struct fps __user *) addr;
addr2p = (void __user *) addr2;
switch (request) {
case PTRACE_PEEKUSR:
@ -1029,8 +1032,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_READTEXT:
case PTRACE_READDATA:
ret = ptrace_readdata(child, addr,
(char __user *)addr2, data);
ret = ptrace_readdata(child, addr, addr2p, data);
if (ret == data)
ret = 0;
else if (ret >= 0)
@ -1039,8 +1041,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA:
ret = ptrace_writedata(child, (char __user *) addr2,
addr, data);
ret = ptrace_writedata(child, addr2p, addr, data);
if (ret == data)
ret = 0;
else if (ret >= 0)

View File

@ -75,7 +75,7 @@ void __kunmap_atomic(void *kvaddr)
return;
}
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
#ifdef CONFIG_DEBUG_HIGHMEM
{
@ -104,6 +104,8 @@ void __kunmap_atomic(void *kvaddr)
#endif
}
#endif
kmap_atomic_idx_pop();
pagefault_enable();
}
EXPORT_SYMBOL(__kunmap_atomic);

View File

@ -58,6 +58,9 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING
config ARCH_PHYS_ADDR_T_64BIT
def_bool y
config ARCH_DMA_ADDR_T_64BIT
def_bool y
config LOCKDEP_SUPPORT
def_bool y

View File

@ -45,7 +45,8 @@ void ptrace_disable(struct task_struct *child)
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 tmp;
@ -57,7 +58,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
switch (request) {
case PTRACE_PEEKUSR: /* Read register from pt_regs. */
if (addr < 0 || addr >= PTREGS_SIZE)
if (addr >= PTREGS_SIZE)
break;
childreg = (char *)task_pt_regs(child) + addr;
#ifdef CONFIG_COMPAT
@ -76,7 +77,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_POKEUSR: /* Write register in pt_regs. */
if (addr < 0 || addr >= PTREGS_SIZE)
if (addr >= PTREGS_SIZE)
break;
childreg = (char *)task_pt_regs(child) + addr;
#ifdef CONFIG_COMPAT
@ -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))
break;
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]);
if (ret != 0)
break;
@ -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))
break;
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]);
if (ret != 0)
break;

View File

@ -30,8 +30,6 @@
#include <linux/timex.h>
#include <asm/setup.h>
#include <asm/sections.h>
#include <asm/sections.h>
#include <asm/cacheflush.h>
#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>

View File

@ -241,7 +241,7 @@ void __kunmap_atomic(void *kvaddr)
pte_t pteval = *pte;
int idx, type;
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
idx = type + KM_TYPE_NR*smp_processor_id();
/*
@ -252,6 +252,7 @@ void __kunmap_atomic(void *kvaddr)
BUG_ON(!pte_present(pteval) && !pte_migrating(pteval));
kmap_atomic_unregister(pte_page(pteval), vaddr);
kpte_clear_flush(pte, vaddr);
kmap_atomic_idx_pop();
} else {
/* Must be a lowmem page */
BUG_ON(vaddr < PAGE_OFFSET);

View File

@ -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 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;
unsigned long __user *p = (void __user *)(unsigned long)data;
unsigned long __user *p = (void __user *)data;
void __user *vp = p;
switch (request) {
/* read word at location addr. */
@ -107,24 +109,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#endif
#ifdef PTRACE_GETFPREGS
case PTRACE_GETFPREGS: /* Get the child FPU state. */
ret = get_fpregs((struct user_i387_struct __user *) data,
child);
ret = get_fpregs(vp, child);
break;
#endif
#ifdef PTRACE_SETFPREGS
case PTRACE_SETFPREGS: /* Set the child FPU state. */
ret = set_fpregs((struct user_i387_struct __user *) data,
child);
ret = set_fpregs(vp, child);
break;
#endif
case PTRACE_GET_THREAD_AREA:
ret = ptrace_get_thread_area(child, addr,
(struct user_desc __user *) data);
ret = ptrace_get_thread_area(child, addr, vp);
break;
case PTRACE_SET_THREAD_AREA:
ret = ptrace_set_thread_area(child, addr,
(struct user_desc __user *) data);
ret = ptrace_set_thread_area(child, addr, datavp);
break;
case PTRACE_FAULTINFO: {
@ -134,7 +132,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* On i386, ptrace_faultinfo is smaller!
*/
ret = copy_to_user(p, &child->thread.arch.faultinfo,
sizeof(struct ptrace_faultinfo));
sizeof(struct ptrace_faultinfo)) ?
-EIO : 0;
break;
}
@ -158,7 +157,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
#ifdef PTRACE_ARCH_PRCTL
case PTRACE_ARCH_PRCTL:
/* 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;
#endif
default:

View File

@ -203,8 +203,8 @@ int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
(unsigned long *) &fpregs);
}
long subarch_ptrace(struct task_struct *child, long request, long addr,
long data)
long subarch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
return -EIO;
}

View File

@ -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);
}
long subarch_ptrace(struct task_struct *child, long request, long addr,
long data)
long subarch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
int ret = -EIO;
void __user *datap = (void __user *) data;
switch (request) {
case PTRACE_GETFPXREGS: /* Get the child FPU state. */
ret = get_fpregs((struct user_i387_struct __user *) data,
child);
ret = get_fpregs(datap, child);
break;
case PTRACE_SETFPXREGS: /* Set the child FPU state. */
ret = set_fpregs((struct user_i387_struct __user *) data,
child);
ret = set_fpregs(datap, child);
break;
}

View File

@ -801,7 +801,8 @@ void ptrace_disable(struct task_struct *child)
static const struct user_regset_view user_x86_32_view; /* Initialized below. */
#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;
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)
unsigned long tmp;
ret = -EIO;
if ((addr & (sizeof(data) - 1)) || addr < 0 ||
addr >= sizeof(struct user))
if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
break;
tmp = 0; /* Default return condition */
@ -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 */
ret = -EIO;
if ((addr & (sizeof(data) - 1)) || addr < 0 ||
addr >= sizeof(struct user))
if ((addr & (sizeof(data) - 1)) || addr >= sizeof(struct user))
break;
if (addr < sizeof(struct user_regs_struct))
@ -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
case PTRACE_GET_THREAD_AREA:
if (addr < 0)
if ((int) addr < 0)
return -EIO;
ret = do_get_thread_area(child, addr,
(struct user_desc __user *) data);
(struct user_desc __user *)data);
break;
case PTRACE_SET_THREAD_AREA:
if (addr < 0)
if ((int) addr < 0)
return -EIO;
ret = do_set_thread_area(child, addr,
(struct user_desc __user *) data, 0);
(struct user_desc __user *)data, 0);
break;
#endif

View File

@ -74,7 +74,7 @@ void __kunmap_atomic(void *kvaddr)
vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
int idx, type;
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
idx = type + KM_TYPE_NR * smp_processor_id();
#ifdef CONFIG_DEBUG_HIGHMEM
@ -87,6 +87,7 @@ void __kunmap_atomic(void *kvaddr)
* attributes or becomes a protected page in a hypervisor.
*/
kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
}
#ifdef CONFIG_DEBUG_HIGHMEM
else {

View File

@ -51,7 +51,6 @@
#include <asm/numa.h>
#include <asm/cacheflush.h>
#include <asm/init.h>
#include <linux/bootmem.h>
static int __init parse_direct_gbpages_off(char *arg)
{

View File

@ -98,7 +98,7 @@ iounmap_atomic(void __iomem *kvaddr)
vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
int idx, type;
type = kmap_atomic_idx_pop();
type = kmap_atomic_idx();
idx = type + KM_TYPE_NR * smp_processor_id();
#ifdef CONFIG_DEBUG_HIGHMEM
@ -111,6 +111,7 @@ iounmap_atomic(void __iomem *kvaddr)
* attributes or becomes a protected page in a hypervisor.
*/
kpte_clear_flush(kmap_pte-idx, vaddr);
kmap_atomic_idx_pop();
}
pagefault_enable();

View File

@ -59,7 +59,6 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/reboot.h>
#include <asm/setup.h>
#include <asm/stackprotector.h>
#include <asm/hypervisor.h>

View File

@ -256,9 +256,11 @@ int ptrace_pokeusr(struct task_struct *child, long regno, long val)
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;
void __user *datap = (void __user *) data;
switch (request) {
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)
break;
case PTRACE_PEEKUSR: /* read register specified by addr. */
ret = ptrace_peekusr(child, addr, (void __user *) data);
ret = ptrace_peekusr(child, addr, datap);
break;
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)
break;
case PTRACE_GETREGS:
ret = ptrace_getregs(child, (void __user *) data);
ret = ptrace_getregs(child, datap);
break;
case PTRACE_SETREGS:
ret = ptrace_setregs(child, (void __user *) data);
ret = ptrace_setregs(child, datap);
break;
case PTRACE_GETXTREGS:
ret = ptrace_getxregs(child, (void __user *) data);
ret = ptrace_getxregs(child, datap);
break;
case PTRACE_SETXTREGS:
ret = ptrace_setxregs(child, (void __user *) data);
ret = ptrace_setxregs(child, datap);
break;
default:

View File

@ -566,6 +566,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_
struct mailbox mailbox;
/* Got a packet for us */
memset(&st_loc, 0, sizeof(st_loc));
ret = do_ac_read(i, buf, &st_loc, &mailbox);
spin_unlock_irqrestore(&apbs[i].mutex, flags);
set_current_state(TASK_RUNNING);

View File

@ -713,7 +713,6 @@ static int khvcd(void *unused)
struct hvc_struct *hp;
set_freezable();
__set_current_state(TASK_RUNNING);
do {
poll_mask = 0;
hvc_kicked = 0;

View File

@ -4,5 +4,5 @@
obj-$(CONFIG_COMPUTONE) += ip2.o
ip2-objs := ip2main.o
ip2-y := ip2main.o

View File

@ -2,7 +2,7 @@
# 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_DEVICE_INTERFACE) += ipmi_devintf.o

View File

@ -916,7 +916,7 @@ static struct ipmi_smi_watcher smi_watcher =
.smi_gone = ipmi_smi_gone,
};
static __init int init_ipmi_devintf(void)
static int __init init_ipmi_devintf(void)
{
int rv;
@ -954,7 +954,7 @@ static __init int init_ipmi_devintf(void)
}
module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void)
static void __exit cleanup_ipmi(void)
{
struct ipmi_reg_list *entry, *entry2;
mutex_lock(&reg_list_mutex);

View File

@ -4442,13 +4442,13 @@ static int ipmi_init_msghandler(void)
return 0;
}
static __init int ipmi_init_msghandler_mod(void)
static int __init ipmi_init_msghandler_mod(void)
{
ipmi_init_msghandler();
return 0;
}
static __exit void cleanup_ipmi(void)
static void __exit cleanup_ipmi(void)
{
int count;

View File

@ -1846,7 +1846,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
return rv;
}
static __devinit void hardcode_find_bmc(void)
static void __devinit hardcode_find_bmc(void)
{
int i;
struct smi_info *info;
@ -2029,7 +2029,7 @@ struct SPMITable {
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;
@ -2112,7 +2112,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
return 0;
}
static __devinit void spmi_find_bmc(void)
static void __devinit spmi_find_bmc(void)
{
acpi_status status;
struct SPMITable *spmi;
@ -2325,7 +2325,7 @@ static int __devinit decode_dmi(const struct dmi_header *dm,
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;
@ -3012,7 +3012,7 @@ static __devinitdata struct ipmi_default_vals
{ .port = 0 }
};
static __devinit void default_find_bmc(void)
static void __devinit default_find_bmc(void)
{
struct smi_info *info;
int i;
@ -3312,7 +3312,7 @@ static int try_smi_init(struct smi_info *new_smi)
return rv;
}
static __devinit int init_ipmi_si(void)
static int __devinit init_ipmi_si(void)
{
int i;
char *str;
@ -3525,7 +3525,7 @@ static void cleanup_one_si(struct smi_info *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;

View File

@ -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.
* 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) {
case 0:
mmtimer_setup_int_0(cpu, expires);
@ -191,7 +191,8 @@ static int mmtimer_setup(int cpu, int comparator, unsigned long expires)
break;
}
/* We might've missed our expiration time */
if (rtc_time() <= expires)
*set_completion_time = rtc_time();
if (*set_completion_time <= expires)
return 1;
/*
@ -227,6 +228,8 @@ static int mmtimer_disable_int(long nasid, int comparator)
#define TIMER_OFF 0xbadcabLL /* Timer is not setup */
#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 */
struct mmtimer {
struct rb_node list;
@ -242,6 +245,11 @@ struct mmtimer_node {
};
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.
@ -289,7 +297,8 @@ static void mmtimer_set_next_timer(int nodeid)
struct mmtimer_node *n = &timers[nodeid];
struct mmtimer *x;
struct k_itimer *t;
int o;
u64 expires, exp, set_completion_time;
int i;
restart:
if (n->next == NULL)
@ -300,7 +309,8 @@ restart:
if (!t->it.mmtimer.incr) {
/* Not an interval timer */
if (!mmtimer_setup(x->cpu, COMPARATOR,
t->it.mmtimer.expires)) {
t->it.mmtimer.expires,
&set_completion_time)) {
/* Late setup, fire now */
tasklet_schedule(&n->tasklet);
}
@ -308,14 +318,23 @@ restart:
}
/* Interval timer */
o = 0;
while (!mmtimer_setup(x->cpu, COMPARATOR, t->it.mmtimer.expires)) {
unsigned long e, e1;
struct rb_node *next;
t->it.mmtimer.expires += t->it.mmtimer.incr << o;
t->it_overrun += 1 << o;
o++;
if (o > 20) {
i = 0;
expires = exp = t->it.mmtimer.expires;
while (!mmtimer_setup(x->cpu, COMPARATOR, expires,
&set_completion_time)) {
int to;
i++;
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");
t->it.mmtimer.clock = TIMER_OFF;
n->next = rb_next(&x->list);
@ -323,21 +342,6 @@ restart:
kfree(x);
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;
}
}
}

View File

@ -6,10 +6,10 @@
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
# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES
# To compile in lots (~20 KiB) of run-time enablable printk()s for debugging:
EXTRA_CFLAGS += -DMW_TRACE
ccflags-y := -DMW_TRACE

View File

@ -303,6 +303,7 @@ static void mxser_enable_must_enchance_mode(unsigned long baseio)
outb(oldlcr, baseio + UART_LCR);
}
#ifdef CONFIG_PCI
static void mxser_disable_must_enchance_mode(unsigned long baseio)
{
u8 oldlcr;
@ -317,6 +318,7 @@ static void mxser_disable_must_enchance_mode(unsigned long baseio)
outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
outb(oldlcr, baseio + UART_LCR);
}
#endif
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)
outb(oldlcr, baseio + UART_LCR);
}
#ifdef CONFIG_PCI
static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
{
u8 oldlcr;
@ -404,6 +407,7 @@ static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
*pId = inb(baseio + MOXA_MUST_HWID_REGISTER);
outb(oldlcr, baseio + UART_LCR);
}
#endif
static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio)
{

View File

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

View File

@ -613,6 +613,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case PPGETTIME:
to_jiffies = pp->pdev->timeout;
memset(&par_timeout, 0, sizeof(par_timeout));
par_timeout.tv_sec = to_jiffies / HZ;
par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ);
if (copy_to_user (argp, &par_timeout, sizeof(struct timeval)))

View File

@ -25,6 +25,8 @@
#include <linux/time.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/ramoops.h>
#define RAMOOPS_KERNMSG_HDR "===="
#define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval))
@ -91,11 +93,17 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
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;
int err = -EINVAL;
if (pdata) {
mem_size = pdata->mem_size;
mem_address = pdata->mem_address;
}
if (!mem_size) {
printk(KERN_ERR "ramoops: invalid size specification");
goto fail3;
@ -142,7 +150,7 @@ fail3:
return err;
}
static void __exit ramoops_exit(void)
static int __exit ramoops_remove(struct platform_device *pdev)
{
struct ramoops_context *cxt = &oops_cxt;
@ -151,8 +159,26 @@ static void __exit ramoops_exit(void)
iounmap(cxt->virt_addr);
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_exit(ramoops_exit);

View File

@ -8,5 +8,5 @@
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

View File

@ -2345,7 +2345,7 @@ static int __init rp_init(void)
ret = tty_register_driver(rocket_driver);
if (ret < 0) {
printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
goto err_tty;
goto err_controller;
}
#ifdef ROCKET_DEBUG_OPEN
@ -2380,6 +2380,9 @@ static int __init rp_init(void)
return 0;
err_ttyu:
tty_unregister_driver(rocket_driver);
err_controller:
if (controller)
release_region(controller, 4);
err_tty:
put_tty_driver(rocket_driver);
err:

View File

@ -301,6 +301,8 @@ struct slgt_info {
unsigned int rx_pio;
unsigned int if_mode;
unsigned int base_clock;
unsigned int xsync;
unsigned int xctrl;
/* device status */
@ -405,6 +407,8 @@ static MGSL_PARAMS default_params = {
#define TDCSR 0x94 /* tx DMA control/status */
#define RDDAR 0x98 /* rx 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 RXBREAK BIT14
@ -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 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 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
@ -1056,6 +1064,14 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return get_gpio(info, argp);
case MGSL_IOCWAITGPIO:
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);
switch (cmd) {
@ -1132,6 +1148,7 @@ static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *us
struct MGSL_PARAMS32 tmp_params;
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.loopback = info->params.loopback;
tmp_params.flags = info->params.flags;
@ -1212,12 +1229,16 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCSGPIO:
case MGSL_IOCGGPIO:
case MGSL_IOCWAITGPIO:
case MGSL_IOCGXSYNC:
case MGSL_IOCGXCTRL:
case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE:
case MGSL_IOCTXABORT:
case TIOCMIWAIT:
case MGSL_IOCSIF:
case MGSL_IOCSXSYNC:
case MGSL_IOCSXCTRL:
rc = ioctl(tty, file, cmd, arg);
break;
}
@ -1617,6 +1638,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (cmd != SIOCWANDEV)
return hdlc_ioctl(dev, ifr, cmd);
memset(&new_line, 0, sizeof(new_line));
switch(ifr->ifr_settings.type) {
case IF_GET_IFACE: /* return current sync_serial_settings */
@ -1958,6 +1981,7 @@ static void bh_handler(struct work_struct *work)
case MGSL_MODE_RAW:
case MGSL_MODE_MONOSYNC:
case MGSL_MODE_BISYNC:
case MGSL_MODE_XSYNC:
while(rx_get_buf(info));
break;
}
@ -2357,26 +2381,27 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
spin_lock(&info->lock);
while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
info->irq_occurred = true;
for(i=0; i < info->port_count ; i++) {
if (info->port_array[i] == NULL)
continue;
spin_lock(&info->port_array[i]->lock);
if (gsr & (BIT8 << i))
isr_serial(info->port_array[i]);
if (gsr & (BIT16 << (i*2)))
isr_rdma(info->port_array[i]);
if (gsr & (BIT17 << (i*2)))
isr_tdma(info->port_array[i]);
spin_unlock(&info->port_array[i]->lock);
}
}
if (info->gpio_present) {
unsigned int state;
unsigned int changed;
spin_lock(&info->lock);
while ((changed = rd_reg32(info, IOSR)) != 0) {
DBGISR(("%s iosr=%08x\n", info->device_name, changed));
/* read latched state of GPIO signals */
@ -2388,22 +2413,24 @@ static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
isr_gpio(info->port_array[i], changed, state);
}
}
spin_unlock(&info->lock);
}
for(i=0; i < info->port_count ; i++) {
struct slgt_info *port = info->port_array[i];
if (port && (port->port.count || port->netcount) &&
if (port == NULL)
continue;
spin_lock(&port->lock);
if ((port->port.count || port->netcount) &&
port->pending_bh && !port->bh_running &&
!port->bh_requested) {
DBGISR(("%s bh queued\n", port->device_name));
schedule_work(&port->task);
port->bh_requested = true;
}
spin_unlock(&port->lock);
}
spin_unlock(&info->lock);
DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
return IRQ_HANDLED;
}
@ -2883,6 +2910,69 @@ static int set_interface(struct slgt_info *info, int if_mode)
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
*
@ -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,
gpio.dir, gpio.dmask));
spin_lock_irqsave(&info->lock,flags);
spin_lock_irqsave(&info->port_array[0]->lock, flags);
if (gpio.dmask) {
data = rd_reg32(info, IODR);
data |= gpio.dmask & gpio.dir;
@ -2919,7 +3009,7 @@ static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
data &= ~(gpio.smask & ~gpio.state);
wr_reg32(info, IOVR, data);
}
spin_unlock_irqrestore(&info->lock,flags);
spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
return 0;
}
@ -3020,7 +3110,7 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
return -EINVAL;
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 */
wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
/* get current pin states */
@ -3032,20 +3122,20 @@ static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
} else {
/* wait for target state */
add_cond_wait(&info->gpio_wait_q, &wait);
spin_unlock_irqrestore(&info->lock, flags);
spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
schedule();
if (signal_pending(current))
rc = -ERESTARTSYS;
else
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);
}
/* disable all GPIO interrupts if no waiting processes */
if (info->gpio_wait_q == NULL)
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)))
rc = -EFAULT;
@ -3578,7 +3668,6 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
/* copy resource information from first port to others */
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]->reg_addr = port_array[0]->reg_addr;
alloc_dma_bufs(port_array[i]);
@ -3763,7 +3852,9 @@ module_exit(slgt_exit);
#define CALC_REGADDR() \
unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
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)
{
@ -4182,7 +4273,13 @@ static void sync_mode(struct slgt_info *info)
/* 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
* 09 CRC enable
* 08 CRC32
@ -4197,6 +4294,9 @@ static void sync_mode(struct slgt_info *info)
val = BIT2;
switch(info->params.mode) {
case MGSL_MODE_XSYNC:
val |= BIT15 + BIT13;
break;
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
case MGSL_MODE_BISYNC: val |= BIT15; break;
case MGSL_MODE_RAW: val |= BIT13; break;
@ -4251,7 +4351,13 @@ static void sync_mode(struct slgt_info *info)
/* 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
* 09 CRC enable
* 08 CRC32
@ -4263,6 +4369,9 @@ static void sync_mode(struct slgt_info *info)
val = 0;
switch(info->params.mode) {
case MGSL_MODE_XSYNC:
val |= BIT15 + BIT13;
break;
case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
case MGSL_MODE_BISYNC: val |= BIT15; break;
case MGSL_MODE_RAW: val |= BIT13; break;
@ -4679,6 +4788,7 @@ static bool rx_get_buf(struct slgt_info *info)
switch(info->params.mode) {
case MGSL_MODE_MONOSYNC:
case MGSL_MODE_BISYNC:
case MGSL_MODE_XSYNC:
/* ignore residue in byte synchronous modes */
if (desc_residue(info->rbufs[i]))
count--;

View File

@ -503,6 +503,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
struct kbd_struct * kbd;
unsigned int console;
unsigned char ucval;
unsigned int uival;
void __user *up = (void __user *)arg;
int i, perm;
int ret = 0;
@ -657,7 +658,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
break;
case KDGETMODE:
ucval = vc->vc_mode;
uival = vc->vc_mode;
goto setint;
case KDMAPDISP:
@ -695,7 +696,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
break;
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_UNICODE) ? K_UNICODE :
K_XLATE);
@ -717,9 +718,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
break;
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:
ret = put_user(ucval, (int __user *)arg);
ret = put_user(uival, (int __user *)arg);
break;
case KDGETKEYCODE:
@ -949,7 +950,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
for (i = 0; i < MAX_NR_CONSOLES; ++i)
if (! VT_IS_IN_USE(i))
break;
ucval = i < MAX_NR_CONSOLES ? (i+1) : -1;
uival = i < MAX_NR_CONSOLES ? (i+1) : -1;
goto setint;
/*

View File

@ -2,6 +2,7 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/dmi.h>
#include <linux/efi.h>
#include <linux/bootmem.h>
@ -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)
{
u8 buf[15];
@ -381,8 +409,10 @@ static int __init dmi_present(const char __iomem *p)
buf[14] >> 4, buf[14] & 0xF);
else
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 1;
}

182
drivers/gpio/74x164.c Normal file
View File

@ -0,0 +1,182 @@
/*
* 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");

View File

@ -70,6 +70,11 @@ config GPIO_MAX730X
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
tristate "IT8761E GPIO support"
depends on GPIOLIB
@ -267,6 +272,13 @@ config GPIO_ADP5588
To compile this driver as a module, choose M here: the module will be
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:"
config GPIO_CS5535
@ -301,6 +313,14 @@ config GPIO_LANGWELL
help
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
bool "Support for timberdale GPIO IP"
depends on MFD_TIMBERDALE && GPIOLIB && HAS_IOMEM
@ -339,6 +359,14 @@ config GPIO_MC33880
SPI driver for Freescale MC33880 high-side/low-side switch.
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:"
config GPIO_UCB1400

View File

@ -10,6 +10,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIO_ADP5520) += adp5520-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_MAX730X) += max730x.o
obj-$(CONFIG_GPIO_MAX7300) += max7300.o
@ -17,8 +18,10 @@ obj-$(CONFIG_GPIO_MAX7301) += max7301.o
obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MC33880) += mc33880.o
obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o
obj-$(CONFIG_GPIO_74X164) += 74x164.o
obj-$(CONFIG_GPIO_PCA953X) += pca953x.o
obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
obj-$(CONFIG_GPIO_PCH) += pch_gpio.o
obj-$(CONFIG_GPIO_PL061) += pl061.o
obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o
obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o

View File

@ -1,8 +1,8 @@
/*
* 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.
*/
@ -13,21 +13,34 @@
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/i2c/adp5588.h>
#define DRV_NAME "adp5588-gpio"
#define MAXGPIO 18
#define ADP_BANK(offs) ((offs) >> 3)
#define ADP_BIT(offs) (1u << ((offs) & 0x7))
#define DRV_NAME "adp5588-gpio"
/*
* 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 i2c_client *client;
struct gpio_chip gpio_chip;
struct mutex lock; /* protect cached dir, dat_out */
/* protect serialized access to the interrupt controller bus */
struct mutex irq_lock;
unsigned gpio_start;
unsigned irq_base;
uint8_t dat_out[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)
@ -55,8 +68,8 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip);
return !!(adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + ADP_BANK(off))
& ADP_BIT(off));
return !!(adp5588_gpio_read(dev->client,
GPIO_DAT_STAT1 + ADP5588_BANK(off)) & ADP5588_BIT(off));
}
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 =
container_of(chip, struct adp5588_gpio, gpio_chip);
bank = ADP_BANK(off);
bit = ADP_BIT(off);
bank = ADP5588_BANK(off);
bit = ADP5588_BIT(off);
mutex_lock(&dev->lock);
if (val)
@ -87,10 +100,10 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip);
bank = ADP_BANK(off);
bank = ADP5588_BANK(off);
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]);
mutex_unlock(&dev->lock);
@ -105,8 +118,8 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
struct adp5588_gpio *dev =
container_of(chip, struct adp5588_gpio, gpio_chip);
bank = ADP_BANK(off);
bit = ADP_BIT(off);
bank = ADP5588_BANK(off);
bit = ADP5588_BIT(off);
mutex_lock(&dev->lock);
dev->dir[bank] |= bit;
@ -125,6 +138,213 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
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,
const struct i2c_device_id *id)
{
@ -160,37 +380,46 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client,
gc->can_sleep = 1;
gc->base = pdata->gpio_start;
gc->ngpio = MAXGPIO;
gc->ngpio = ADP5588_MAXGPIO;
gc->label = client->name;
gc->owner = THIS_MODULE;
mutex_init(&dev->lock);
ret = adp5588_gpio_read(dev->client, DEV_ID);
if (ret < 0)
goto err;
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->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i);
ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0);
ret |= adp5588_gpio_write(client, GPIO_PULL1 + i,
(pdata->pullup_dis_mask >> (8 * i)) & 0xFF);
ret |= adp5588_gpio_write(client, GPIO_INT_EN1 + i, 0);
if (ret)
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);
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,
client->name, revid);
pdata->irq_base, client->name, revid);
if (pdata->setup) {
ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);
@ -199,8 +428,11 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client,
}
i2c_set_clientdata(client, dev);
return 0;
err_irq:
adp5588_irq_teardown(dev);
err:
kfree(dev);
return ret;
@ -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);
if (ret) {
dev_err(&client->dev, "gpiochip_remove failed %d\n", ret);

View File

@ -0,0 +1,297 @@
/*
* 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");

View File

@ -18,10 +18,12 @@
/* Supports:
* Moorestown platform Langwell chip.
* Medfield platform Penwell chip.
* Whitney point.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/stddef.h>
@ -158,15 +160,15 @@ static int lnw_irq_type(unsigned irq, unsigned type)
spin_unlock_irqrestore(&lnw->lock, flags);
return 0;
};
}
static void lnw_irq_unmask(unsigned irq)
{
};
}
static void lnw_irq_mask(unsigned irq)
{
};
}
static struct irq_chip lnw_irqchip = {
.name = "LNW-GPIO",
@ -300,9 +302,88 @@ static struct pci_driver lnw_gpio_driver = {
.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)
{
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);

312
drivers/gpio/pch_gpio.c Normal file
View File

@ -0,0 +1,312 @@
/*
* 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");

View File

@ -47,6 +47,7 @@ struct timbgpio {
spinlock_t lock; /* mutual exclusion */
struct gpio_chip gpio;
int irq_base;
unsigned long last_ier;
};
static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index,
@ -112,16 +113,24 @@ static void timbgpio_irq_disable(unsigned irq)
{
struct timbgpio *tgpio = get_irq_chip_data(irq);
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)
{
struct timbgpio *tgpio = get_irq_chip_data(irq);
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)
@ -194,8 +203,16 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
ipr = ioread32(tgpio->membase + TGPIO_IPR);
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)
generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
}
static struct irq_chip timbgpio_irqchip = {

View File

@ -27,7 +27,6 @@
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/completion.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/unistd.h>

View File

@ -29,7 +29,6 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <asm/intel_scu_ipc.h>
#include <linux/device.h>
#include <linux/intel_pmic_gpio.h>

View File

@ -192,7 +192,7 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv)
out:return 0;
}
static struct device rio_bus = {
struct device rio_bus = {
.init_name = "rapidio",
};

View File

@ -48,7 +48,7 @@ DEFINE_SPINLOCK(rio_global_list_lock);
static int next_destid = 0;
static int next_switchid = 0;
static int next_net = 0;
static int next_comptag;
static int next_comptag = 1;
static struct timer_list rio_enum_timer =
TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
@ -121,27 +121,6 @@ static int rio_clear_locks(struct rio_mport *port)
u32 result;
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 */
rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
port->host_deviceid);
@ -162,6 +141,15 @@ static int rio_clear_locks(struct rio_mport *port)
rdev->vid, rdev->did);
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;
@ -420,11 +408,27 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
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,
&rdev->src_ops);
rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
&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 (do_enum) {
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,
/* If a PE has both switch and other functions, show it as a switch */
if (rio_is_switch(rdev)) {
rio_mport_read_config_32(port, destid, hopcount,
RIO_SWP_INFO_CAR, &rdev->swpinfo);
rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL);
rswitch = kzalloc(sizeof(*rswitch) +
RIO_GET_TOTAL_PORTS(rdev->swpinfo) *
sizeof(rswitch->nextdev[0]),
GFP_KERNEL);
if (!rswitch)
goto cleanup;
rswitch->switchid = next_switchid;
@ -458,6 +463,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
rdid++)
rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
rdev->rswitch = rswitch;
rswitch->rdev = rdev;
dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
rdev->rswitch->switchid);
rio_switch_init(rdev, do_enum);
@ -478,6 +484,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
}
rdev->dev.bus = &rio_bus_type;
rdev->dev.parent = &rio_bus;
device_initialize(&rdev->dev);
rdev->dev.release = rio_release_dev;
@ -717,87 +724,54 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
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
* @net: RIO network being enumerated
* @port: Master port to send transactions
* @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
* master port passed in @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 num_ports;
int cur_destid;
int sw_destid;
int sw_inport;
struct rio_dev *rdev;
u16 destid;
u32 regval;
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) {
pr_debug("RIO: PE already discovered by this host\n");
/*
* 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;
}
@ -828,13 +802,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
if (rdev) {
/* Add device to the global and bus/net specific list. */
list_add_tail(&rdev->net_list, &net->devices);
rdev->prev = prev;
if (prev && rio_is_switch(prev))
prev->rswitch->nextdev[prev_port] = rdev;
} else
return -1;
if (rio_is_switch(rdev)) {
next_switchid++;
sw_inport = rio_get_swpinfo_inport(port,
RIO_ANY_DESTID(port->sys_size), hopcount);
sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo);
rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE,
port->host_deviceid, sw_inport, 0);
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,
rdev->rswitch->route_table[destid] = sw_inport;
}
num_ports =
rio_get_swpinfo_tports(port, RIO_ANY_DESTID(port->sys_size),
hopcount);
pr_debug(
"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;
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)*/
rio_enable_rx_tx_port(port, 0,
RIO_ANY_DESTID(port->sys_size),
@ -879,7 +855,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
RIO_ANY_DESTID(port->sys_size),
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;
/* Update routing tables */
@ -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)
{
u32 tag_csr;
u32 regval;
rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
return (tag_csr & 0xffff) ? 1 : 0;
rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
&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,
u8 hopcount)
{
u8 port_num, route_port;
int num_ports;
struct rio_dev *rdev;
u16 ndestid;
@ -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 */
rdev->rswitch->destid = destid;
num_ports = rio_get_swpinfo_tports(port, destid, hopcount);
pr_debug(
"RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
rio_name(rdev), rdev->vid, rdev->did, num_ports);
for (port_num = 0; port_num < num_ports; port_num++) {
if (rio_get_swpinfo_inport(port, destid, hopcount) ==
port_num)
rio_name(rdev), rdev->vid, rdev->did,
RIO_GET_TOTAL_PORTS(rdev->swpinfo));
for (port_num = 0;
port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo);
port_num++) {
if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num)
continue;
if (rio_sport_is_active
@ -1011,6 +989,8 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
break;
}
if (ndestid == RIO_ANY_DESTID(port->sys_size))
continue;
rio_unlock_device(port, destid, hopcount);
if (rio_disc_peer
(net, port, ndestid, hopcount + 1) < 0)
@ -1108,8 +1088,7 @@ static void rio_update_route_tables(struct rio_mport *port)
if (rswitch->destid == destid)
continue;
sport = rio_get_swpinfo_inport(port,
rswitch->destid, rswitch->hopcount);
sport = RIO_GET_PORT_NUM(rswitch->rdev->swpinfo);
if (rswitch->add_entry) {
rio_route_add_entry(port, rswitch,
@ -1184,7 +1163,11 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
/* Enable Input Output Port (transmitter reviever) */
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. */
printk(KERN_INFO
"RIO: master port %d device has lost enumeration to a remote host\n",

View File

@ -40,9 +40,6 @@ static ssize_t routes_show(struct device *dev, struct device_attribute *attr, ch
char *str = buf;
int i;
if (!rdev->rswitch)
goto out;
for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
i++) {
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
rdev->rswitch->route_table[i]);
}
out:
return (str - buf);
}
@ -63,10 +59,11 @@ struct device_attribute rio_dev_attrs[] = {
__ATTR_RO(asm_did),
__ATTR_RO(asm_vid),
__ATTR_RO(asm_rev),
__ATTR_RO(routes),
__ATTR_NULL,
};
static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL);
static ssize_t
rio_read_config(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
@ -218,7 +215,17 @@ int rio_create_sysfs_dev_files(struct rio_dev *rdev)
{
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;
}
@ -231,5 +238,10 @@ int rio_create_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);
}
}

View File

@ -443,7 +443,7 @@ rio_mport_get_physefb(struct rio_mport *port, int local,
* @from is not %NULL, searches continue from next device on the global
* list.
*/
static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from)
{
struct list_head *n;
struct rio_dev *rdev;
@ -494,6 +494,232 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock)
return 0;
}
/**
* rio_chk_dev_route - Validate route to the specified device.
* @rdev: RIO device failed to respond
* @nrdev: Last active device on the route to rdev
* @npnum: nrdev's port number on the route to rdev
*
* Follows a route to the specified RIO device to determine the last available
* device (and corresponding RIO port) on the route.
*/
static int
rio_chk_dev_route(struct rio_dev *rdev, struct rio_dev **nrdev, int *npnum)
{
u32 result;
int p_port, dstid, rc = -EIO;
struct rio_dev *prev = NULL;
/* Find switch with failed RIO link */
while (rdev->prev && (rdev->prev->pef & RIO_PEF_SWITCH)) {
if (!rio_read_config_32(rdev->prev, RIO_DEV_ID_CAR, &result)) {
prev = rdev->prev;
break;
}
rdev = rdev->prev;
}
if (prev == NULL)
goto err_out;
dstid = (rdev->pef & RIO_PEF_SWITCH) ?
rdev->rswitch->destid : rdev->destid;
p_port = prev->rswitch->route_table[dstid];
if (p_port != RIO_INVALID_ROUTE) {
pr_debug("RIO: link failed on [%s]-P%d\n",
rio_name(prev), p_port);
*nrdev = prev;
*npnum = p_port;
rc = 0;
} else
pr_debug("RIO: failed to trace route to %s\n", rio_name(rdev));
err_out:
return rc;
}
/**
* rio_mport_chk_dev_access - Validate access to the specified device.
* @mport: Master port to send transactions
* @destid: Device destination ID in network
* @hopcount: Number of hops into the network
*/
int
rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid, u8 hopcount)
{
int i = 0;
u32 tmp;
while (rio_mport_read_config_32(mport, destid, hopcount,
RIO_DEV_ID_CAR, &tmp)) {
i++;
if (i == RIO_MAX_CHK_RETRY)
return -EIO;
mdelay(1);
}
return 0;
}
/**
* rio_chk_dev_access - Validate access to the specified device.
* @rdev: Pointer to RIO device control structure
*/
static int rio_chk_dev_access(struct rio_dev *rdev)
{
u8 hopcount = 0xff;
u16 destid = rdev->destid;
if (rdev->rswitch) {
destid = rdev->rswitch->destid;
hopcount = rdev->rswitch->hopcount;
}
return rio_mport_chk_dev_access(rdev->net->hport, destid, hopcount);
}
/**
* rio_get_input_status - Sends a Link-Request/Input-Status control symbol and
* returns link-response (if requested).
* @rdev: RIO devive to issue Input-status command
* @pnum: Device port number to issue the command
* @lnkresp: Response from a link partner
*/
static int
rio_get_input_status(struct rio_dev *rdev, int pnum, u32 *lnkresp)
{
struct rio_mport *mport = rdev->net->hport;
u16 destid = rdev->rswitch->destid;
u8 hopcount = rdev->rswitch->hopcount;
u32 regval;
int checkcount;
if (lnkresp) {
/* Read from link maintenance response register
* to clear valid bit */
rio_mport_read_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum),
&regval);
udelay(50);
}
/* Issue Input-status command */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_MNT_REQ_CSR(pnum),
RIO_MNT_REQ_CMD_IS);
/* Exit if the response is not expected */
if (lnkresp == NULL)
return 0;
checkcount = 3;
while (checkcount--) {
udelay(50);
rio_mport_read_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(pnum),
&regval);
if (regval & RIO_PORT_N_MNT_RSP_RVAL) {
*lnkresp = regval;
return 0;
}
}
return -EIO;
}
/**
* rio_clr_err_stopped - Clears port Error-stopped states.
* @rdev: Pointer to RIO device control structure
* @pnum: Switch port number to clear errors
* @err_status: port error status (if 0 reads register from device)
*/
static int rio_clr_err_stopped(struct rio_dev *rdev, u32 pnum, u32 err_status)
{
struct rio_mport *mport = rdev->net->hport;
u16 destid = rdev->rswitch->destid;
u8 hopcount = rdev->rswitch->hopcount;
struct rio_dev *nextdev = rdev->rswitch->nextdev[pnum];
u32 regval;
u32 far_ackid, far_linkstat, near_ackid;
if (err_status == 0)
rio_mport_read_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum),
&err_status);
if (err_status & RIO_PORT_N_ERR_STS_PW_OUT_ES) {
pr_debug("RIO_EM: servicing Output Error-Stopped state\n");
/*
* Send a Link-Request/Input-Status control symbol
*/
if (rio_get_input_status(rdev, pnum, &regval)) {
pr_debug("RIO_EM: Input-status response timeout\n");
goto rd_err;
}
pr_debug("RIO_EM: SP%d Input-status response=0x%08x\n",
pnum, regval);
far_ackid = (regval & RIO_PORT_N_MNT_RSP_ASTAT) >> 5;
far_linkstat = regval & RIO_PORT_N_MNT_RSP_LSTAT;
rio_mport_read_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_ACK_STS_CSR(pnum),
&regval);
pr_debug("RIO_EM: SP%d_ACK_STS_CSR=0x%08x\n", pnum, regval);
near_ackid = (regval & RIO_PORT_N_ACK_INBOUND) >> 24;
pr_debug("RIO_EM: SP%d far_ackID=0x%02x far_linkstat=0x%02x" \
" near_ackID=0x%02x\n",
pnum, far_ackid, far_linkstat, near_ackid);
/*
* If required, synchronize ackIDs of near and
* far sides.
*/
if ((far_ackid != ((regval & RIO_PORT_N_ACK_OUTSTAND) >> 8)) ||
(far_ackid != (regval & RIO_PORT_N_ACK_OUTBOUND))) {
/* Align near outstanding/outbound ackIDs with
* far inbound.
*/
rio_mport_write_config_32(mport, destid,
hopcount, rdev->phys_efptr +
RIO_PORT_N_ACK_STS_CSR(pnum),
(near_ackid << 24) |
(far_ackid << 8) | far_ackid);
/* Align far outstanding/outbound ackIDs with
* near inbound.
*/
far_ackid++;
if (nextdev)
rio_write_config_32(nextdev,
nextdev->phys_efptr +
RIO_PORT_N_ACK_STS_CSR(RIO_GET_PORT_NUM(nextdev->swpinfo)),
(far_ackid << 24) |
(near_ackid << 8) | near_ackid);
else
pr_debug("RIO_EM: Invalid nextdev pointer (NULL)\n");
}
rd_err:
rio_mport_read_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum),
&err_status);
pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status);
}
if ((err_status & RIO_PORT_N_ERR_STS_PW_INP_ES) && nextdev) {
pr_debug("RIO_EM: servicing Input Error-Stopped state\n");
rio_get_input_status(nextdev,
RIO_GET_PORT_NUM(nextdev->swpinfo), NULL);
udelay(50);
rio_mport_read_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(pnum),
&err_status);
pr_debug("RIO_EM: SP%d_ERR_STS_CSR=0x%08x\n", pnum, err_status);
}
return (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES |
RIO_PORT_N_ERR_STS_PW_INP_ES)) ? 1 : 0;
}
/**
* rio_inb_pwrite_handler - process inbound port-write message
* @pw_msg: pointer to inbound port-write message
@ -507,13 +733,13 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
struct rio_mport *mport;
u8 hopcount;
u16 destid;
u32 err_status;
u32 err_status, em_perrdet, em_ltlerrdet;
int rc, portnum;
rdev = rio_get_comptag(pw_msg->em.comptag, NULL);
if (rdev == NULL) {
/* Someting bad here (probably enumeration error) */
pr_err("RIO: %s No matching device for CTag 0x%08x\n",
/* Device removed or enumeration error */
pr_debug("RIO: %s No matching device for CTag 0x%08x\n",
__func__, pw_msg->em.comptag);
return -EIO;
}
@ -524,12 +750,11 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
{
u32 i;
for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) {
pr_debug("0x%02x: %08x %08x %08x %08x",
pr_debug("0x%02x: %08x %08x %08x %08x\n",
i*4, pw_msg->raw[i], pw_msg->raw[i + 1],
pw_msg->raw[i + 2], pw_msg->raw[i + 3]);
i += 4;
}
pr_debug("\n");
}
#endif
@ -545,6 +770,26 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
return 0;
}
portnum = pw_msg->em.is_port & 0xFF;
/* Check if device and route to it are functional:
* Sometimes devices may send PW message(s) just before being
* powered down (or link being lost).
*/
if (rio_chk_dev_access(rdev)) {
pr_debug("RIO: device access failed - get link partner\n");
/* Scan route to the device and identify failed link.
* This will replace device and port reported in PW message.
* PW message should not be used after this point.
*/
if (rio_chk_dev_route(rdev, &rdev, &portnum)) {
pr_err("RIO: Route trace for %s failed\n",
rio_name(rdev));
return -EIO;
}
pw_msg = NULL;
}
/* For End-point devices processing stops here */
if (!(rdev->pef & RIO_PEF_SWITCH))
return 0;
@ -562,9 +807,6 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
/*
* Process the port-write notification from switch
*/
portnum = pw_msg->em.is_port & 0xFF;
if (rdev->rswitch->em_handle)
rdev->rswitch->em_handle(rdev, portnum);
@ -573,29 +815,28 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
&err_status);
pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status);
if (pw_msg->em.errdetect) {
pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n",
portnum, pw_msg->em.errdetect);
/* Clear EM Port N Error Detect CSR */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0);
}
if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) {
if (pw_msg->em.ltlerrdet) {
pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n",
pw_msg->em.ltlerrdet);
/* Clear EM L/T Layer Error Detect CSR */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0);
}
if (!(rdev->rswitch->port_ok & (1 << portnum))) {
rdev->rswitch->port_ok |= (1 << portnum);
rio_set_port_lockout(rdev, portnum, 0);
/* Schedule Insertion Service */
pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n",
rio_name(rdev), portnum);
}
/* Clear Port Errors */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
err_status & RIO_PORT_N_ERR_STS_CLR_MASK);
/* Clear error-stopped states (if reported).
* Depending on the link partner state, two attempts
* may be needed for successful recovery.
*/
if (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES |
RIO_PORT_N_ERR_STS_PW_INP_ES)) {
if (rio_clr_err_stopped(rdev, portnum, err_status))
rio_clr_err_stopped(rdev, portnum, 0);
}
} else { /* if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) */
if (rdev->rswitch->port_ok & (1 << portnum)) {
if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) {
if (rdev->rswitch->port_ok & (1 << portnum)) {
rdev->rswitch->port_ok &= ~(1 << portnum);
rio_set_port_lockout(rdev, portnum, 1);
@ -608,21 +849,32 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg)
pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n",
rio_name(rdev), portnum);
}
} else {
if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) {
rdev->rswitch->port_ok |= (1 << portnum);
rio_set_port_lockout(rdev, portnum, 0);
/* Schedule Insertion Service */
pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n",
rio_name(rdev), portnum);
}
}
/* Clear Port-Write Pending bit */
rio_mport_read_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet);
if (em_perrdet) {
pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n",
portnum, em_perrdet);
/* Clear EM Port N Error Detect CSR */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0);
}
rio_mport_read_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet);
if (em_ltlerrdet) {
pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n",
em_ltlerrdet);
/* Clear EM L/T Layer Error Detect CSR */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0);
}
/* Clear remaining error bits and Port-Write Pending bit */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum),
RIO_PORT_N_ERR_STS_PW_PEND);
err_status);
return 0;
}

View File

@ -14,6 +14,8 @@
#include <linux/list.h>
#include <linux/rio.h>
#define RIO_MAX_CHK_RETRY 3
/* Functions internal to the RIO core code */
extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid,
@ -22,6 +24,8 @@ extern u32 rio_mport_get_physefb(struct rio_mport *port, int local,
u16 destid, u8 hopcount);
extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid,
u8 hopcount, u32 from);
extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid,
u8 hopcount);
extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
extern int rio_enum_mport(struct rio_mport *mport);
extern int rio_disc_mport(struct rio_mport *mport);
@ -34,6 +38,7 @@ extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid,
extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
u8 hopcount, u16 table);
extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from);
/* Structures internal to the RIO core code */
extern struct device_attribute rio_dev_attrs[];

View File

@ -20,6 +20,13 @@ config RAPIDIO_TSI568
---help---
Includes support for IDT Tsi568 serial RapidIO switch.
config RAPIDIO_CPS_GEN2
bool "IDT CPS Gen.2 SRIO switch support"
depends on RAPIDIO
default n
---help---
Includes support for ITD CPS Gen.2 serial RapidIO switches.
config RAPIDIO_TSI500
bool "Tsi500 Parallel RapidIO switch support"
depends on RAPIDIO

View File

@ -6,6 +6,7 @@ obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o
obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o
obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o
obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o
obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o
ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG

View File

@ -0,0 +1,447 @@
/*
* IDT CPS Gen.2 Serial RapidIO switch family support
*
* Copyright 2010 Integrated Device Technology, Inc.
* Alexandre Bounine <alexandre.bounine@idt.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.
*/
#include <linux/rio.h>
#include <linux/rio_drv.h>
#include <linux/rio_ids.h>
#include <linux/delay.h>
#include "../rio.h"
#define LOCAL_RTE_CONF_DESTID_SEL 0x010070
#define LOCAL_RTE_CONF_DESTID_SEL_PSEL 0x0000001f
#define IDT_LT_ERR_REPORT_EN 0x03100c
#define IDT_PORT_ERR_REPORT_EN(n) (0x031044 + (n)*0x40)
#define IDT_PORT_ERR_REPORT_EN_BC 0x03ff04
#define IDT_PORT_ISERR_REPORT_EN(n) (0x03104C + (n)*0x40)
#define IDT_PORT_ISERR_REPORT_EN_BC 0x03ff0c
#define IDT_PORT_INIT_TX_ACQUIRED 0x00000020
#define IDT_LANE_ERR_REPORT_EN(n) (0x038010 + (n)*0x100)
#define IDT_LANE_ERR_REPORT_EN_BC 0x03ff10
#define IDT_DEV_CTRL_1 0xf2000c
#define IDT_DEV_CTRL_1_GENPW 0x02000000
#define IDT_DEV_CTRL_1_PRSTBEH 0x00000001
#define IDT_CFGBLK_ERR_CAPTURE_EN 0x020008
#define IDT_CFGBLK_ERR_REPORT 0xf20014
#define IDT_CFGBLK_ERR_REPORT_GENPW 0x00000002
#define IDT_AUX_PORT_ERR_CAP_EN 0x020000
#define IDT_AUX_ERR_REPORT_EN 0xf20018
#define IDT_AUX_PORT_ERR_LOG_I2C 0x00000002
#define IDT_AUX_PORT_ERR_LOG_JTAG 0x00000001
#define IDT_ISLTL_ADDRESS_CAP 0x021014
#define IDT_RIO_DOMAIN 0xf20020
#define IDT_RIO_DOMAIN_MASK 0x000000ff
#define IDT_PW_INFO_CSR 0xf20024
#define IDT_SOFT_RESET 0xf20040
#define IDT_SOFT_RESET_REQ 0x00030097
#define IDT_I2C_MCTRL 0xf20050
#define IDT_I2C_MCTRL_GENPW 0x04000000
#define IDT_JTAG_CTRL 0xf2005c
#define IDT_JTAG_CTRL_GENPW 0x00000002
#define IDT_LANE_CTRL(n) (0xff8000 + (n)*0x100)
#define IDT_LANE_CTRL_BC 0xffff00
#define IDT_LANE_CTRL_GENPW 0x00200000
#define IDT_LANE_DFE_1_BC 0xffff18
#define IDT_LANE_DFE_2_BC 0xffff1c
#define IDT_PORT_OPS(n) (0xf40004 + (n)*0x100)
#define IDT_PORT_OPS_GENPW 0x08000000
#define IDT_PORT_OPS_PL_ELOG 0x00000040
#define IDT_PORT_OPS_LL_ELOG 0x00000020
#define IDT_PORT_OPS_LT_ELOG 0x00000010
#define IDT_PORT_OPS_BC 0xf4ff04
#define IDT_PORT_ISERR_DET(n) (0xf40008 + (n)*0x100)
#define IDT_ERR_CAP 0xfd0000
#define IDT_ERR_CAP_LOG_OVERWR 0x00000004
#define IDT_ERR_RD 0xfd0004
#define IDT_DEFAULT_ROUTE 0xde
#define IDT_NO_ROUTE 0xdf
static int
idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 route_port)
{
/*
* Select routing table to update
*/
if (table == RIO_GLOBAL_TABLE)
table = 0;
else
table++;
rio_mport_write_config_32(mport, destid, hopcount,
LOCAL_RTE_CONF_DESTID_SEL, table);
/*
* Program destination port for the specified destID
*/
rio_mport_write_config_32(mport, destid, hopcount,
RIO_STD_RTE_CONF_DESTID_SEL_CSR,
(u32)route_destid);
rio_mport_write_config_32(mport, destid, hopcount,
RIO_STD_RTE_CONF_PORT_SEL_CSR,
(u32)route_port);
udelay(10);
return 0;
}
static int
idtg2_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
u16 table, u16 route_destid, u8 *route_port)
{
u32 result;
/*
* Select routing table to read
*/
if (table == RIO_GLOBAL_TABLE)
table = 0;
else
table++;
rio_mport_write_config_32(mport, destid, hopcount,
LOCAL_RTE_CONF_DESTID_SEL, table);
rio_mport_write_config_32(mport, destid, hopcount,
RIO_STD_RTE_CONF_DESTID_SEL_CSR,
route_destid);
rio_mport_read_config_32(mport, destid, hopcount,
RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
if (IDT_DEFAULT_ROUTE == (u8)result || IDT_NO_ROUTE == (u8)result)
*route_port = RIO_INVALID_ROUTE;
else
*route_port = (u8)result;
return 0;
}
static int
idtg2_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
u16 table)
{
u32 i;
/*
* Select routing table to read
*/
if (table == RIO_GLOBAL_TABLE)
table = 0;
else
table++;
rio_mport_write_config_32(mport, destid, hopcount,
LOCAL_RTE_CONF_DESTID_SEL, table);
for (i = RIO_STD_RTE_CONF_EXTCFGEN;
i <= (RIO_STD_RTE_CONF_EXTCFGEN | 0xff);) {
rio_mport_write_config_32(mport, destid, hopcount,
RIO_STD_RTE_CONF_DESTID_SEL_CSR, i);
rio_mport_write_config_32(mport, destid, hopcount,
RIO_STD_RTE_CONF_PORT_SEL_CSR,
(IDT_DEFAULT_ROUTE << 24) | (IDT_DEFAULT_ROUTE << 16) |
(IDT_DEFAULT_ROUTE << 8) | IDT_DEFAULT_ROUTE);
i += 4;
}
return 0;
}
static int
idtg2_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
u8 sw_domain)
{
/*
* Switch domain configuration operates only at global level
*/
rio_mport_write_config_32(mport, destid, hopcount,
IDT_RIO_DOMAIN, (u32)sw_domain);
return 0;
}
static int
idtg2_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
u8 *sw_domain)
{
u32 regval;
/*
* Switch domain configuration operates only at global level
*/
rio_mport_read_config_32(mport, destid, hopcount,
IDT_RIO_DOMAIN, &regval);
*sw_domain = (u8)(regval & 0xff);
return 0;
}
static int
idtg2_em_init(struct rio_dev *rdev)
{
struct rio_mport *mport = rdev->net->hport;
u16 destid = rdev->rswitch->destid;
u8 hopcount = rdev->rswitch->hopcount;
u32 regval;
int i, tmp;
/*
* This routine performs device-specific initialization only.
* All standard EM configuration should be performed at upper level.
*/
pr_debug("RIO: %s [%d:%d]\n", __func__, destid, hopcount);
/* Set Port-Write info CSR: PRIO=3 and CRF=1 */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_PW_INFO_CSR, 0x0000e000);
/*
* Configure LT LAYER error reporting.
*/
/* Enable standard (RIO.p8) error reporting */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_LT_ERR_REPORT_EN,
REM_LTL_ERR_ILLTRAN | REM_LTL_ERR_UNSOLR |
REM_LTL_ERR_UNSUPTR);
/* Use Port-Writes for LT layer error reporting.
* Enable per-port reset
*/
rio_mport_read_config_32(mport, destid, hopcount,
IDT_DEV_CTRL_1, &regval);
rio_mport_write_config_32(mport, destid, hopcount,
IDT_DEV_CTRL_1,
regval | IDT_DEV_CTRL_1_GENPW | IDT_DEV_CTRL_1_PRSTBEH);
/*
* Configure PORT error reporting.
*/
/* Report all RIO.p8 errors supported by device */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_PORT_ERR_REPORT_EN_BC, 0x807e8037);
/* Configure reporting of implementation specific errors/events */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_PORT_ISERR_REPORT_EN_BC, IDT_PORT_INIT_TX_ACQUIRED);
/* Use Port-Writes for port error reporting and enable error logging */
tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo);
for (i = 0; i < tmp; i++) {
rio_mport_read_config_32(mport, destid, hopcount,
IDT_PORT_OPS(i), &regval);
rio_mport_write_config_32(mport, destid, hopcount,
IDT_PORT_OPS(i), regval | IDT_PORT_OPS_GENPW |
IDT_PORT_OPS_PL_ELOG |
IDT_PORT_OPS_LL_ELOG |
IDT_PORT_OPS_LT_ELOG);
}
/* Overwrite error log if full */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_ERR_CAP, IDT_ERR_CAP_LOG_OVERWR);
/*
* Configure LANE error reporting.
*/
/* Disable line error reporting */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_LANE_ERR_REPORT_EN_BC, 0);
/* Use Port-Writes for lane error reporting (when enabled)
* (do per-lane update because lanes may have different configuration)
*/
tmp = (rdev->did == RIO_DID_IDTCPS1848) ? 48 : 16;
for (i = 0; i < tmp; i++) {
rio_mport_read_config_32(mport, destid, hopcount,
IDT_LANE_CTRL(i), &regval);
rio_mport_write_config_32(mport, destid, hopcount,
IDT_LANE_CTRL(i), regval | IDT_LANE_CTRL_GENPW);
}
/*
* Configure AUX error reporting.
*/
/* Disable JTAG and I2C Error capture */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_AUX_PORT_ERR_CAP_EN, 0);
/* Disable JTAG and I2C Error reporting/logging */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_AUX_ERR_REPORT_EN, 0);
/* Disable Port-Write notification from JTAG */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_JTAG_CTRL, 0);
/* Disable Port-Write notification from I2C */
rio_mport_read_config_32(mport, destid, hopcount,
IDT_I2C_MCTRL, &regval);
rio_mport_write_config_32(mport, destid, hopcount,
IDT_I2C_MCTRL,
regval & ~IDT_I2C_MCTRL_GENPW);
/*
* Configure CFG_BLK error reporting.
*/
/* Disable Configuration Block error capture */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_CFGBLK_ERR_CAPTURE_EN, 0);
/* Disable Port-Writes for Configuration Block error reporting */
rio_mport_read_config_32(mport, destid, hopcount,
IDT_CFGBLK_ERR_REPORT, &regval);
rio_mport_write_config_32(mport, destid, hopcount,
IDT_CFGBLK_ERR_REPORT,
regval & ~IDT_CFGBLK_ERR_REPORT_GENPW);
/* set TVAL = ~50us */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
return 0;
}
static int
idtg2_em_handler(struct rio_dev *rdev, u8 portnum)
{
struct rio_mport *mport = rdev->net->hport;
u16 destid = rdev->rswitch->destid;
u8 hopcount = rdev->rswitch->hopcount;
u32 regval, em_perrdet, em_ltlerrdet;
rio_mport_read_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet);
if (em_ltlerrdet) {
/* Service Logical/Transport Layer Error(s) */
if (em_ltlerrdet & REM_LTL_ERR_IMPSPEC) {
/* Implementation specific error reported */
rio_mport_read_config_32(mport, destid, hopcount,
IDT_ISLTL_ADDRESS_CAP, &regval);
pr_debug("RIO: %s Implementation Specific LTL errors" \
" 0x%x @(0x%x)\n",
rio_name(rdev), em_ltlerrdet, regval);
/* Clear implementation specific address capture CSR */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_ISLTL_ADDRESS_CAP, 0);
}
}
rio_mport_read_config_32(mport, destid, hopcount,
rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet);
if (em_perrdet) {
/* Service Port-Level Error(s) */
if (em_perrdet & REM_PED_IMPL_SPEC) {
/* Implementation Specific port error reported */
/* Get IS errors reported */
rio_mport_read_config_32(mport, destid, hopcount,
IDT_PORT_ISERR_DET(portnum), &regval);
pr_debug("RIO: %s Implementation Specific Port" \
" errors 0x%x\n", rio_name(rdev), regval);
/* Clear all implementation specific events */
rio_mport_write_config_32(mport, destid, hopcount,
IDT_PORT_ISERR_DET(portnum), 0);
}
}
return 0;
}
static ssize_t
idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf)
{
struct rio_dev *rdev = to_rio_dev(dev);
struct rio_mport *mport = rdev->net->hport;
u16 destid = rdev->rswitch->destid;
u8 hopcount = rdev->rswitch->hopcount;
ssize_t len = 0;
u32 regval;
while (!rio_mport_read_config_32(mport, destid, hopcount,
IDT_ERR_RD, &regval)) {
if (!regval) /* 0 = end of log */
break;
len += snprintf(buf + len, PAGE_SIZE - len,
"%08x\n", regval);
if (len >= (PAGE_SIZE - 10))
break;
}
return len;
}
static DEVICE_ATTR(errlog, S_IRUGO, idtg2_show_errlog, NULL);
static int idtg2_sysfs(struct rio_dev *rdev, int create)
{
struct device *dev = &rdev->dev;
int err = 0;
if (create == RIO_SW_SYSFS_CREATE) {
/* Initialize sysfs entries */
err = device_create_file(dev, &dev_attr_errlog);
if (err)
dev_err(dev, "Unable create sysfs errlog file\n");
} else
device_remove_file(dev, &dev_attr_errlog);
return err;
}
static int idtg2_switch_init(struct rio_dev *rdev, int do_enum)
{
pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
rdev->rswitch->add_entry = idtg2_route_add_entry;
rdev->rswitch->get_entry = idtg2_route_get_entry;
rdev->rswitch->clr_table = idtg2_route_clr_table;
rdev->rswitch->set_domain = idtg2_set_domain;
rdev->rswitch->get_domain = idtg2_get_domain;
rdev->rswitch->em_init = idtg2_em_init;
rdev->rswitch->em_handle = idtg2_em_handler;
rdev->rswitch->sw_sysfs = idtg2_sysfs;
return 0;
}
DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init);
DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init);

View File

@ -117,6 +117,10 @@ idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
static int idtcps_switch_init(struct rio_dev *rdev, int do_enum)
{
struct rio_mport *mport = rdev->net->hport;
u16 destid = rdev->rswitch->destid;
u8 hopcount = rdev->rswitch->hopcount;
pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
rdev->rswitch->add_entry = idtcps_route_add_entry;
rdev->rswitch->get_entry = idtcps_route_get_entry;
@ -126,6 +130,12 @@ static int idtcps_switch_init(struct rio_dev *rdev, int do_enum)
rdev->rswitch->em_init = NULL;
rdev->rswitch->em_handle = NULL;
if (do_enum) {
/* set TVAL = ~50us */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
}
return 0;
}

View File

@ -29,7 +29,7 @@
#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
#define TSI568_SP_MODE_BC 0x10004
#define TSI568_SP_MODE(n) (0x11004 + 0x100*n)
#define TSI568_SP_MODE_PW_DIS 0x08000000
static int
@ -117,14 +117,19 @@ tsi568_em_init(struct rio_dev *rdev)
u16 destid = rdev->rswitch->destid;
u8 hopcount = rdev->rswitch->hopcount;
u32 regval;
int portnum;
pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount);
/* Make sure that Port-Writes are disabled (for all ports) */
rio_mport_read_config_32(mport, destid, hopcount,
TSI568_SP_MODE_BC, &regval);
rio_mport_write_config_32(mport, destid, hopcount,
TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS);
for (portnum = 0;
portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) {
rio_mport_read_config_32(mport, destid, hopcount,
TSI568_SP_MODE(portnum), &regval);
rio_mport_write_config_32(mport, destid, hopcount,
TSI568_SP_MODE(portnum),
regval | TSI568_SP_MODE_PW_DIS);
}
return 0;
}

View File

@ -166,7 +166,8 @@ tsi57x_em_init(struct rio_dev *rdev)
pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount);
for (portnum = 0; portnum < 16; portnum++) {
for (portnum = 0;
portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) {
/* Make sure that Port-Writes are enabled (for all ports) */
rio_mport_read_config_32(mport, destid, hopcount,
TSI578_SP_MODE(portnum), &regval);
@ -205,6 +206,10 @@ tsi57x_em_init(struct rio_dev *rdev)
portnum++;
}
/* set TVAL = ~50us */
rio_mport_write_config_32(mport, destid, hopcount,
rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x9a << 8);
return 0;
}

View File

@ -171,7 +171,8 @@ config RTC_DRV_DS3232
depends on RTC_CLASS && I2C
help
If you say yes here you get support for Dallas Semiconductor
DS3232 real-time clock chips.
DS3232 real-time clock chips. If an interrupt is associated
with the device, the alarm functionality is supported.
This driver can also be built as a module. If so, the module
will be called rtc-ds3232.
@ -952,4 +953,13 @@ config RTC_DRV_JZ4740
This driver can also be buillt as a module. If so, the module
will be called rtc-jz4740.
config RTC_DRV_LPC32XX
depends on ARCH_LPC32XX
tristate "NXP LPC32XX RTC"
help
This enables support for the NXP RTC in the LPC32XX
This driver can also be buillt as a module. If so, the module
will be called rtc-lpc32xx.
endif # RTC_CLASS

View File

@ -51,6 +51,7 @@ obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o
obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o

View File

@ -158,8 +158,10 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
rtc_dev_prepare(rtc);
err = device_register(&rtc->dev);
if (err)
if (err) {
put_device(&rtc->dev);
goto exit_kfree;
}
rtc_dev_add_device(rtc);
rtc_sysfs_add_device(rtc);

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