Merge branches 'sh/hwblk' and 'sh/platform-updates'

This commit is contained in:
Paul Mundt 2009-07-20 04:28:11 +09:00
commit c358fc46ef
455 changed files with 4603 additions and 4270 deletions

View file

@ -207,8 +207,8 @@ Attributes
~~~~~~~~~~
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
ssize_t (*show)(struct device_driver *driver, char *buf);
ssize_t (*store)(struct device_driver *, const char * buf, size_t count);
};
Device drivers can export attributes via their sysfs directories.

View file

@ -73,7 +73,7 @@ The remaining CPU time will be used for user input and other tasks. Because
realtime tasks have explicitly allocated the CPU time they need to perform
their tasks, buffer underruns in the graphics or audio can be eliminated.
NOTE: the above example is not fully implemented as of yet (2.6.25). We still
NOTE: the above example is not fully implemented yet. We still
lack an EDF scheduler to make non-uniform periods usable.
@ -140,14 +140,15 @@ The other option is:
.o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups")
This uses the /cgroup virtual file system and "/cgroup/<cgroup>/cpu.rt_runtime_us"
to control the CPU time reserved for each control group instead.
This uses the /cgroup virtual file system and
"/cgroup/<cgroup>/cpu.rt_runtime_us" to control the CPU time reserved for each
control group instead.
For more information on working with control groups, you should read
Documentation/cgroups/cgroups.txt as well.
Group settings are checked against the following limits in order to keep the configuration
schedulable:
Group settings are checked against the following limits in order to keep the
configuration schedulable:
\Sum_{i} runtime_{i} / global_period <= global_runtime / global_period
@ -189,7 +190,7 @@ Implementing SCHED_EDF might take a while to complete. Priority Inheritance is
the biggest challenge as the current linux PI infrastructure is geared towards
the limited static priority levels 0-99. With deadline scheduling you need to
do deadline inheritance (since priority is inversely proportional to the
deadline delta (deadline - now).
deadline delta (deadline - now)).
This means the whole PI machinery will have to be reworked - and that is one of
the most complex pieces of code we have.

View file

@ -2,3 +2,5 @@
- this file
mtrr.txt
- how to use x86 Memory Type Range Registers to increase performance
exception-tables.txt
- why and how Linux kernel uses exception tables on x86

View file

@ -1,123 +1,123 @@
Kernel level exception handling in Linux 2.1.8
Kernel level exception handling in Linux
Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com>
When a process runs in kernel mode, it often has to access user
mode memory whose address has been passed by an untrusted program.
When a process runs in kernel mode, it often has to access user
mode memory whose address has been passed by an untrusted program.
To protect itself the kernel has to verify this address.
In older versions of Linux this was done with the
int verify_area(int type, const void * addr, unsigned long size)
In older versions of Linux this was done with the
int verify_area(int type, const void * addr, unsigned long size)
function (which has since been replaced by access_ok()).
This function verified that the memory area starting at address
This function verified that the memory area starting at address
'addr' and of size 'size' was accessible for the operation specified
in type (read or write). To do this, verify_read had to look up the
virtual memory area (vma) that contained the address addr. In the
normal case (correctly working program), this test was successful.
in type (read or write). To do this, verify_read had to look up the
virtual memory area (vma) that contained the address addr. In the
normal case (correctly working program), this test was successful.
It only failed for a few buggy programs. In some kernel profiling
tests, this normally unneeded verification used up a considerable
amount of time.
To overcome this situation, Linus decided to let the virtual memory
To overcome this situation, Linus decided to let the virtual memory
hardware present in every Linux-capable CPU handle this test.
How does this work?
Whenever the kernel tries to access an address that is currently not
accessible, the CPU generates a page fault exception and calls the
page fault handler
Whenever the kernel tries to access an address that is currently not
accessible, the CPU generates a page fault exception and calls the
page fault handler
void do_page_fault(struct pt_regs *regs, unsigned long error_code)
in arch/i386/mm/fault.c. The parameters on the stack are set up by
the low level assembly glue in arch/i386/kernel/entry.S. The parameter
regs is a pointer to the saved registers on the stack, error_code
in arch/x86/mm/fault.c. The parameters on the stack are set up by
the low level assembly glue in arch/x86/kernel/entry_32.S. The parameter
regs is a pointer to the saved registers on the stack, error_code
contains a reason code for the exception.
do_page_fault first obtains the unaccessible address from the CPU
control register CR2. If the address is within the virtual address
space of the process, the fault probably occurred, because the page
was not swapped in, write protected or something similar. However,
we are interested in the other case: the address is not valid, there
is no vma that contains this address. In this case, the kernel jumps
to the bad_area label.
do_page_fault first obtains the unaccessible address from the CPU
control register CR2. If the address is within the virtual address
space of the process, the fault probably occurred, because the page
was not swapped in, write protected or something similar. However,
we are interested in the other case: the address is not valid, there
is no vma that contains this address. In this case, the kernel jumps
to the bad_area label.
There it uses the address of the instruction that caused the exception
(i.e. regs->eip) to find an address where the execution can continue
(fixup). If this search is successful, the fault handler modifies the
return address (again regs->eip) and returns. The execution will
There it uses the address of the instruction that caused the exception
(i.e. regs->eip) to find an address where the execution can continue
(fixup). If this search is successful, the fault handler modifies the
return address (again regs->eip) and returns. The execution will
continue at the address in fixup.
Where does fixup point to?
Since we jump to the contents of fixup, fixup obviously points
to executable code. This code is hidden inside the user access macros.
I have picked the get_user macro defined in include/asm/uaccess.h as an
example. The definition is somewhat hard to follow, so let's peek at
Since we jump to the contents of fixup, fixup obviously points
to executable code. This code is hidden inside the user access macros.
I have picked the get_user macro defined in arch/x86/include/asm/uaccess.h
as an example. The definition is somewhat hard to follow, so let's peek at
the code generated by the preprocessor and the compiler. I selected
the get_user call in drivers/char/console.c for a detailed examination.
the get_user call in drivers/char/sysrq.c for a detailed examination.
The original code in console.c line 1405:
The original code in sysrq.c line 587:
get_user(c, buf);
The preprocessor output (edited to become somewhat readable):
(
{
long __gu_err = - 14 , __gu_val = 0;
const __typeof__(*( ( buf ) )) *__gu_addr = ((buf));
if (((((0 + current_set[0])->tss.segment) == 0x18 ) ||
(((sizeof(*(buf))) <= 0xC0000000UL) &&
((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
{
long __gu_err = - 14 , __gu_val = 0;
const __typeof__(*( ( buf ) )) *__gu_addr = ((buf));
if (((((0 + current_set[0])->tss.segment) == 0x18 ) ||
(((sizeof(*(buf))) <= 0xC0000000UL) &&
((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
do {
__gu_err = 0;
switch ((sizeof(*(buf)))) {
case 1:
__asm__ __volatile__(
"1: mov" "b" " %2,%" "b" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "b" " %" "b" "1,%" "b" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
".text" : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )) ;
break;
case 2:
__gu_err = 0;
switch ((sizeof(*(buf)))) {
case 1:
__asm__ __volatile__(
"1: mov" "w" " %2,%" "w" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "w" " %" "w" "1,%" "w" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
"1: mov" "b" " %2,%" "b" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "b" " %" "b" "1,%" "b" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
".text" : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err )) ;
break;
case 2:
__asm__ __volatile__(
"1: mov" "w" " %2,%" "w" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "w" " %" "w" "1,%" "w" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n"
" .long 1b,3b\n"
".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err ));
break;
case 4:
__asm__ __volatile__(
"1: mov" "l" " %2,%" "" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "l" " %" "" "1,%" "" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n" " .long 1b,3b\n"
( __gu_addr )) ), "i"(- 14 ), "0"( __gu_err ));
break;
case 4:
__asm__ __volatile__(
"1: mov" "l" " %2,%" "" "1\n"
"2:\n"
".section .fixup,\"ax\"\n"
"3: movl %3,%0\n"
" xor" "l" " %" "" "1,%" "" "1\n"
" jmp 2b\n"
".section __ex_table,\"a\"\n"
" .align 4\n" " .long 1b,3b\n"
".text" : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
( __gu_addr )) ), "i"(- 14 ), "0"(__gu_err));
break;
default:
(__gu_val) = __get_user_bad();
}
} while (0) ;
((c)) = (__typeof__(*((buf))))__gu_val;
( __gu_addr )) ), "i"(- 14 ), "0"(__gu_err));
break;
default:
(__gu_val) = __get_user_bad();
}
} while (0) ;
((c)) = (__typeof__(*((buf))))__gu_val;
__gu_err;
}
);
@ -127,12 +127,12 @@ see what code gcc generates:
> xorl %edx,%edx
> movl current_set,%eax
> cmpl $24,788(%eax)
> je .L1424
> cmpl $24,788(%eax)
> je .L1424
> cmpl $-1073741825,64(%esp)
> ja .L1423
> ja .L1423
> .L1424:
> movl %edx,%eax
> movl %edx,%eax
> movl 64(%esp),%ebx
> #APP
> 1: movb (%ebx),%dl /* this is the actual user access */
@ -149,17 +149,17 @@ see what code gcc generates:
> .L1423:
> movzbl %dl,%esi
The optimizer does a good job and gives us something we can actually
understand. Can we? The actual user access is quite obvious. Thanks
to the unified address space we can just access the address in user
The optimizer does a good job and gives us something we can actually
understand. Can we? The actual user access is quite obvious. Thanks
to the unified address space we can just access the address in user
memory. But what does the .section stuff do?????
To understand this we have to look at the final kernel:
> objdump --section-headers vmlinux
>
>
> vmlinux: file format elf32-i386
>
>
> Sections:
> Idx Name Size VMA LMA File off Algn
> 0 .text 00098f40 c0100000 c0100000 00001000 2**4
@ -198,18 +198,18 @@ final kernel executable:
The whole user memory access is reduced to 10 x86 machine instructions.
The instructions bracketed in the .section directives are no longer
in the normal execution path. They are located in a different section
in the normal execution path. They are located in a different section
of the executable file:
> objdump --disassemble --section=.fixup vmlinux
>
>
> c0199ff5 <.fixup+10b5> movl $0xfffffff2,%eax
> c0199ffa <.fixup+10ba> xorb %dl,%dl
> c0199ffc <.fixup+10bc> jmp c017e7a7 <do_con_write+e3>
And finally:
> objdump --full-contents --section=__ex_table vmlinux
>
>
> c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0 ................
> c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0 ................
> c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0 ................
@ -235,8 +235,8 @@ sections in the ELF object file. So the instructions
ended up in the .fixup section of the object file and the addresses
.long 1b,3b
ended up in the __ex_table section of the object file. 1b and 3b
are local labels. The local label 1b (1b stands for next label 1
backward) is the address of the instruction that might fault, i.e.
are local labels. The local label 1b (1b stands for next label 1
backward) is the address of the instruction that might fault, i.e.
in our case the address of the label 1 is c017e7a5:
the original assembly code: > 1: movb (%ebx),%dl
and linked in vmlinux : > c017e7a5 <do_con_write+e1> movb (%ebx),%dl
@ -254,7 +254,7 @@ The assembly code
becomes the value pair
> c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5 ................
^this is ^this is
1b 3b
1b 3b
c017e7a5,c0199ff5 in the exception table of the kernel.
So, what actually happens if a fault from kernel mode with no suitable
@ -266,9 +266,9 @@ vma occurs?
3.) CPU calls do_page_fault
4.) do page fault calls search_exception_table (regs->eip == c017e7a5);
5.) search_exception_table looks up the address c017e7a5 in the
exception table (i.e. the contents of the ELF section __ex_table)
exception table (i.e. the contents of the ELF section __ex_table)
and returns the address of the associated fault handle code c0199ff5.
6.) do_page_fault modifies its own return address to point to the fault
6.) do_page_fault modifies its own return address to point to the fault
handle code and returns.
7.) execution continues in the fault handling code.
8.) 8a) EAX becomes -EFAULT (== -14)

View file

@ -3287,11 +3287,11 @@ F: include/linux/ivtv*
JFS FILESYSTEM
P: Dave Kleikamp
M: shaggy@austin.ibm.com
M: shaggy@linux.vnet.ibm.com
L: jfs-discussion@lists.sourceforge.net
W: http://jfs.sourceforge.net/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
S: Supported
S: Maintained
F: Documentation/filesystems/jfs.txt
F: fs/jfs/
@ -4407,7 +4407,7 @@ W: http://www.nongnu.org/orinoco/
S: Maintained
F: drivers/net/wireless/orinoco/
OSD LIBRARY
OSD LIBRARY and FILESYSTEM
P: Boaz Harrosh
M: bharrosh@panasas.com
P: Benny Halevy
@ -4416,6 +4416,9 @@ L: osd-dev@open-osd.org
W: http://open-osd.org
T: git git://git.open-osd.org/open-osd.git
S: Maintained
F: drivers/scsi/osd/
F: drivers/include/scsi/osd_*
F: fs/exofs/
P54 WIRELESS DRIVER
P: Michael Wu
@ -5851,7 +5854,7 @@ UBI FILE SYSTEM (UBIFS)
P: Artem Bityutskiy
M: dedekind@infradead.org
P: Adrian Hunter
M: ext-adrian.hunter@nokia.com
M: adrian.hunter@nokia.com
L: linux-mtd@lists.infradead.org
T: git git://git.infradead.org/ubifs-2.6.git
W: http://www.linux-mtd.infradead.org/doc/ubifs.html

View file

@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 31
EXTRAVERSION = -rc2
EXTRAVERSION = -rc3
NAME = Man-Eating Seals of Antiquity
# *DOCUMENTATION*
@ -343,7 +343,8 @@ KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration \
-Wno-format-security
-Wno-format-security \
-fno-delete-null-pointer-checks
KBUILD_AFLAGS := -D__ASSEMBLY__
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
@ -565,7 +566,7 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += $(call cc-option,-fwrapv)
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
# revert to pre-gcc-4.4 behaviour of .eh_frame
KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)

View file

@ -8,7 +8,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>

View file

@ -31,7 +31,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>

View file

@ -29,7 +29,6 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/sem.h>
#include <linux/msg.h>

View file

@ -15,7 +15,6 @@
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>

View file

@ -6,6 +6,8 @@
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/types.h>
/* floating point status register: */
#define FPSR_TRAP_VD (1 << 0) /* invalid op trap disabled */
#define FPSR_TRAP_DD (1 << 1) /* denormal trap disabled */

View file

@ -33,6 +33,7 @@
#ifndef _ASM_IA64_XEN_HYPERVISOR_H
#define _ASM_IA64_XEN_HYPERVISOR_H
#include <linux/err.h>
#include <xen/interface/xen.h>
#include <xen/interface/version.h> /* to compile feature.c */
#include <xen/features.h> /* to comiple xen-netfront.c */

View file

@ -6,6 +6,14 @@ int iommu_detected __read_mostly;
struct dma_map_ops *dma_ops;
EXPORT_SYMBOL(dma_ops);
#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
static int __init dma_init(void)
{
dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
}
fs_initcall(dma_init);
struct dma_map_ops *dma_get_ops(struct device *dev)
{
return dma_ops;

View file

@ -15,7 +15,6 @@
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/smp_lock.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>

View file

@ -19,7 +19,6 @@
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>

View file

@ -27,7 +27,6 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/ptrace.h>
#include <linux/signal.h>

View file

@ -21,7 +21,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>

View file

@ -15,7 +15,6 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/syscalls.h>
#include <linux/sem.h>
#include <linux/msg.h>

View file

@ -22,7 +22,6 @@
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/user.h>
#include <linux/security.h>

View file

@ -16,7 +16,6 @@
#include <linux/mm.h>
#include <linux/hugetlb.h>
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/sysctl.h>

View file

@ -13,7 +13,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>

View file

@ -12,7 +12,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>

View file

@ -13,7 +13,6 @@
#include <linux/syscalls.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
@ -21,7 +20,6 @@
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/utsname.h>
#include <linux/syscalls.h>
#include <linux/tty.h>
#include <asm/uaccess.h>

View file

@ -17,7 +17,6 @@
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>

View file

@ -20,7 +20,6 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/vt_kern.h> /* For unblank_screen() */

View file

@ -17,7 +17,6 @@
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>

View file

@ -736,15 +736,16 @@ void user_disable_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
#if defined(CONFIG_BOOKE)
/* If DAC then do not single step, skip */
if (task->thread.dabr)
return;
#endif
if (regs != NULL) {
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
#if defined(CONFIG_BOOKE)
/* If DAC don't clear DBCRO_IDM or MSR_DE */
if (task->thread.dabr)
task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT);
else {
task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
regs->msr &= ~MSR_DE;
}
#elif defined(CONFIG_40x)
task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
regs->msr &= ~MSR_DE;
#else

View file

@ -21,7 +21,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/regset.h>

View file

@ -80,10 +80,10 @@ _GLOBAL(load_up_altivec)
mtvscr vr0
REST_32VRS(0,r4,r5)
#ifndef CONFIG_SMP
/* Update last_task_used_math to 'current' */
/* Update last_task_used_altivec to 'current' */
subi r4,r5,THREAD /* Back to 'current' */
fromreal(r4)
PPC_STL r4,ADDROFF(last_task_used_math)(r3)
PPC_STL r4,ADDROFF(last_task_used_altivec)(r3)
#endif /* CONFIG_SMP */
/* restore registers and return */
blr
@ -172,7 +172,7 @@ _GLOBAL(load_up_vsx)
oris r12,r12,MSR_VSX@h
std r12,_MSR(r1)
#ifndef CONFIG_SMP
/* Update last_task_used_math to 'current' */
/* Update last_task_used_vsx to 'current' */
ld r4,PACACURRENT(r13)
std r4,0(r3)
#endif /* CONFIG_SMP */

View file

@ -95,6 +95,11 @@ config S390
select HAVE_ARCH_TRACEHOOK
select INIT_ALL_POSSIBLE
select HAVE_PERF_COUNTERS
select GENERIC_ATOMIC64 if !64BIT
config SCHED_OMIT_FRAME_POINTER
bool
default y
source "init/Kconfig"
@ -116,6 +121,9 @@ config 32BIT
bool
default y if !64BIT
config KTIME_SCALAR
def_bool 32BIT
config SMP
bool "Symmetric multi-processing support"
---help---

View file

@ -268,7 +268,12 @@ static __inline__ int atomic64_add_unless(atomic64_t *v,
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
#undef __CSG_LOOP
#endif
#else /* __s390x__ */
#include <asm-generic/atomic64.h>
#endif /* __s390x__ */
#define smp_mb__before_atomic_dec() smp_mb()
#define smp_mb__after_atomic_dec() smp_mb()

View file

@ -6,3 +6,5 @@
static inline void set_perf_counter_pending(void) {}
static inline void clear_perf_counter_pending(void) {}
#define PERF_COUNTER_INDEX_OFFSET 0

View file

@ -15,7 +15,6 @@
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>

View file

@ -70,6 +70,7 @@ struct shutdown_action {
char *name;
void (*fn) (struct shutdown_trigger *trigger);
int (*init) (void);
int init_rc;
};
static char *ipl_type_str(enum ipl_type type)
@ -1486,11 +1487,13 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
int i;
for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
if (!shutdown_actions_list[i])
continue;
if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
trigger->action = shutdown_actions_list[i];
return len;
if (shutdown_actions_list[i]->init_rc) {
return shutdown_actions_list[i]->init_rc;
} else {
trigger->action = shutdown_actions_list[i];
return len;
}
}
}
return -EINVAL;
@ -1640,8 +1643,8 @@ static void __init shutdown_actions_init(void)
for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
if (!shutdown_actions_list[i]->init)
continue;
if (shutdown_actions_list[i]->init())
shutdown_actions_list[i] = NULL;
shutdown_actions_list[i]->init_rc =
shutdown_actions_list[i]->init();
}
}

View file

@ -26,7 +26,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>

View file

@ -3,6 +3,6 @@
#
lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o

View file

@ -36,9 +36,11 @@ static void __udelay_disabled(unsigned long usecs)
cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
__ctl_load(cr0 , 0, 0);
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
lockdep_off();
trace_hardirqs_on();
__load_psw_mask(mask);
local_irq_disable();
lockdep_on();
__ctl_load(cr0_saved, 0, 0);
local_tick_enable(clock_saved);
set_clock_comparator(S390_lowcore.clock_comparator);

26
arch/s390/lib/ucmpdi2.c Normal file
View file

@ -0,0 +1,26 @@
#include <linux/module.h>
union ull_union {
unsigned long long ull;
struct {
unsigned int high;
unsigned int low;
} ui;
};
int __ucmpdi2(unsigned long long a, unsigned long long b)
{
union ull_union au = {.ull = a};
union ull_union bu = {.ull = b};
if (au.ui.high < bu.ui.high)
return 0;
else if (au.ui.high > bu.ui.high)
return 2;
if (au.ui.low < bu.ui.low)
return 0;
else if (au.ui.low > bu.ui.low)
return 2;
return 1;
}
EXPORT_SYMBOL(__ucmpdi2);

View file

@ -22,7 +22,6 @@
#include <linux/compat.h>
#include <linux/smp.h>
#include <linux/kdebug.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/module.h>

View file

@ -304,6 +304,7 @@ static struct platform_device sh_eth_device = {
};
static struct r8a66597_platdata sh7724_usb0_host_data = {
.on_chip = 1,
};
static struct resource sh7724_usb0_host_resources[] = {

View file

@ -4,6 +4,9 @@
#include <asm/clock.h>
#include <asm/io.h>
#define HWBLK_CNT_USAGE 0
#define HWBLK_CNT_NR 1
#define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */
#define HWBLK_AREA(_flags, _parent) \
@ -13,7 +16,7 @@
}
struct hwblk_area {
unsigned long cnt;
int cnt[HWBLK_CNT_NR];
unsigned char parent;
unsigned char flags;
};
@ -29,7 +32,7 @@ struct hwblk {
void __iomem *mstp;
unsigned char bit;
unsigned char area;
unsigned long cnt;
int cnt[HWBLK_CNT_NR];
};
struct hwblk_info {
@ -46,6 +49,12 @@ int arch_hwblk_sleep_mode(void);
int hwblk_register(struct hwblk_info *info);
int hwblk_init(void);
void hwblk_enable(struct hwblk_info *info, int hwblk);
void hwblk_disable(struct hwblk_info *info, int hwblk);
void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt);
void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt);
/* allow clocks to enable and disable hardware blocks */
#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \
{ \

View file

@ -265,4 +265,21 @@ enum {
GPIO_FN_IDEA1, GPIO_FN_IDEA0,
};
enum {
HWBLK_UNKNOWN = 0,
HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_L2C, HWBLK_ILMEM, HWBLK_FPU,
HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY,
HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC, HWBLK_SUBC,
HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1,
HWBLK_FLCTL,
HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2,
HWBLK_SCIF3, HWBLK_SCIF4, HWBLK_SCIF5,
HWBLK_MSIOF0, HWBLK_MSIOF1, HWBLK_MERAM, HWBLK_IIC, HWBLK_RTC,
HWBLK_ATAPI, HWBLK_ADC, HWBLK_TPU, HWBLK_IRDA, HWBLK_TSIF, HWBLK_ICB,
HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_KEYSC, HWBLK_USB,
HWBLK_2DG, HWBLK_SIU, HWBLK_VEU2H1, HWBLK_VOU, HWBLK_BEU, HWBLK_CEU,
HWBLK_VEU2H0, HWBLK_VPU, HWBLK_LCDC,
HWBLK_NR,
};
#endif /* __ASM_SH7723_H__ */

View file

@ -9,38 +9,64 @@
static DEFINE_SPINLOCK(hwblk_lock);
static void hwblk_area_inc(struct hwblk_info *info, int area)
static void hwblk_area_mod_cnt(struct hwblk_info *info,
int area, int counter, int value, int goal)
{
struct hwblk_area *hap = info->areas + area;
hap->cnt++;
if (hap->cnt == 1)
if (hap->flags & HWBLK_AREA_FLAG_PARENT)
hwblk_area_inc(info, hap->parent);
hap->cnt[counter] += value;
if (hap->cnt[counter] != goal)
return;
if (hap->flags & HWBLK_AREA_FLAG_PARENT)
hwblk_area_mod_cnt(info, hap->parent, counter, value, goal);
}
static void hwblk_area_dec(struct hwblk_info *info, int area)
static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
int counter, int value, int goal)
{
struct hwblk_area *hap = info->areas + area;
struct hwblk *hp = info->hwblks + hwblk;
if (hap->cnt == 1)
if (hap->flags & HWBLK_AREA_FLAG_PARENT)
hwblk_area_dec(info, hap->parent);
hap->cnt--;
hp->cnt[counter] += value;
if (hp->cnt[counter] == goal)
hwblk_area_mod_cnt(info, hp->area, counter, value, goal);
return hp->cnt[counter];
}
static void hwblk_enable(struct hwblk_info *info, int hwblk)
static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk,
int counter, int value, int goal)
{
unsigned long flags;
spin_lock_irqsave(&hwblk_lock, flags);
__hwblk_mod_cnt(info, hwblk, counter, value, goal);
spin_unlock_irqrestore(&hwblk_lock, flags);
}
void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter)
{
hwblk_mod_cnt(info, hwblk, counter, 1, 1);
}
void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter)
{
hwblk_mod_cnt(info, hwblk, counter, -1, 0);
}
void hwblk_enable(struct hwblk_info *info, int hwblk)
{
struct hwblk *hp = info->hwblks + hwblk;
unsigned long tmp;
unsigned long flags;
int ret;
spin_lock_irqsave(&hwblk_lock, flags);
hp->cnt++;
if (hp->cnt == 1) {
hwblk_area_inc(info, hp->area);
ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1);
if (ret == 1) {
tmp = __raw_readl(hp->mstp);
tmp &= ~(1 << hp->bit);
__raw_writel(tmp, hp->mstp);
@ -49,27 +75,26 @@ static void hwblk_enable(struct hwblk_info *info, int hwblk)
spin_unlock_irqrestore(&hwblk_lock, flags);
}
static void hwblk_disable(struct hwblk_info *info, int hwblk)
void hwblk_disable(struct hwblk_info *info, int hwblk)
{
struct hwblk *hp = info->hwblks + hwblk;
unsigned long tmp;
unsigned long flags;
int ret;
spin_lock_irqsave(&hwblk_lock, flags);
if (hp->cnt == 1) {
hwblk_area_dec(info, hp->area);
ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0);
if (ret == 0) {
tmp = __raw_readl(hp->mstp);
tmp |= 1 << hp->bit;
__raw_writel(tmp, hp->mstp);
}
hp->cnt--;
spin_unlock_irqrestore(&hwblk_lock, flags);
}
static struct hwblk_info *hwblk_info;
struct hwblk_info *hwblk_info;
int __init hwblk_register(struct hwblk_info *info)
{

View file

@ -26,7 +26,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o hwblk-sh7722.o
clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o
clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o hwblk-sh7723.o
clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o

View file

@ -22,6 +22,8 @@
#include <linux/kernel.h>
#include <linux/io.h>
#include <asm/clock.h>
#include <asm/hwblk.h>
#include <cpu/sh7723.h>
/* SH7723 registers */
#define FRQCR 0xa4150000
@ -140,60 +142,64 @@ struct clk div6_clks[] = {
SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0),
};
#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \
SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT)
#define R_CLK (&r_clk)
#define P_CLK (&div4_clks[DIV4_P])
#define B_CLK (&div4_clks[DIV4_B])
#define U_CLK (&div4_clks[DIV4_U])
#define I_CLK (&div4_clks[DIV4_I])
#define SH_CLK (&div4_clks[DIV4_SH])
static struct clk mstp_clks[] = {
/* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0),
MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0),
MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0),
MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0),
MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0),
MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0),
MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0),
MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1),
MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0),
MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0),
MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0),
MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0),
MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0),
MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0),
MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1),
MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0),
MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0),
MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0),
MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0),
MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0),
MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0),
MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0),
MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0),
MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0),
MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0),
MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0),
SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0),
SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0),
SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0),
SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0),
SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0),
SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0),
SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0),
SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0),
SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0),
SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0),
SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0),
SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0),
SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0),
SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0),
SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0),
SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0),
SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0),
SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0),
MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0),
MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0),
SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0),
SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0),
MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0),
MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0),
MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0),
MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0),
MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0),
MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1),
MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0),
MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0),
MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0),
MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0),
MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1),
MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0),
MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1),
MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1),
MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1),
MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1),
MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1),
MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1),
MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1),
SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0),
SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0),
SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0),
SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0),
SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0),
SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0),
SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0),
SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0),
SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0),
SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0),
SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0),
SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0),
SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0),
SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0),
SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT),
SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0),
};
int __init arch_clk_init(void)
@ -216,7 +222,7 @@ int __init arch_clk_init(void)
ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks));
if (!ret)
ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks));
ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks));
return ret;
}

View file

@ -91,10 +91,10 @@ static struct hwblk_info sh7722_hwblk_info = {
int arch_hwblk_sleep_mode(void)
{
if (!sh7722_hwblk_area[CORE_AREA].cnt)
if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
return SUSP_SH_STANDBY | SUSP_SH_SF;
if (!sh7722_hwblk_area[CORE_AREA_BM].cnt)
if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
return SUSP_SH_SLEEP | SUSP_SH_SF;
return SUSP_SH_SLEEP;

View file

@ -0,0 +1,117 @@
/*
* arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
*
* SH7723 hardware block support
*
* Copyright (C) 2009 Magnus Damm
*
* 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
*
* 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/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <asm/suspend.h>
#include <asm/hwblk.h>
#include <cpu/sh7723.h>
/* SH7723 registers */
#define MSTPCR0 0xa4150030
#define MSTPCR1 0xa4150034
#define MSTPCR2 0xa4150038
/* SH7723 Power Domains */
enum { CORE_AREA, SUB_AREA, CORE_AREA_BM };
static struct hwblk_area sh7723_hwblk_area[] = {
[CORE_AREA] = HWBLK_AREA(0, 0),
[CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA),
[SUB_AREA] = HWBLK_AREA(0, 0),
};
/* Table mapping HWBLK to Module Stop Bit and Power Domain */
static struct hwblk sh7723_hwblk[HWBLK_NR] = {
[HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA),
[HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA),
[HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA),
[HWBLK_L2C] = HWBLK(MSTPCR0, 28, CORE_AREA),
[HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA),
[HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA),
[HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA),
[HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM),
[HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA),
[HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA),
[HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA),
[HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA),
[HWBLK_SUBC] = HWBLK(MSTPCR0, 16, CORE_AREA),
[HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA),
[HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA),
[HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA),
[HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM),
[HWBLK_TMU1] = HWBLK(MSTPCR0, 11, CORE_AREA),
[HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA),
[HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA),
[HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA),
[HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA),
[HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA),
[HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA),
[HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA),
[HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA),
[HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA),
[HWBLK_MERAM] = HWBLK(MSTPCR0, 0, CORE_AREA),
[HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA),
[HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA),
[HWBLK_ATAPI] = HWBLK(MSTPCR2, 28, CORE_AREA_BM),
[HWBLK_ADC] = HWBLK(MSTPCR2, 27, CORE_AREA),
[HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA),
[HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA),
[HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA),
[HWBLK_ICB] = HWBLK(MSTPCR2, 21, CORE_AREA_BM),
[HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA),
[HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA),
[HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA),
[HWBLK_USB] = HWBLK(MSTPCR2, 11, CORE_AREA),
[HWBLK_2DG] = HWBLK(MSTPCR2, 10, CORE_AREA_BM),
[HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA),
[HWBLK_VEU2H1] = HWBLK(MSTPCR2, 6, CORE_AREA_BM),
[HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM),
[HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM),
[HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM),
[HWBLK_VEU2H0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM),
[HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM),
[HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM),
};
static struct hwblk_info sh7723_hwblk_info = {
.areas = sh7723_hwblk_area,
.nr_areas = ARRAY_SIZE(sh7723_hwblk_area),
.hwblks = sh7723_hwblk,
.nr_hwblks = ARRAY_SIZE(sh7723_hwblk),
};
int arch_hwblk_sleep_mode(void)
{
if (!sh7723_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE])
return SUSP_SH_STANDBY | SUSP_SH_SF;
if (!sh7723_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE])
return SUSP_SH_SLEEP | SUSP_SH_SF;
return SUSP_SH_SLEEP;
}
int __init arch_hwblk_init(void)
{
return hwblk_register(&sh7723_hwblk_info);
}

View file

@ -40,7 +40,7 @@ static struct platform_device iic_device = {
};
static struct r8a66597_platdata r8a66597_data = {
/* This set zero to all members */
.on_chip = 1,
};
static struct resource usb_host_resources[] = {

View file

@ -398,7 +398,7 @@ static struct platform_device rtc_device = {
};
static struct r8a66597_platdata r8a66597_data = {
/* This set zero to all members */
.on_chip = 1,
};
static struct resource sh7723_usb_host_resources[] = {

View file

@ -18,7 +18,6 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <asm/system.h>

View file

@ -16,7 +16,6 @@
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/security.h>
#include <linux/signal.h>
#include <linux/regset.h>

View file

@ -17,7 +17,6 @@
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/security.h>
#include <linux/seccomp.h>
#include <linux/audit.h>

View file

@ -11,7 +11,6 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>

View file

@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kdebug.h>
#include <asm/delay.h>

View file

@ -224,7 +224,12 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
if (!strcmp(type, "domain-services-port"))
bus_id_name = "ds";
if (strlen(bus_id_name) >= BUS_ID_SIZE - 4) {
/*
* 20 char is the old driver-core name size limit, which is no more.
* This check can probably be removed after review and possible
* adaption of the vio users name length handling.
*/
if (strlen(bus_id_name) >= 20 - 4) {
printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n",
bus_id_name);
return NULL;

View file

@ -161,6 +161,7 @@ extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr);
extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void);
extern void ioapic_insert_resources(void);
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
@ -180,6 +181,7 @@ extern void ioapic_write_entry(int apic, int pin,
#define io_apic_assign_pci_irqs 0
static const int timer_through_8259 = 0;
static inline void ioapic_init_mappings(void) { }
static inline void ioapic_insert_resources(void) { }
static inline void probe_nr_irqs_gsi(void) { }
#endif

View file

@ -30,7 +30,7 @@
#include <asm/hw_irq.h>
#include <asm/kvm_para.h>
/*G:031 But first, how does our Guest contact the Host to ask for privileged
/*G:030 But first, how does our Guest contact the Host to ask for privileged
* operations? There are two ways: the direct way is to make a "hypercall",
* to make requests of the Host Itself.
*

View file

@ -652,7 +652,8 @@ static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem,
return ret && es7000_apic_is_cluster();
}
struct apic apic_es7000_cluster = {
/* We've been warned by a false positive warning.Use __refdata to keep calm. */
struct apic __refdata apic_es7000_cluster = {
.name = "es7000",
.probe = probe_es7000,

View file

@ -4181,28 +4181,20 @@ void __init ioapic_init_mappings(void)
}
}
static int __init ioapic_insert_resources(void)
void __init ioapic_insert_resources(void)
{
int i;
struct resource *r = ioapic_resources;
if (!r) {
if (nr_ioapics > 0) {
if (nr_ioapics > 0)
printk(KERN_ERR
"IO APIC resources couldn't be allocated.\n");
return -1;
}
return 0;
return;
}
for (i = 0; i < nr_ioapics; i++) {
insert_resource(&iomem_resource, r);
r++;
}
return 0;
}
/* Insert the IO APIC resources after PCI initialization has occured to handle
* IO APICS that are mapped in on a BAR in PCI space. */
late_initcall(ioapic_insert_resources);

View file

@ -493,7 +493,8 @@ static void numaq_setup_portio_remap(void)
(u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD);
}
struct apic apic_numaq = {
/* Use __refdata to keep false positive warning calm. */
struct apic __refdata apic_numaq = {
.name = "NUMAQ",
.probe = probe_numaq,

View file

@ -60,7 +60,7 @@ static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift)
"adc %5,%%edx ; "
: "=A" (product), "=r" (tmp1), "=r" (tmp2)
: "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
#elif __x86_64__
#elif defined(__x86_64__)
__asm__ (
"mul %%rdx ; shrd $32,%%rdx,%%rax"
: "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );

View file

@ -379,6 +379,11 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
native_cpuid(ax, bx, cx, dx);
switch (function) {
case 0: /* ID and highest CPUID. Futureproof a little by sticking to
* older ones. */
if (*ax > 5)
*ax = 5;
break;
case 1: /* Basic feature request. */
/* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
*cx &= 0x00002201;
@ -1079,7 +1084,7 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
return insn_len;
}
/*G:030 Once we get to lguest_init(), we know we're a Guest. The various
/*G:029 Once we get to lguest_init(), we know we're a Guest. The various
* pv_ops structures in the kernel provide points for (almost) every routine we
* have to override to avoid privileged instructions. */
__init void lguest_init(void)

View file

@ -697,7 +697,7 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code,
if (!printk_ratelimit())
return;
printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
tsk->comm, task_pid_nr(tsk), address,
(void *)regs->ip, (void *)regs->sp, error_code);

View file

@ -35,6 +35,7 @@
#include <asm/pat.h>
#include <asm/e820.h>
#include <asm/pci_x86.h>
#include <asm/io_apic.h>
static int
@ -227,6 +228,12 @@ void __init pcibios_resource_survey(void)
pcibios_allocate_resources(1);
e820_reserve_resources_late();
/*
* Insert the IO APIC resources after PCI initialization has
* occured to handle IO APICS that are mapped in on a BAR in
* PCI space, but before trying to assign unassigned pci res.
*/
ioapic_insert_resources();
}
/**

View file

@ -513,6 +513,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */

View file

@ -3392,17 +3392,27 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
static int ata_dev_set_mode(struct ata_device *dev)
{
struct ata_port *ap = dev->link->ap;
struct ata_eh_context *ehc = &dev->link->eh_context;
const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER;
const char *dev_err_whine = "";
int ign_dev_err = 0;
unsigned int err_mask;
unsigned int err_mask = 0;
int rc;
dev->flags &= ~ATA_DFLAG_PIO;
if (dev->xfer_shift == ATA_SHIFT_PIO)
dev->flags |= ATA_DFLAG_PIO;
err_mask = ata_dev_set_xfermode(dev);
if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id))
dev_err_whine = " (SET_XFERMODE skipped)";
else {
if (nosetxfer)
ata_dev_printk(dev, KERN_WARNING,
"NOSETXFER but PATA detected - can't "
"skip SETXFER, might malfunction\n");
err_mask = ata_dev_set_xfermode(dev);
}
if (err_mask & ~AC_ERR_DEV)
goto fail;
@ -4297,6 +4307,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* Devices which aren't very happy with higher link speeds */
{ "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, },
/*
* Devices which choke on SETXFER. Applies only if both the
* device and controller are SATA.
*/
{ "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER },
/* End Marker */
{ }
};

View file

@ -2517,6 +2517,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
rc = ata_do_reset(link, reset, classes, deadline, true);
if (rc) {
failed_link = link;
goto fail;
}
}
} else {
if (verbose)

View file

@ -312,11 +312,12 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
static int __devexit pata_at91_remove(struct platform_device *pdev)
{
struct ata_host *host = dev_get_drvdata(&pdev->dev);
struct at91_ide_info *info = host->private_data;
struct at91_ide_info *info;
struct device *dev = &pdev->dev;
if (!host)
return 0;
info = host->private_data;
ata_host_detach(host);

View file

@ -428,6 +428,9 @@ int devres_release_all(struct device *dev)
{
unsigned long flags;
/* Looks like an uninitialized device structure */
if (WARN_ON(dev->devres_head.next == NULL))
return -ENODEV;
spin_lock_irqsave(&dev->devres_lock, flags);
return release_nodes(dev, dev->devres_head.next, &dev->devres_head,
flags);

View file

@ -217,8 +217,10 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
ret_count = -ENODEV;
goto out;
}
if (offset > fw->size)
return 0;
if (offset > fw->size) {
ret_count = 0;
goto out;
}
if (count > fw->size - offset)
count = fw->size - offset;

View file

@ -36,6 +36,7 @@
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/proc_fs.h>
#include <linux/reboot.h>
#include <linux/spinlock.h>

View file

@ -298,6 +298,22 @@ config BLK_DEV_NBD
If unsure, say N.
config BLK_DEV_OSD
tristate "OSD object-as-blkdev support"
depends on SCSI_OSD_ULD
---help---
Saying Y or M here will allow the exporting of a single SCSI
OSD (object-based storage) object as a Linux block device.
For example, if you create a 2G object on an OSD device,
you can then use this module to present that 2G object as
a Linux block device.
To compile this driver as a module, choose M here: the
module will be called osdblk.
If unsure, say N.
config BLK_DEV_SX8
tristate "Promise SATA SX8 support"
depends on PCI

View file

@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE) += xsysace.o
obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
obj-$(CONFIG_MG_DISK) += mg_disk.o
obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_OSD) += osdblk.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o

View file

@ -26,6 +26,7 @@
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/major.h>
#include <linux/fs.h>

View file

@ -61,7 +61,6 @@
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/loop.h>

701
drivers/block/osdblk.c Normal file
View file

@ -0,0 +1,701 @@
/*
osdblk.c -- Export a single SCSI OSD object as a Linux block device
Copyright 2009 Red Hat, Inc.
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.
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; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
Instructions for use
--------------------
1) Map a Linux block device to an existing OSD object.
In this example, we will use partition id 1234, object id 5678,
OSD device /dev/osd1.
$ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add
2) List all active blkdev<->object mappings.
In this example, we have performed step #1 twice, creating two blkdevs,
mapped to two separate OSD objects.
$ cat /sys/class/osdblk/list
0 174 1234 5678 /dev/osd1
1 179 1994 897123 /dev/osd0
The columns, in order, are:
- blkdev unique id
- blkdev assigned major
- OSD object partition id
- OSD object id
- OSD device
3) Remove an active blkdev<->object mapping.
In this example, we remove the mapping with blkdev unique id 1.
$ echo 1 > /sys/class/osdblk/remove
NOTE: The actual creation and deletion of OSD objects is outside the scope
of this driver.
*/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <scsi/osd_initiator.h>
#include <scsi/osd_attributes.h>
#include <scsi/osd_sec.h>
#include <scsi/scsi_device.h>
#define DRV_NAME "osdblk"
#define PFX DRV_NAME ": "
/* #define _OSDBLK_DEBUG */
#ifdef _OSDBLK_DEBUG
#define OSDBLK_DEBUG(fmt, a...) \
printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a)
#else
#define OSDBLK_DEBUG(fmt, a...) \
do { if (0) printk(fmt, ##a); } while (0)
#endif
MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
MODULE_DESCRIPTION("block device inside an OSD object osdblk.ko");
MODULE_LICENSE("GPL");
struct osdblk_device;
enum {
OSDBLK_MINORS_PER_MAJOR = 256, /* max minors per blkdev */
OSDBLK_MAX_REQ = 32, /* max parallel requests */
OSDBLK_OP_TIMEOUT = 4 * 60, /* sync OSD req timeout */
};
struct osdblk_request {
struct request *rq; /* blk layer request */
struct bio *bio; /* cloned bio */
struct osdblk_device *osdev; /* associated blkdev */
};
struct osdblk_device {
int id; /* blkdev unique id */
int major; /* blkdev assigned major */
struct gendisk *disk; /* blkdev's gendisk and rq */
struct request_queue *q;
struct osd_dev *osd; /* associated OSD */
char name[32]; /* blkdev name, e.g. osdblk34 */
spinlock_t lock; /* queue lock */
struct osd_obj_id obj; /* OSD partition, obj id */
uint8_t obj_cred[OSD_CAP_LEN]; /* OSD cred */
struct osdblk_request req[OSDBLK_MAX_REQ]; /* request table */
struct list_head node;
char osd_path[0]; /* OSD device path */
};
static struct class *class_osdblk; /* /sys/class/osdblk */
static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */
static LIST_HEAD(osdblkdev_list);
static struct block_device_operations osdblk_bd_ops = {
.owner = THIS_MODULE,
};
static const struct osd_attr g_attr_logical_length = ATTR_DEF(
OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
static void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN],
const struct osd_obj_id *obj)
{
osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
}
/* copied from exofs; move to libosd? */
/*
* Perform a synchronous OSD operation. copied from exofs; move to libosd?
*/
static int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential)
{
int ret;
or->timeout = timeout;
ret = osd_finalize_request(or, 0, credential, NULL);
if (ret)
return ret;
ret = osd_execute_request(or);
/* osd_req_decode_sense(or, ret); */
return ret;
}
/*
* Perform an asynchronous OSD operation. copied from exofs; move to libosd?
*/
static int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done,
void *caller_context, u8 *cred)
{
int ret;
ret = osd_finalize_request(or, 0, cred, NULL);
if (ret)
return ret;
ret = osd_execute_request_async(or, async_done, caller_context);
return ret;
}
/* copied from exofs; move to libosd? */
static int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr)
{
struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
void *iter = NULL;
int nelem;
do {
nelem = 1;
osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter);
if ((cur_attr.attr_page == attr->attr_page) &&
(cur_attr.attr_id == attr->attr_id)) {
attr->len = cur_attr.len;
attr->val_ptr = cur_attr.val_ptr;
return 0;
}
} while (iter);
return -EIO;
}
static int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out)
{
struct osd_request *or;
struct osd_attr attr;
int ret;
/* start request */
or = osd_start_request(osdev->osd, GFP_KERNEL);
if (!or)
return -ENOMEM;
/* create a get-attributes(length) request */
osd_req_get_attributes(or, &osdev->obj);
osd_req_add_get_attr_list(or, &g_attr_logical_length, 1);
/* execute op synchronously */
ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred);
if (ret)
goto out;
/* extract length from returned attribute info */
attr = g_attr_logical_length;
ret = extract_attr_from_req(or, &attr);
if (ret)
goto out;
*size_out = get_unaligned_be64(attr.val_ptr);
out:
osd_end_request(or);
return ret;
}
static void osdblk_osd_complete(struct osd_request *or, void *private)
{
struct osdblk_request *orq = private;
struct osd_sense_info osi;
int ret = osd_req_decode_sense(or, &osi);
if (ret) {
ret = -EIO;
OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret);
}
/* complete OSD request */
osd_end_request(or);
/* complete request passed to osdblk by block layer */
__blk_end_request_all(orq->rq, ret);
}
static void bio_chain_put(struct bio *chain)
{
struct bio *tmp;
while (chain) {
tmp = chain;
chain = chain->bi_next;
bio_put(tmp);
}
}
static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
{
struct bio *tmp, *new_chain = NULL, *tail = NULL;
while (old_chain) {
tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
if (!tmp)
goto err_out;
__bio_clone(tmp, old_chain);
tmp->bi_bdev = NULL;
gfpmask &= ~__GFP_WAIT;
tmp->bi_next = NULL;
if (!new_chain)
new_chain = tail = tmp;
else {
tail->bi_next = tmp;
tail = tmp;
}
old_chain = old_chain->bi_next;
}
return new_chain;
err_out:
OSDBLK_DEBUG("bio_chain_clone with err\n");
bio_chain_put(new_chain);
return NULL;
}
static void osdblk_rq_fn(struct request_queue *q)
{
struct osdblk_device *osdev = q->queuedata;
while (1) {
struct request *rq;
struct osdblk_request *orq;
struct osd_request *or;
struct bio *bio;
bool do_write, do_flush;
/* peek at request from block layer */
rq = blk_fetch_request(q);
if (!rq)
break;
/* filter out block requests we don't understand */
if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) {
blk_end_request_all(rq, 0);
continue;
}
/* deduce our operation (read, write, flush) */
/* I wish the block layer simplified cmd_type/cmd_flags/cmd[]
* into a clearly defined set of RPC commands:
* read, write, flush, scsi command, power mgmt req,
* driver-specific, etc.
*/
do_flush = (rq->special == (void *) 0xdeadbeefUL);
do_write = (rq_data_dir(rq) == WRITE);
if (!do_flush) { /* osd_flush does not use a bio */
/* a bio clone to be passed down to OSD request */
bio = bio_chain_clone(rq->bio, GFP_ATOMIC);
if (!bio)
break;
} else
bio = NULL;
/* alloc internal OSD request, for OSD command execution */
or = osd_start_request(osdev->osd, GFP_ATOMIC);
if (!or) {
bio_chain_put(bio);
OSDBLK_DEBUG("osd_start_request with err\n");
break;
}
orq = &osdev->req[rq->tag];
orq->rq = rq;
orq->bio = bio;
orq->osdev = osdev;
/* init OSD command: flush, write or read */
if (do_flush)
osd_req_flush_object(or, &osdev->obj,
OSD_CDB_FLUSH_ALL, 0, 0);
else if (do_write)
osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
bio, blk_rq_bytes(rq));
else
osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
bio, blk_rq_bytes(rq));
OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n",
do_flush ? "flush" : do_write ?
"write" : "read", blk_rq_bytes(rq),
blk_rq_pos(rq) * 512ULL);
/* begin OSD command execution */
if (osd_async_op(or, osdblk_osd_complete, orq,
osdev->obj_cred)) {
osd_end_request(or);
blk_requeue_request(q, rq);
bio_chain_put(bio);
OSDBLK_DEBUG("osd_execute_request_async with err\n");
break;
}
/* remove the special 'flush' marker, now that the command
* is executing
*/
rq->special = NULL;
}
}
static void osdblk_prepare_flush(struct request_queue *q, struct request *rq)
{
/* add driver-specific marker, to indicate that this request
* is a flush command
*/
rq->special = (void *) 0xdeadbeefUL;
}
static void osdblk_free_disk(struct osdblk_device *osdev)
{
struct gendisk *disk = osdev->disk;
if (!disk)
return;
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
if (disk->queue)
blk_cleanup_queue(disk->queue);
put_disk(disk);
}
static int osdblk_init_disk(struct osdblk_device *osdev)
{
struct gendisk *disk;
struct request_queue *q;
int rc;
u64 obj_size = 0;
/* contact OSD, request size info about the object being mapped */
rc = osdblk_get_obj_size(osdev, &obj_size);
if (rc)
return rc;
/* create gendisk info */
disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR);
if (!disk)
return -ENOMEM;
sprintf(disk->disk_name, DRV_NAME "%d", osdev->id);
disk->major = osdev->major;
disk->first_minor = 0;
disk->fops = &osdblk_bd_ops;
disk->private_data = osdev;
/* init rq */
q = blk_init_queue(osdblk_rq_fn, &osdev->lock);
if (!q) {
put_disk(disk);
return -ENOMEM;
}
/* switch queue to TCQ mode; allocate tag map */
rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL);
if (rc) {
blk_cleanup_queue(q);
put_disk(disk);
return rc;
}
/* Set our limits to the lower device limits, because osdblk cannot
* sleep when allocating a lower-request and therefore cannot be
* bouncing.
*/
blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
blk_queue_prep_rq(q, blk_queue_start_tag);
blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush);
disk->queue = q;
q->queuedata = osdev;
osdev->disk = disk;
osdev->q = q;
/* finally, announce the disk to the world */
set_capacity(disk, obj_size / 512ULL);
add_disk(disk);
printk(KERN_INFO "%s: Added of size 0x%llx\n",
disk->disk_name, (unsigned long long)obj_size);
return 0;
}
/********************************************************************
* /sys/class/osdblk/
* add map OSD object to blkdev
* remove unmap OSD object
* list show mappings
*******************************************************************/
static void class_osdblk_release(struct class *cls)
{
kfree(cls);
}
static ssize_t class_osdblk_list(struct class *c, char *data)
{
int n = 0;
struct list_head *tmp;
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
list_for_each(tmp, &osdblkdev_list) {
struct osdblk_device *osdev;
osdev = list_entry(tmp, struct osdblk_device, node);
n += sprintf(data+n, "%d %d %llu %llu %s\n",
osdev->id,
osdev->major,
osdev->obj.partition,
osdev->obj.id,
osdev->osd_path);
}
mutex_unlock(&ctl_mutex);
return n;
}
static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count)
{
struct osdblk_device *osdev;
ssize_t rc;
int irc, new_id = 0;
struct list_head *tmp;
if (!try_module_get(THIS_MODULE))
return -ENODEV;
/* new osdblk_device object */
osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL);
if (!osdev) {
rc = -ENOMEM;
goto err_out_mod;
}
/* static osdblk_device initialization */
spin_lock_init(&osdev->lock);
INIT_LIST_HEAD(&osdev->node);
/* generate unique id: find highest unique id, add one */
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
list_for_each(tmp, &osdblkdev_list) {
struct osdblk_device *osdev;
osdev = list_entry(tmp, struct osdblk_device, node);
if (osdev->id > new_id)
new_id = osdev->id + 1;
}
osdev->id = new_id;
/* add to global list */
list_add_tail(&osdev->node, &osdblkdev_list);
mutex_unlock(&ctl_mutex);
/* parse add command */
if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id,
osdev->osd_path) != 3) {
rc = -EINVAL;
goto err_out_slot;
}
/* initialize rest of new object */
sprintf(osdev->name, DRV_NAME "%d", osdev->id);
/* contact requested OSD */
osdev->osd = osduld_path_lookup(osdev->osd_path);
if (IS_ERR(osdev->osd)) {
rc = PTR_ERR(osdev->osd);
goto err_out_slot;
}
/* build OSD credential */
osdblk_make_credential(osdev->obj_cred, &osdev->obj);
/* register our block device */
irc = register_blkdev(0, osdev->name);
if (irc < 0) {
rc = irc;
goto err_out_osd;
}
osdev->major = irc;
/* set up and announce blkdev mapping */
rc = osdblk_init_disk(osdev);
if (rc)
goto err_out_blkdev;
return count;
err_out_blkdev:
unregister_blkdev(osdev->major, osdev->name);
err_out_osd:
osduld_put_device(osdev->osd);
err_out_slot:
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
list_del_init(&osdev->node);
mutex_unlock(&ctl_mutex);
kfree(osdev);
err_out_mod:
OSDBLK_DEBUG("Error adding device %s\n", buf);
module_put(THIS_MODULE);
return rc;
}
static ssize_t class_osdblk_remove(struct class *c, const char *buf,
size_t count)
{
struct osdblk_device *osdev = NULL;
int target_id, rc;
unsigned long ul;
struct list_head *tmp;
rc = strict_strtoul(buf, 10, &ul);
if (rc)
return rc;
/* convert to int; abort if we lost anything in the conversion */
target_id = (int) ul;
if (target_id != ul)
return -EINVAL;
/* remove object from list immediately */
mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
list_for_each(tmp, &osdblkdev_list) {
osdev = list_entry(tmp, struct osdblk_device, node);
if (osdev->id == target_id) {
list_del_init(&osdev->node);
break;
}
osdev = NULL;
}
mutex_unlock(&ctl_mutex);
if (!osdev)
return -ENOENT;
/* clean up and free blkdev and associated OSD connection */
osdblk_free_disk(osdev);
unregister_blkdev(osdev->major, osdev->name);
osduld_put_device(osdev->osd);
kfree(osdev);
/* release module ref */
module_put(THIS_MODULE);
return count;
}
static struct class_attribute class_osdblk_attrs[] = {
__ATTR(add, 0200, NULL, class_osdblk_add),
__ATTR(remove, 0200, NULL, class_osdblk_remove),
__ATTR(list, 0444, class_osdblk_list, NULL),
__ATTR_NULL
};
static int osdblk_sysfs_init(void)
{
int ret = 0;
/*
* create control files in sysfs
* /sys/class/osdblk/...
*/
class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL);
if (!class_osdblk)
return -ENOMEM;
class_osdblk->name = DRV_NAME;
class_osdblk->owner = THIS_MODULE;
class_osdblk->class_release = class_osdblk_release;
class_osdblk->class_attrs = class_osdblk_attrs;
ret = class_register(class_osdblk);
if (ret) {
kfree(class_osdblk);
class_osdblk = NULL;
printk(PFX "failed to create class osdblk\n");
return ret;
}
return 0;
}
static void osdblk_sysfs_cleanup(void)
{
if (class_osdblk)
class_destroy(class_osdblk);
class_osdblk = NULL;
}
static int __init osdblk_init(void)
{
int rc;
rc = osdblk_sysfs_init();
if (rc)
return rc;
return 0;
}
static void __exit osdblk_exit(void)
{
osdblk_sysfs_cleanup();
}
module_init(osdblk_init);
module_exit(osdblk_exit);

View file

@ -213,7 +213,7 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
* Only allow the generic SCSI ioctls if the host can support it.
*/
if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
return -ENOIOCTLCMD;
return -ENOTTY;
return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
}
@ -360,6 +360,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2);
blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2);
/* No need to bounce any requests */
blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY);
/* No real sector limit. */
blk_queue_max_sectors(vblk->disk->queue, -1U);

View file

@ -28,7 +28,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/sched.h>

View file

@ -81,6 +81,7 @@ static char *serial_version = "4.30";
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/bitops.h>

View file

@ -633,6 +633,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/smp_lock.h>
#include <linux/major.h>
#include <linux/string.h>
#include <linux/fcntl.h>

View file

@ -36,6 +36,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>

View file

@ -122,6 +122,7 @@
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/serial.h>
#include <linux/smp_lock.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/timer.h>

View file

@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>

View file

@ -34,6 +34,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/major.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>

View file

@ -23,6 +23,7 @@
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tty.h>

View file

@ -97,6 +97,7 @@
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/string.h> /* used in new tty drivers */
#include <linux/signal.h> /* used in new tty drivers */
#include <linux/if.h>

View file

@ -58,6 +58,7 @@
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/tty.h>
#include <linux/errno.h>
#include <linux/string.h> /* used in new tty drivers */

View file

@ -1331,9 +1331,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
static void n_tty_write_wakeup(struct tty_struct *tty)
{
/* Write out any echoed characters that are still pending */
process_echoes(tty);
if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
}

View file

@ -828,7 +828,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
struct port *port = &dc->port[index];
void __iomem *addr = port->dl_addr[port->toggle_dl];
struct tty_struct *tty = tty_port_tty_get(&port->port);
int i;
int i, ret;
if (unlikely(!tty)) {
DBG1("tty not open for port: %d?", index);
@ -844,12 +844,14 @@ static int receive_data(enum port_type index, struct nozomi *dc)
/* disable interrupt in downlink... */
disable_transmit_dl(index, dc);
return 0;
ret = 0;
goto put;
}
if (unlikely(size == 0)) {
dev_err(&dc->pdev->dev, "size == 0?\n");
return 1;
ret = 1;
goto put;
}
tty_buffer_request_room(tty, size);
@ -871,8 +873,10 @@ static int receive_data(enum port_type index, struct nozomi *dc)
}
set_bit(index, &dc->flip);
ret = 1;
put:
tty_kref_put(tty);
return 1;
return ret;
}
/* Debug for interrupts */

View file

@ -22,6 +22,7 @@
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/sysctl.h>
#include <linux/device.h>
#include <linux/uaccess.h>

View file

@ -44,6 +44,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/miscdevice.h>
#include <linux/init.h>

View file

@ -47,6 +47,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/tty_flip.h>
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/device.h>

View file

@ -73,6 +73,7 @@
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>

View file

@ -52,6 +52,7 @@
#include <linux/interrupt.h>
#include <linux/serial.h>
#include <linux/serialP.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>

View file

@ -87,6 +87,7 @@
#include <linux/tty_flip.h>
#include <linux/mm.h>
#include <linux/serial.h>
#include <linux/smp_lock.h>
#include <linux/fcntl.h>
#include <linux/major.h>
#include <linux/delay.h>

View file

@ -216,6 +216,7 @@
#include <linux/eisa.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/bitops.h>

View file

@ -81,6 +81,7 @@
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>

View file

@ -62,6 +62,7 @@
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/init.h>

View file

@ -52,6 +52,7 @@
#include <linux/mm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>
#include <linux/init.h>

View file

@ -26,7 +26,6 @@
#include <linux/poll.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include "tpm.h"

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