mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-03 17:40:04 +00:00
Merge branches 'sh/hwblk' and 'sh/platform-updates'
This commit is contained in:
commit
c358fc46ef
455 changed files with 4603 additions and 4270 deletions
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
11
MAINTAINERS
11
MAINTAINERS
|
@ -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
|
||||
|
|
7
Makefile
7
Makefile
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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() */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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---
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
26
arch/s390/lib/ucmpdi2.c
Normal 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);
|
|
@ -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>
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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) \
|
||||
{ \
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
117
arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
Normal file
117
arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c
Normal 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);
|
||||
}
|
|
@ -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[] = {
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
701
drivers/block/osdblk.c
Normal 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);
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue