Merge git://git.kernel.org/pub/scm/linux/kernel/git/bunk/trivial
* git://git.kernel.org/pub/scm/linux/kernel/git/bunk/trivial:
further UTF-8 fixes and name correction
Fix wrong identifier name in Documentation/kref.txt
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 6491b2c..3af3e65 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -73,9 +73,9 @@
If the new code is substantial, addition of subsystem-specific fault
injection might be appropriate.
-22: Newly-added code has been compiled with `gcc -W'. This will generate
- lots of noise, but is good for finding bugs like "warning: comparison
- between signed and unsigned".
+22: Newly-added code has been compiled with `gcc -W' (use "make
+ EXTRA_CFLAGS=-W"). This will generate lots of noise, but is good for
+ finding bugs like "warning: comparison between signed and unsigned".
23: Tested after it has been merged into the -mm patchset to make sure
that it still works with all of the other queued patches and various
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index f8528db..e8be0ab 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -66,7 +66,9 @@
used for several very different kinds of GPIO controller.
That said, if the convention is supported on their platform, drivers should
-use it when possible:
+use it when possible. Platforms should declare GENERIC_GPIO support in
+Kconfig (boolean true), which multi-platform drivers can depend on when
+using the include file:
#include <asm/gpio.h>
diff --git a/Documentation/mips/pci/pci.README b/Documentation/mips/pci/pci.README
deleted file mode 100644
index 8697ee4..0000000
--- a/Documentation/mips/pci/pci.README
+++ /dev/null
@@ -1,54 +0,0 @@
-
-Pete Popov, ppopov@pacbell.net
-07/11/2001
-
-This README briefly explains how to use the pci and pci_auto
-code in arch/mips/kernel. The code was ported from PowerPC and
-modified slightly. It has been tested pretty well on PPC on some
-rather complex systems with multiple bridges and devices behind
-each bridge. However, at the time this README was written, the
-mips port was tested only on boards with a single pci bus and
-no P2P bridges. It's very possible that on boards with P2P
-bridges some modifications have to be made. The code will
-evolve, no doubt, but currently every single mips board
-is doing its own pcibios thing and it has become a big
-mess. This generic pci code is meant to clean up the mips
-pci mess and make it easier to add pci support to new boards.
-
-inside the define for your board in arch/mips/config.in.
-For example, the Galileo EV96100 board looks like this:
-
-if [ "$CONFIG_MIPS_EV96100" = "y" ]; then
- define_bool CONFIG_PCI y
- define_bool CONFIG_MIPS_GT96100 y
- define_bool CONFIG_NEW_PCI y
- define_bool CONFIG_SWAP_IO_SPACE y
-fi
-
-
-Next, if you want to use the arch/mips/kernel/pci code, which has the
-pcibios_init() function, add
-
-define_bool CONFIG_NEW_PCI y
-
-inside the define for your board. Again, the EV96100 example above
-show NEW_PCI turned on.
-
-
-Now you need to add your files to hook in your pci configuration
-cycles. Usually you'll need only a couple of files named something
-like pci_fixups.c and pci_ops.c. You can copy the templates
-provided and fill in the code.
-
-The file pci_ops.c should contain the pci configuration cycles routines.
-It also has the mips_pci_channels[] array which contains the descriptors
-of each pci controller.
-
-The file pci_fixups.c contains a few routines to do interrupt fixups,
-resources fixups, and, if needed, pci bios fixups.
-
-Usually you'll put your pci_fixups.c file in your board specific directory,
-since the functions in that file are board specific. The functions in
-pci_ops.c, on the other hand, are usually pci controller specific so that
-file could be shared among a few different boards using the same
-pci controller.
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index 9550f37..1e7a101 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -1195,7 +1195,7 @@
/*
*
*/
-static void __attribute__((unused)) gdbstub_show_regs(void)
+static void __maybe_unused gdbstub_show_regs(void)
{
unsigned long *reg;
int loop;
@@ -1223,7 +1223,7 @@
/*
* dump debugging regs
*/
-static void __attribute__((unused)) gdbstub_dump_debugregs(void)
+static void __maybe_unused gdbstub_dump_debugregs(void)
{
gdbstub_printk("DCR %08lx ", __debug_status.dcr);
gdbstub_printk("BRR %08lx\n", __debug_status.brr);
@@ -2079,25 +2079,25 @@
* GDB wants to call malloc() and free() to allocate memory for calling kernel
* functions directly from its command line
*/
-static void *malloc(size_t size) __attribute__((unused));
+static void *malloc(size_t size) __maybe_unused;
static void *malloc(size_t size)
{
return kmalloc(size, GFP_ATOMIC);
}
-static void free(void *p) __attribute__((unused));
+static void free(void *p) __maybe_unused;
static void free(void *p)
{
kfree(p);
}
-static uint32_t ___get_HSR0(void) __attribute__((unused));
+static uint32_t ___get_HSR0(void) __maybe_unused;
static uint32_t ___get_HSR0(void)
{
return __get_HSR(0);
}
-static uint32_t ___set_HSR0(uint32_t x) __attribute__((unused));
+static uint32_t ___set_HSR0(uint32_t x) __maybe_unused;
static uint32_t ___set_HSR0(uint32_t x)
{
__set_HSR(0, x);
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
index dab98fd..54e21c3 100644
--- a/arch/h8300/kernel/syscalls.S
+++ b/arch/h8300/kernel/syscalls.S
@@ -31,7 +31,7 @@
.long SYMBOL_NAME(sys_mknod)
.long SYMBOL_NAME(sys_chmod) /* 15 */
.long SYMBOL_NAME(sys_chown16)
- .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */
.long SYMBOL_NAME(sys_stat)
.long SYMBOL_NAME(sys_lseek)
.long SYMBOL_NAME(sys_getpid) /* 20 */
@@ -45,11 +45,11 @@
.long SYMBOL_NAME(sys_fstat)
.long SYMBOL_NAME(sys_pause)
.long SYMBOL_NAME(sys_utime) /* 30 */
- .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */
- .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */
.long SYMBOL_NAME(sys_access)
.long SYMBOL_NAME(sys_nice)
- .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* 35 old ftime syscall holder */
.long SYMBOL_NAME(sys_sync)
.long SYMBOL_NAME(sys_kill)
.long SYMBOL_NAME(sys_rename)
@@ -58,7 +58,7 @@
.long SYMBOL_NAME(sys_dup)
.long SYMBOL_NAME(sys_pipe)
.long SYMBOL_NAME(sys_times)
- .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */
.long SYMBOL_NAME(sys_brk) /* 45 */
.long SYMBOL_NAME(sys_setgid16)
.long SYMBOL_NAME(sys_getgid16)
@@ -66,13 +66,13 @@
.long SYMBOL_NAME(sys_geteuid16)
.long SYMBOL_NAME(sys_getegid16) /* 50 */
.long SYMBOL_NAME(sys_acct)
- .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */
- .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */
+ .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */
.long SYMBOL_NAME(sys_ioctl)
.long SYMBOL_NAME(sys_fcntl) /* 55 */
- .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */
.long SYMBOL_NAME(sys_setpgid)
- .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */
.long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_umask) /* 60 */
.long SYMBOL_NAME(sys_chroot)
@@ -112,7 +112,7 @@
.long SYMBOL_NAME(sys_fchown16) /* 95 */
.long SYMBOL_NAME(sys_getpriority)
.long SYMBOL_NAME(sys_setpriority)
- .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */
+ .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */
.long SYMBOL_NAME(sys_statfs)
.long SYMBOL_NAME(sys_fstatfs) /* 100 */
.long SYMBOL_NAME(sys_ni_syscall) /* ioperm for i386 */
@@ -202,8 +202,8 @@
.long SYMBOL_NAME(sys_capset) /* 185 */
.long SYMBOL_NAME(sys_sigaltstack)
.long SYMBOL_NAME(sys_sendfile)
- .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
- .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
.long SYMBOL_NAME(sys_vfork) /* 190 */
.long SYMBOL_NAME(sys_getrlimit)
.long SYMBOL_NAME(sys_mmap2)
@@ -236,10 +236,10 @@
.long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_getdents64) /* 220 */
.long SYMBOL_NAME(sys_fcntl64)
- .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */
- .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall) /* reserved TUX */
+ .long SYMBOL_NAME(sys_ni_syscall) /* reserved Security */
.long SYMBOL_NAME(sys_gettid)
- .long SYMBOL_NAME(sys_ni_syscall) /* 225 */ /* sys_readahead */
+ .long SYMBOL_NAME(sys_readahead) /* 225 */
.long SYMBOL_NAME(sys_setxattr)
.long SYMBOL_NAME(sys_lsetxattr)
.long SYMBOL_NAME(sys_fsetxattr)
@@ -257,8 +257,8 @@
.long SYMBOL_NAME(sys_futex) /* 240 */
.long SYMBOL_NAME(sys_sched_setaffinity)
.long SYMBOL_NAME(sys_sched_getaffinity)
- .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */
- .long SYMBOL_NAME(sys_ni_syscall) /* sys_get_thread_area */
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_ni_syscall)
.long SYMBOL_NAME(sys_io_setup) /* 245 */
.long SYMBOL_NAME(sys_io_destroy)
.long SYMBOL_NAME(sys_io_getevents)
@@ -288,8 +288,8 @@
.long SYMBOL_NAME(sys_utimes)
.long SYMBOL_NAME(sys_fadvise64_64)
.long SYMBOL_NAME(sys_ni_syscall) /* sys_vserver */
- .long SYMBOL_NAME(sys_mbind)
- .long SYMBOL_NAME(sys_get_mempolicy)
+ .long SYMBOL_NAME(sys_ni_syscall)
+ .long SYMBOL_NAME(sys_get_mempolicy) /* 275 */
.long SYMBOL_NAME(sys_set_mempolicy)
.long SYMBOL_NAME(sys_mq_open)
.long SYMBOL_NAME(sys_mq_unlink)
@@ -297,16 +297,42 @@
.long SYMBOL_NAME(sys_mq_timedreceive) /* 280 */
.long SYMBOL_NAME(sys_mq_notify)
.long SYMBOL_NAME(sys_mq_getsetattr)
- .long SYMBOL_NAME(sys_ni_syscall) /* reserved for kexec */
.long SYMBOL_NAME(sys_waitid)
- .long SYMBOL_NAME(sys_ni_syscall) /* 285 */ /* available */
- .long SYMBOL_NAME(sys_add_key)
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_kexec_load */
+ .long SYMBOL_NAME(sys_add_key) /* 285 */
.long SYMBOL_NAME(sys_request_key)
.long SYMBOL_NAME(sys_keyctl)
-
- .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
- .long SYMBOL_NAME(sys_ni_syscall)
- .endr
+ .long SYMBOL_NAME(sys_ioprio_set)
+ .long SYMBOL_NAME(sys_ioprio_get) /* 290 */
+ .long SYMBOL_NAME(sys_inotify_init)
+ .long SYMBOL_NAME(sys_inotify_add_watch)
+ .long SYMBOL_NAME(sys_inotify_rm_watch)
+ .long SYMBOL_NAME(sys_migrate_pages)
+ .long SYMBOL_NAME(sys_openat) /* 295 */
+ .long SYMBOL_NAME(sys_mkdirat)
+ .long SYMBOL_NAME(sys_mknodat)
+ .long SYMBOL_NAME(sys_fchownat)
+ .long SYMBOL_NAME(sys_futimesat)
+ .long SYMBOL_NAME(sys_fstatat64) /* 300 */
+ .long SYMBOL_NAME(sys_unlinkat)
+ .long SYMBOL_NAME(sys_renameat)
+ .long SYMBOL_NAME(sys_linkat)
+ .long SYMBOL_NAME(sys_symlinkat)
+ .long SYMBOL_NAME(sys_readlinkat) /* 305 */
+ .long SYMBOL_NAME(sys_fchmodat)
+ .long SYMBOL_NAME(sys_faccessat)
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_pselect6 */
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_ppoll */
+ .long SYMBOL_NAME(sys_unshare) /* 310 */
+ .long SYMBOL_NAME(sys_set_robust_list)
+ .long SYMBOL_NAME(sys_get_robust_list)
+ .long SYMBOL_NAME(sys_splice)
+ .long SYMBOL_NAME(sys_sync_file_range)
+ .long SYMBOL_NAME(sys_tee) /* 315 */
+ .long SYMBOL_NAME(sys_vmsplice)
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_move_pages */
+ .long SYMBOL_NAME(sys_getcpu)
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_pwait */
.macro call_sp addr
mov.l #SYMBOL_NAME(\addr),er6
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 0772678..bf6adce 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -320,3 +320,6 @@
.long sys_getcpu
.long sys_epoll_pwait
.long sys_utimensat /* 320 */
+ .long sys_signalfd
+ .long sys_timerfd
+ .long sys_eventfd
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c
index 92d7d0c..8850fe4 100644
--- a/arch/ia64/ia32/audit.c
+++ b/arch/ia64/ia32/audit.c
@@ -20,6 +20,11 @@
~0U
};
+unsigned ia32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
int ia32_classify_syscall(unsigned syscall)
{
switch(syscall) {
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c
index 0468255..f3802ae 100644
--- a/arch/ia64/kernel/audit.c
+++ b/arch/ia64/kernel/audit.c
@@ -23,6 +23,20 @@
~0U
};
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_IA32_SUPPORT
+ if (arch == AUDIT_ARCH_I386)
+ return 1;
+#endif
+ return 0;
+}
+
int audit_classify_syscall(int abi, unsigned syscall)
{
#ifdef CONFIG_IA32_SUPPORT
@@ -49,15 +63,18 @@
extern __u32 ia32_write_class[];
extern __u32 ia32_read_class[];
extern __u32 ia32_chattr_class[];
+ extern __u32 ia32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
#endif
audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0;
}
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 9740d6b..c3bb8a75 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -241,6 +241,10 @@
bool
default y
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+ bool
+ default y
+
config PREEMPT
bool "Preemptible Kernel"
help
diff --git a/arch/m32r/mm/mmu.S b/arch/m32r/mm/mmu.S
index 8bb74b1..49a6d16 100644
--- a/arch/m32r/mm/mmu.S
+++ b/arch/m32r/mm/mmu.S
@@ -163,7 +163,8 @@
; pte_data = (unsigned long)pte_val(*pte);
ld r2, @r3 ; r2: pte data
- or3 r2, r2, #2 ; _PAGE_PRESENT(=2)
+ and3 r3, r2, #2 ; _PAGE_PRESENT(=2) check
+ beqz r3, 3f
.fillinsn
5:
@@ -264,11 +265,8 @@
;
and3 r1, r1, #0xeff
ldi r4, #611 ; _KERNPG_TABLE(=611)
- beq r1, r4, 4f ; !pmd_bad(*pmd) ?
- .fillinsn
-3:
- ldi r1, #0 ; r1: pte_data = 0
- bra 5f
+ bne r1, r4, 3f ; !pmd_bad(*pmd) ?
+
.fillinsn
4:
; pte = pte_offset(pmd, address);
@@ -282,8 +280,10 @@
add r4, r3 ; r4: pte
; pte_data = (unsigned long)pte_val(*pte);
ld r1, @r4 ; r1: pte_data
- .fillinsn
+ and3 r3, r1, #2 ; _PAGE_PRESENT(=2) check
+ beqz r3, 3f
+ .fillinsn
;; set tlb
; r0: address, r1: pte_data, r2: entry
; r3,r4: (free)
@@ -295,8 +295,7 @@
and3 r4, r4, #(MMU_CONTEXT_ASID_MASK)
or r3, r4
st r3, @r2
- or3 r4, r1, #2 ; _PAGE_PRESENT(=2)
- st r4, @(4,r2) ; set_tlb_data(entry, pte_data);
+ st r1, @(4,r2) ; set_tlb_data(entry, pte_data);
ld r4, @sp+
ld r3, @sp+
@@ -306,6 +305,11 @@
ld sp, @sp+
rte
+ .fillinsn
+3:
+ ldi r1, #2 ; r1: pte_data = 0 | _PAGE_PRESENT(=2)
+ bra 5b
+
#else
#error unknown isa configuration
#endif
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 16ecea3..0f09412 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -15,121 +15,8 @@
prompt "System type"
default SGI_IP22
-config MIPS_MTX1
- bool "4G Systems MTX-1 board"
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select RESOURCES_64BIT if PCI
- select SOC_AU1500
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_BOSPORUS
- bool "AMD Alchemy Bosporus board"
- select SOC_AU1500
- select DMA_NONCOHERENT
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1000
- bool "AMD Alchemy PB1000 board"
- select SOC_AU1000
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select RESOURCES_64BIT if PCI
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1100
- bool "AMD Alchemy PB1100 board"
- select SOC_AU1100
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select RESOURCES_64BIT if PCI
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1500
- bool "AMD Alchemy PB1500 board"
- select SOC_AU1500
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select RESOURCES_64BIT if PCI
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1550
- bool "AMD Alchemy PB1550 board"
- select SOC_AU1550
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select MIPS_DISABLE_OBSOLETE_IDE
- select RESOURCES_64BIT if PCI
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1200
- bool "AMD Alchemy PB1200 board"
- select SOC_AU1200
- select DMA_NONCOHERENT
- select MIPS_DISABLE_OBSOLETE_IDE
- select RESOURCES_64BIT if PCI
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1000
- bool "AMD Alchemy DB1000 board"
- select SOC_AU1000
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select RESOURCES_64BIT if PCI
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1100
- bool "AMD Alchemy DB1100 board"
- select SOC_AU1100
- select DMA_NONCOHERENT
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1500
- bool "AMD Alchemy DB1500 board"
- select SOC_AU1500
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select MIPS_DISABLE_OBSOLETE_IDE
- select RESOURCES_64BIT if PCI
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1550
- bool "AMD Alchemy DB1550 board"
- select SOC_AU1550
- select HW_HAS_PCI
- select DMA_NONCOHERENT
- select MIPS_DISABLE_OBSOLETE_IDE
- select RESOURCES_64BIT if PCI
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1200
- bool "AMD Alchemy DB1200 board"
- select SOC_AU1200
- select DMA_COHERENT
- select MIPS_DISABLE_OBSOLETE_IDE
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_MIRAGE
- bool "AMD Alchemy Mirage board"
- select DMA_NONCOHERENT
- select SOC_AU1500
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_LITTLE_ENDIAN
+config MACH_ALCHEMY
+ bool "Alchemy processor based machines"
config BASLER_EXCITE
bool "Basler eXcite smart camera"
@@ -369,28 +256,6 @@
This option enables support for MIPS Technologies MIPSsim software
emulator.
-config MOMENCO_JAGUAR_ATX
- bool "Momentum Jaguar board"
- select BOOT_ELF32
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
- select IRQ_CPU_RM7K
- select IRQ_MV64340
- select LIMITED_DMA
- select PCI_MARVELL
- select RM7000_CPU_SCACHE
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_RM9000
- select SYS_HAS_EARLY_PRINTK
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_KGDB
- help
- The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
- Momentum Computer <http://www.momenco.com/>.
-
config MOMENCO_OCELOT
bool "Momentum Ocelot board"
select DMA_NONCOHERENT
@@ -446,29 +311,6 @@
The Ocelot is a MIPS-based Single Board Computer (SBC) made by
Momentum Computer <http://www.momenco.com/>.
-config MOMENCO_OCELOT_G
- bool "Momentum Ocelot-G board"
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
- select IRQ_CPU_RM7K
- select PCI_MARVELL
- select RM7000_CPU_SCACHE
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_RM7000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
- select SYS_SUPPORTS_BIG_ENDIAN
- help
- The Ocelot is a MIPS-based Single Board Computer (SBC) made by
- Momentum Computer <http://www.momenco.com/>.
-
-config MIPS_XXS1500
- bool "MyCable XXS1500 board"
- select DMA_NONCOHERENT
- select SOC_AU1500
- select SYS_SUPPORTS_LITTLE_ENDIAN
-
config PNX8550_JBS
bool "Philips PNX8550 based JBS board"
select PNX8550
@@ -775,7 +617,6 @@
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
- select TOSHIBA_BOARDS
select GENERIC_HARDIRQS_NO__DO_IRQ
config TOSHIBA_RBTX4927
@@ -791,7 +632,6 @@
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_KGDB
- select TOSHIBA_BOARDS
select GENERIC_HARDIRQS_NO__DO_IRQ
help
This Toshiba board is based on the TX4927 processor. Say Y here to
@@ -811,7 +651,6 @@
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_KGDB
- select TOSHIBA_BOARDS
select GENERIC_HARDIRQS_NO__DO_IRQ
help
This Toshiba board is based on the TX4938 processor. Say Y here to
@@ -819,11 +658,11 @@
endchoice
+source "arch/mips/au1000/Kconfig"
source "arch/mips/ddb5xxx/Kconfig"
source "arch/mips/gt64120/ev64120/Kconfig"
source "arch/mips/jazz/Kconfig"
source "arch/mips/lasat/Kconfig"
-source "arch/mips/momentum/Kconfig"
source "arch/mips/pmc-sierra/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
@@ -923,11 +762,6 @@
config I8259
bool
-config LIMITED_DMA
- bool
- select HIGHMEM
- select SYS_SUPPORTS_HIGHMEM
-
config MIPS_BONITO64
bool
@@ -1013,33 +847,6 @@
config PCI_MARVELL
bool
-config SOC_AU1000
- bool
- select SOC_AU1X00
-
-config SOC_AU1100
- bool
- select SOC_AU1X00
-
-config SOC_AU1500
- bool
- select SOC_AU1X00
-
-config SOC_AU1550
- bool
- select SOC_AU1X00
-
-config SOC_AU1200
- bool
- select SOC_AU1X00
-
-config SOC_AU1X00
- bool
- select SYS_HAS_CPU_MIPS32_R1
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_APM_EMULATION
- select SYS_SUPPORTS_KGDB
-
config SERIAL_RM9000
bool
@@ -1081,9 +888,9 @@
choice
prompt "Galileo Chip Clock"
#default SYSCLK_83 if MIPS_EV64120
- depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+ depends on MIPS_EV64120 || MOMENCO_OCELOT
default SYSCLK_83 if MIPS_EV64120
- default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G
+ default SYSCLK_100 if MOMENCO_OCELOT
config SYSCLK_75
bool "75" if MIPS_EV64120
@@ -1092,7 +899,7 @@
bool "83.3" if MIPS_EV64120
config SYSCLK_100
- bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+ bool "100" if MIPS_EV64120 || MOMENCO_OCELOT
endchoice
@@ -1131,9 +938,6 @@
config BOOT_ELF64
bool
-config TOSHIBA_BOARDS
- bool
-
menu "CPU selection"
choice
@@ -1557,6 +1361,7 @@
bool "Use 1 TC on each available VPE for SMP"
depends on SYS_SUPPORTS_MULTITHREADING
select CPU_MIPSR2_IRQ_VI
+ select CPU_MIPSR2_IRQ_EI
select CPU_MIPSR2_SRS
select MIPS_MT
select NR_CPUS_DEFAULT_2
@@ -1572,6 +1377,7 @@
#depends on CPU_MIPS64_R2 # once there is hardware ...
depends on SYS_SUPPORTS_MULTITHREADING
select CPU_MIPSR2_IRQ_VI
+ select CPU_MIPSR2_IRQ_EI
select CPU_MIPSR2_SRS
select MIPS_MT
select NR_CPUS_DEFAULT_8
@@ -1584,6 +1390,8 @@
config MIPS_VPE_LOADER
bool "VPE loader support."
depends on SYS_SUPPORTS_MULTITHREADING
+ select CPU_MIPSR2_IRQ_VI
+ select CPU_MIPSR2_IRQ_EI
select MIPS_MT
help
Includes a loader for loading an elf relocatable object
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 4892db8..f450066 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -343,15 +343,6 @@
load-$(CONFIG_MOMENCO_OCELOT) += 0xffffffff80100000
#
-# Momentum Ocelot-G board
-#
-# The Ocelot-G setup.o must be linked early - it does the ioremap() for the
-# mips_io_port_base.
-#
-core-$(CONFIG_MOMENCO_OCELOT_G) += arch/mips/momentum/ocelot_g/
-load-$(CONFIG_MOMENCO_OCELOT_G) += 0xffffffff80100000
-
-#
# Momentum Ocelot-C and -CS boards
#
# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the
@@ -388,17 +379,6 @@
load-$(CONFIG_BASLER_EXCITE) += 0x80100000
#
-# Momentum Jaguar ATX
-#
-core-$(CONFIG_MOMENCO_JAGUAR_ATX) += arch/mips/momentum/jaguar_atx/
-cflags-$(CONFIG_MOMENCO_JAGUAR_ATX) += -Iinclude/asm-mips/mach-ja
-#ifdef CONFIG_JAGUAR_DMALOW
-#load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff88000000
-#else
-load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0xffffffff80100000
-#endif
-
-#
# NEC DDB
#
core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/
@@ -729,3 +709,25 @@
CLEAN_FILES += vmlinux.32 \
vmlinux.64 \
vmlinux.ecoff
+
+quiet_cmd_syscalls_n32 = CALL-N32 $<
+ cmd_syscalls_n32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=n32
+
+quiet_cmd_syscalls_o32 = CALL-O32 $<
+ cmd_syscalls_o32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=32
+
+PHONY += missing-syscalls-n32 missing-syscalls-o32
+
+missing-syscalls-n32: scripts/checksyscalls.sh FORCE
+ $(call cmd,syscalls_n32)
+
+missing-syscalls-o32: scripts/checksyscalls.sh FORCE
+ $(call cmd,syscalls_o32)
+
+archprepare:
+ifdef CONFIG_MIPS32_N32
+ $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-n32
+endif
+ifdef CONFIG_MIPS32_O32
+ $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-o32
+endif
diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig
new file mode 100644
index 0000000..abea880
--- /dev/null
+++ b/arch/mips/au1000/Kconfig
@@ -0,0 +1,142 @@
+choice
+ prompt "Machine type"
+ depends on MACH_ALCHEMY
+ default MIPS_DB1000
+
+config MIPS_MTX1
+ bool "4G Systems MTX-1 board"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select RESOURCES_64BIT if PCI
+ select SOC_AU1500
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_BOSPORUS
+ bool "Alchemy Bosporus board"
+ select SOC_AU1500
+ select DMA_NONCOHERENT
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1000
+ bool "Alchemy DB1000 board"
+ select SOC_AU1000
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select RESOURCES_64BIT if PCI
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1100
+ bool "Alchemy DB1100 board"
+ select SOC_AU1100
+ select DMA_NONCOHERENT
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1200
+ bool "Alchemy DB1200 board"
+ select SOC_AU1200
+ select DMA_COHERENT
+ select MIPS_DISABLE_OBSOLETE_IDE
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1500
+ bool "Alchemy DB1500 board"
+ select SOC_AU1500
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select MIPS_DISABLE_OBSOLETE_IDE
+ select RESOURCES_64BIT if PCI
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1550
+ bool "Alchemy DB1550 board"
+ select SOC_AU1550
+ select HW_HAS_PCI
+ select DMA_NONCOHERENT
+ select MIPS_DISABLE_OBSOLETE_IDE
+ select RESOURCES_64BIT if PCI
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_MIRAGE
+ bool "Alchemy Mirage board"
+ select DMA_NONCOHERENT
+ select SOC_AU1500
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1000
+ bool "Alchemy PB1000 board"
+ select SOC_AU1000
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select RESOURCES_64BIT if PCI
+ select SWAP_IO_SPACE
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1100
+ bool "Alchemy PB1100 board"
+ select SOC_AU1100
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select RESOURCES_64BIT if PCI
+ select SWAP_IO_SPACE
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1200
+ bool "Alchemy PB1200 board"
+ select SOC_AU1200
+ select DMA_NONCOHERENT
+ select MIPS_DISABLE_OBSOLETE_IDE
+ select RESOURCES_64BIT if PCI
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1500
+ bool "Alchemy PB1500 board"
+ select SOC_AU1500
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select RESOURCES_64BIT if PCI
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1550
+ bool "Alchemy PB1550 board"
+ select SOC_AU1550
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select MIPS_DISABLE_OBSOLETE_IDE
+ select RESOURCES_64BIT if PCI
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_XXS1500
+ bool "MyCable XXS1500 board"
+ select DMA_NONCOHERENT
+ select SOC_AU1500
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+
+endchoice
+
+config SOC_AU1000
+ bool
+ select SOC_AU1X00
+
+config SOC_AU1100
+ bool
+ select SOC_AU1X00
+
+config SOC_AU1500
+ bool
+ select SOC_AU1X00
+
+config SOC_AU1550
+ bool
+ select SOC_AU1X00
+
+config SOC_AU1200
+ bool
+ select SOC_AU1X00
+
+config SOC_AU1X00
+ bool
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_APM_EMULATION
+ select SYS_SUPPORTS_KGDB
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
index cc1ce77..e00bc2d 100644
--- a/arch/mips/basler/excite/excite_device.c
+++ b/arch/mips/basler/excite/excite_device.c
@@ -68,7 +68,7 @@
static struct resource
- excite_ctr_resource __attribute__((unused)) = {
+ excite_ctr_resource __maybe_unused = {
.name = "GPI counters",
.start = 0,
.end = 5,
@@ -77,7 +77,7 @@
.sibling = NULL,
.child = NULL
},
- excite_gpislice_resource __attribute__((unused)) = {
+ excite_gpislice_resource __maybe_unused = {
.name = "GPI slices",
.start = 0,
.end = 1,
@@ -86,7 +86,7 @@
.sibling = NULL,
.child = NULL
},
- excite_mdio_channel_resource __attribute__((unused)) = {
+ excite_mdio_channel_resource __maybe_unused = {
.name = "MDIO channels",
.start = 0,
.end = 1,
@@ -95,7 +95,7 @@
.sibling = NULL,
.child = NULL
},
- excite_fifomem_resource __attribute__((unused)) = {
+ excite_fifomem_resource __maybe_unused = {
.name = "FIFO memory",
.start = 0,
.end = 767,
@@ -104,7 +104,7 @@
.sibling = NULL,
.child = NULL
},
- excite_scram_resource __attribute__((unused)) = {
+ excite_scram_resource __maybe_unused = {
.name = "Scratch RAM",
.start = EXCITE_PHYS_SCRAM,
.end = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
@@ -113,7 +113,7 @@
.sibling = NULL,
.child = NULL
},
- excite_fpga_resource __attribute__((unused)) = {
+ excite_fpga_resource __maybe_unused = {
.name = "System FPGA",
.start = EXCITE_PHYS_FPGA,
.end = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
@@ -122,7 +122,7 @@
.sibling = NULL,
.child = NULL
},
- excite_nand_resource __attribute__((unused)) = {
+ excite_nand_resource __maybe_unused = {
.name = "NAND flash control",
.start = EXCITE_PHYS_NAND,
.end = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
@@ -131,7 +131,7 @@
.sibling = NULL,
.child = NULL
},
- excite_titan_resource __attribute__((unused)) = {
+ excite_titan_resource __maybe_unused = {
.name = "TITAN registers",
.start = EXCITE_PHYS_TITAN,
.end = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 9565b21..c292f80 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
# Makefile for the Cobalt micro systems family specific parts of the kernel
#
-obj-y := irq.o reset.o setup.o buttons.o
+obj-y := buttons.o irq.o reset.o rtc.o serial.o setup.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_EARLY_PRINTK) += console.o
diff --git a/arch/mips/cobalt/rtc.c b/arch/mips/cobalt/rtc.c
new file mode 100644
index 0000000..284daef
--- /dev/null
+++ b/arch/mips/cobalt/rtc.c
@@ -0,0 +1,63 @@
+/*
+ * Registration of Cobalt RTC platform device.
+ *
+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+static struct resource cobalt_rtc_resource[] __initdata = {
+ {
+ .start = 0x70,
+ .end = 0x77,
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static __init int cobalt_rtc_add(void)
+{
+ struct platform_device *pdev;
+ int retval;
+
+ pdev = platform_device_alloc("rtc_cmos", -1);
+ if (!pdev)
+ return -ENOMEM;
+
+ retval = platform_device_add_resources(pdev, cobalt_rtc_resource,
+ ARRAY_SIZE(cobalt_rtc_resource));
+ if (retval)
+ goto err_free_device;
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto err_free_device;
+
+ return 0;
+
+err_free_device:
+ platform_device_put(pdev);
+
+ return retval;
+}
+device_initcall(cobalt_rtc_add);
diff --git a/arch/mips/cobalt/serial.c b/arch/mips/cobalt/serial.c
new file mode 100644
index 0000000..c271165
--- /dev/null
+++ b/arch/mips/cobalt/serial.c
@@ -0,0 +1,85 @@
+/*
+ * Registration of Cobalt UART platform device.
+ *
+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <cobalt.h>
+
+static struct resource cobalt_uart_resource[] __initdata = {
+ {
+ .start = 0x1c800000,
+ .end = 0x1c800007,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = COBALT_SERIAL_IRQ,
+ .end = COBALT_SERIAL_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct plat_serial8250_port cobalt_serial8250_port[] = {
+ {
+ .irq = COBALT_SERIAL_IRQ,
+ .uartclk = 18432000,
+ .iotype = UPIO_MEM,
+ .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .mapbase = 0x1c800000,
+ },
+ {},
+};
+
+static __init int cobalt_uart_add(void)
+{
+ struct platform_device *pdev;
+ int retval;
+
+ /*
+ * Cobalt Qube1 and RAQ1 have no UART.
+ */
+ if (cobalt_board_id <= COBALT_BRD_ID_RAQ1)
+ return 0;
+
+ pdev = platform_device_alloc("serial8250", -1);
+ if (!pdev)
+ return -ENOMEM;
+
+ pdev->id = PLAT8250_DEV_PLATFORM;
+ pdev->dev.platform_data = cobalt_serial8250_port;
+
+ retval = platform_device_add_resources(pdev, cobalt_uart_resource, ARRAY_SIZE(cobalt_uart_resource));
+ if (retval)
+ goto err_free_device;
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto err_free_device;
+
+ return 0;
+
+err_free_device:
+ platform_device_put(pdev);
+
+ return retval;
+}
+device_initcall(cobalt_uart_add);
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index d0dd817..7abe45e 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -10,11 +10,8 @@
*
*/
#include <linux/interrupt.h>
-#include <linux/pci.h>
#include <linux/init.h>
#include <linux/pm.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
@@ -27,9 +24,6 @@
extern void cobalt_machine_restart(char *command);
extern void cobalt_machine_halt(void);
extern void cobalt_machine_power_off(void);
-extern void cobalt_early_console(void);
-
-int cobalt_board_id;
const char *get_system_type(void)
{
@@ -95,8 +89,6 @@
void __init plat_mem_setup(void)
{
- static struct uart_port uart;
- unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
int i;
_machine_restart = cobalt_machine_restart;
@@ -111,29 +103,6 @@
/* These resources have been reserved by VIA SuperI/O chip. */
for (i = 0; i < ARRAY_SIZE(cobalt_reserved_resources); i++)
request_resource(&ioport_resource, cobalt_reserved_resources + i);
-
- /* Read the cobalt id register out of the PCI config space */
- PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
- cobalt_board_id = GT_READ(GT_PCI0_CFGDATA_OFS);
- cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
- cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
-
- printk("Cobalt board ID: %d\n", cobalt_board_id);
-
- if (cobalt_board_id > COBALT_BRD_ID_RAQ1) {
-#ifdef CONFIG_SERIAL_8250
- uart.line = 0;
- uart.type = PORT_UNKNOWN;
- uart.uartclk = 18432000;
- uart.irq = COBALT_SERIAL_IRQ;
- uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF |
- UPF_SKIP_TEST;
- uart.iotype = UPIO_MEM;
- uart.mapbase = 0x1c800000;
-
- early_serial_setup(&uart);
-#endif
- }
}
/*
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index ba593b5..631b213 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:24 2007
+# Linux kernel version: 2.6.21-rc7
+# Wed Apr 18 14:25:45 2007
#
CONFIG_MIPS=y
@@ -62,7 +62,6 @@
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_EARLY_PRINTK=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -74,12 +73,14 @@
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
CONFIG_I8259=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_IRQ_CPU=y
-CONFIG_MIPS_GT64111=y
+CONFIG_PCI_GT64XXX_PCI0=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
#
@@ -179,6 +180,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -477,7 +479,6 @@
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CDROM_PKTCDVD=y
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -518,7 +519,7 @@
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
@@ -546,7 +547,6 @@
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -779,7 +779,8 @@
#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
CONFIG_COBALT_LCD=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
@@ -815,6 +816,11 @@
# CONFIG_HWMON_VID is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -827,7 +833,7 @@
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
# CONFIG_FB is not set
#
@@ -835,7 +841,6 @@
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -894,7 +899,29 @@
#
# Real Time Clock
#
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
# DMA Engine support
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 0db6a8b..10f6af4 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 162add9..4b08629 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 82801ec..820659e 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 545f230..4050b9b 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 5bd3b43..7b35190 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
deleted file mode 100644
index 083104d..0000000
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ /dev/null
@@ -1,897 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:33 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-CONFIG_MOMENCO_JAGUAR_ATX=y
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_JAGUAR_DMALOW=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_LIMITED_DMA=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_HIGHMEM=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_SYS_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_IPV6_SIT=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_MV643XX_ETH=y
-CONFIG_QLA3XXX=m
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-CONFIG_SYS_SUPPORTS_KGDB=y
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=m
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 068e48e..1b364cf 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -80,7 +80,6 @@
CONFIG_MIPS_TX3927=y
CONFIG_SWAP_IO_SPACE=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
-CONFIG_TOSHIBA_BOARDS=y
#
# CPU selection
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 69678d9..37d696c 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 0706727..b11f0e8 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 354e49b..2927f38 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -9,6 +9,7 @@
# Machine selection
#
CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/rbhma4200_defconfig
similarity index 73%
rename from arch/mips/configs/ocelot_g_defconfig
rename to arch/mips/configs/rbhma4200_defconfig
index 7078e6b..35d6426 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/rbhma4200_defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:36 2007
+# Linux kernel version: 2.6.21
+# Wed May 9 23:44:19 2007
#
CONFIG_MIPS=y
#
# Machine selection
#
-CONFIG_ZONE_DMA=y
# CONFIG_MIPS_MTX1 is not set
# CONFIG_MIPS_BOSPORUS is not set
# CONFIG_MIPS_PB1000 is not set
@@ -33,11 +32,9 @@
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
# CONFIG_MOMENCO_OCELOT_3 is not set
# CONFIG_MOMENCO_OCELOT_C is not set
-CONFIG_MOMENCO_OCELOT_G=y
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
@@ -60,8 +57,9 @@
# CONFIG_SIBYTE_CRHONE is not set
# CONFIG_SNI_RM is not set
# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_TOSHIBA_RBTX4927=y
# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_TOSHIBA_FPCIB0 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -70,19 +68,15 @@
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_I8259=y
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_PCI_MARVELL=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_SWAP_IO_SPACE=y
-# CONFIG_SYSCLK_75 is not set
-# CONFIG_SYSCLK_83 is not set
-CONFIG_SYSCLK_100=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
#
@@ -97,18 +91,19 @@
# CONFIG_CPU_VR41XX is not set
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_TX49XX=y
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
+# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_SYS_HAS_CPU_TX49XX=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
@@ -121,19 +116,15 @@
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
@@ -143,17 +134,17 @@
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
@@ -183,34 +174,42 @@
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
+# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
#
# Block layer
@@ -218,7 +217,7 @@
CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
-CONFIG_LSF=y
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -238,17 +237,12 @@
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_MMU=y
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
@@ -260,10 +254,7 @@
#
# Power management options
#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
#
# Networking
@@ -273,25 +264,21 @@
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_DHCP is not set
# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
@@ -299,19 +286,19 @@
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
@@ -352,13 +339,16 @@
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -369,18 +359,12 @@
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
+# CONFIG_CONNECTOR is not set
# CONFIG_MTD is not set
#
@@ -401,21 +385,24 @@
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-CONFIG_SGI_IOC4=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -425,7 +412,7 @@
#
# SCSI device support
#
-CONFIG_RAID_ATTRS=y
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
@@ -471,27 +458,13 @@
#
# PHY device support
#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_GALILEO_64240_ETH=y
+# CONFIG_MII is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
@@ -503,6 +476,7 @@
#
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
+CONFIG_NE2000=y
# CONFIG_NET_PCI is not set
#
@@ -521,18 +495,18 @@
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=y
+# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -540,9 +514,10 @@
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
# Wan interfaces
@@ -570,29 +545,7 @@
#
# Input device support
#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
@@ -601,34 +554,31 @@
# CONFIG_SERIO_I8042 is not set
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
# Serial drivers
#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_TXX9=y
+CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_NR_UARTS=6
+CONFIG_SERIAL_TXX9_CONSOLE=y
+CONFIG_SERIAL_TXX9_STDSERIAL=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
@@ -656,10 +606,7 @@
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -672,12 +619,12 @@
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
@@ -692,15 +639,14 @@
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Console display driver support
+# Display device support
#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
#
# Sound
@@ -708,11 +654,6 @@
# CONFIG_SOUND is not set
#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -728,10 +669,6 @@
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -759,7 +696,40 @@
#
# Real Time Clock
#
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+CONFIG_RTC_DRV_DS1742=y
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
#
# DMA Engine support
@@ -785,9 +755,7 @@
#
# File systems
#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
# CONFIG_REISERFS_FS is not set
@@ -801,10 +769,10 @@
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+# CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
#
@@ -824,21 +792,20 @@
# Pseudo filesystems
#
CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
+# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=y
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -855,17 +822,17 @@
# Network File Systems
#
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
+CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -889,10 +856,7 @@
#
# Distributed Lock Manager
#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
#
# Profiling support
@@ -910,72 +874,29 @@
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+# CONFIG_LIBCRC32C is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 7d0f217..41011f7 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -89,7 +89,6 @@
CONFIG_SWAP_IO_SPACE=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
CONFIG_HAVE_STD_PC_SERIAL_PORT=y
-CONFIG_TOSHIBA_BOARDS=y
#
# CPU selection
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0219_defconfig
similarity index 98%
rename from arch/mips/configs/tb0229_defconfig
rename to arch/mips/configs/tb0219_defconfig
index 1756d2b..8b1675c 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:41 2007
+# Linux kernel version: 2.6.21-rc6
+# Sun Apr 15 01:06:01 2007
#
CONFIG_MIPS=y
@@ -66,10 +66,11 @@
# CONFIG_IBM_WORKPAD is not set
# CONFIG_NEC_CMBVR4133 is not set
CONFIG_TANBAC_TB022X=y
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0287 is not set
# CONFIG_VICTOR_MPC30X is not set
# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_TANBAC_TB0219=y
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0287 is not set
CONFIG_PCI_VR41XX=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -184,6 +185,7 @@
# CONFIG_IKCONFIG is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -375,7 +377,7 @@
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
# CONFIG_SYS_HYPERVISOR is not set
#
@@ -415,7 +417,6 @@
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
@@ -646,7 +647,7 @@
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
-CONFIG_TANBAC_TB0219=y
+CONFIG_GPIO_TB0219=y
# CONFIG_DRM is not set
CONFIG_GPIO_VR41XX=y
# CONFIG_RAW_DRIVER is not set
@@ -679,6 +680,11 @@
# CONFIG_HWMON_VID is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -692,7 +698,7 @@
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
# CONFIG_FB is not set
#
@@ -700,7 +706,6 @@
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -831,6 +836,7 @@
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
diff --git a/arch/mips/kernel/early_printk.c b/arch/mips/kernel/early_printk.c
index 4fa54b2..9dccfa4 100644
--- a/arch/mips/kernel/early_printk.c
+++ b/arch/mips/kernel/early_printk.c
@@ -12,7 +12,8 @@
extern void prom_putchar(char);
-static void early_console_write(struct console *con, const char *s, unsigned n)
+static void __init
+early_console_write(struct console *con, const char *s, unsigned n)
{
while (n-- && *s) {
if (*s == '\n')
@@ -22,14 +23,20 @@
}
}
-static struct console early_console = {
+static struct console early_console __initdata = {
.name = "early",
.write = early_console_write,
.flags = CON_PRINTBUFFER | CON_BOOT,
.index = -1
};
+static int early_console_initialized __initdata;
+
void __init setup_early_printk(void)
{
+ if (early_console_initialized)
+ return;
+ early_console_initialized = 1;
+
register_console(&early_console);
}
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 2967537..410868b 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -132,11 +132,11 @@
};
-void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq)
+void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
{
extern void (*board_bind_eic_interrupt)(unsigned int irq, unsigned int regset);
- _icctrl_msc = (unsigned long) ioremap (MIPS_MSC01_IC_REG_BASE, 0x40000);
+ _icctrl_msc = (unsigned long) ioremap (icubase, 0x40000);
/* Reset interrupt controller - initialises all registers to 0 */
MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
@@ -148,14 +148,14 @@
switch (imp->im_type) {
case MSC01_IRQ_EDGE:
- set_irq_chip(base+n, &msc_edgeirq_type);
+ set_irq_chip(irqbase+n, &msc_edgeirq_type);
if (cpu_has_veic)
MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
else
MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
break;
case MSC01_IRQ_LEVEL:
- set_irq_chip(base+n, &msc_levelirq_type);
+ set_irq_chip(irqbase+n, &msc_levelirq_type);
if (cpu_has_veic)
MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
else
@@ -163,7 +163,7 @@
}
}
- irq_base = base;
+ irq_base = irqbase;
MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT); /* Enable interrupt generation */
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 2fe4c86..aeded6c 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -28,7 +28,7 @@
static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
-int __devinit allocate_irqno(void)
+int allocate_irqno(void)
{
int irq;
@@ -59,7 +59,7 @@
BUG_ON(test_and_set_bit(i, irq_map));
}
-void __devinit free_irqno(unsigned int irq)
+void free_irqno(unsigned int irq)
{
smp_mb__before_clear_bit();
clear_bit(irq, irq_map);
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index e5e56bd..751b4a1 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -306,7 +306,7 @@
struct clocksource clocksource_mips = {
.name = "MIPS",
- .mask = 0xffffffff,
+ .mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index ff45a4b..200de02 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -927,9 +927,9 @@
(regs->cp0_cause & 0x7f) >> 2);
}
-asmlinkage void do_default_vi(struct pt_regs *regs)
+static asmlinkage void do_default_vi(void)
{
- show_regs(regs);
+ show_regs(get_irq_regs());
panic("Caught unexpected vectored interrupt.");
}
@@ -1128,7 +1128,7 @@
clear_bit(set, &sr->sr_allocated);
}
-static void *set_vi_srs_handler(int n, void *addr, int srs)
+static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
{
unsigned long handler;
unsigned long old_handler = vi_handlers[n];
@@ -1217,7 +1217,7 @@
return (void *)old_handler;
}
-void *set_vi_handler(int n, void *addr)
+void *set_vi_handler(int n, vi_handler_t addr)
{
return set_vi_srs_handler(n, addr, 0);
}
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index d7d3b14..5dad13e 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -9,4 +9,4 @@
obj-$(CONFIG_PCI) += iomap-pci.o
# libgcc-style stuff needed in the kernel
-lib-y += ashldi3.o ashrdi3.o lshrdi3.o
+lib-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
new file mode 100644
index 0000000..e9ff258
--- /dev/null
+++ b/arch/mips/lib/ucmpdi2.c
@@ -0,0 +1,19 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+word_type __ucmpdi2 (unsigned long a, unsigned long b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+ return 0;
+ else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+ return 2;
+ if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+ return 0;
+ else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+ return 2;
+ return 1;
+}
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 83d7602..1cd830e 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -311,16 +311,21 @@
if (!cpu_has_veic)
mips_cpu_irq_init();
- switch(mips_revision_corid) {
- case MIPS_REVISION_CORID_CORE_MSC:
- case MIPS_REVISION_CORID_CORE_FPGA2:
- case MIPS_REVISION_CORID_CORE_FPGA3:
- case MIPS_REVISION_CORID_CORE_24K:
- case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ switch(mips_revision_sconid) {
+ case MIPS_REVISION_SCON_SOCIT:
+ case MIPS_REVISION_SCON_ROCIT:
if (cpu_has_veic)
- init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
+ init_msc_irqs (MIPS_MSC01_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
else
- init_msc_irqs (MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs);
+ init_msc_irqs (MIPS_MSC01_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs);
+ break;
+
+ case MIPS_REVISION_SCON_SOCITSC:
+ case MIPS_REVISION_SCON_SOCITSCP:
+ if (cpu_has_veic)
+ init_msc_irqs (MIPS_SOCITSC_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
+ else
+ init_msc_irqs (MIPS_SOCITSC_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs);
}
if (cpu_has_veic) {
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 675502a..10dd2af 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -80,7 +80,6 @@
pagefault_enable();
}
-#ifndef CONFIG_LIMITED_DMA
/*
* This is the same as kmap_atomic() but can map memory that doesn't
* have a struct page associated with it.
@@ -99,7 +98,6 @@
return (void*) vaddr;
}
-#endif /* CONFIG_LIMITED_DMA */
struct page *__kmap_atomic_to_page(void *ptr)
{
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 2d1c2c0..4c80528 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -424,9 +424,6 @@
continue;
}
ClearPageReserved(page);
-#ifdef CONFIG_LIMITED_DMA
- set_page_address(page, lowmem_page_address(page));
-#endif
init_page_count(page);
__free_page(page);
totalhigh_pages++;
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 492c518..e714929 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -35,24 +35,24 @@
#include <asm/smp.h>
#include <asm/war.h>
-static __init int __attribute__((unused)) r45k_bvahwbug(void)
+static __init int __maybe_unused r45k_bvahwbug(void)
{
/* XXX: We should probe for the presence of this bug, but we don't. */
return 0;
}
-static __init int __attribute__((unused)) r4k_250MHZhwbug(void)
+static __init int __maybe_unused r4k_250MHZhwbug(void)
{
/* XXX: We should probe for the presence of this bug, but we don't. */
return 0;
}
-static __init int __attribute__((unused)) bcm1250_m3_war(void)
+static __init int __maybe_unused bcm1250_m3_war(void)
{
return BCM1250_M3_WAR;
}
-static __init int __attribute__((unused)) r10000_llsc_war(void)
+static __init int __maybe_unused r10000_llsc_war(void)
{
return R10000_LLSC_WAR;
}
@@ -511,18 +511,18 @@
#define i_ehb(buf) i_sll(buf, 0, 0, 3)
#ifdef CONFIG_64BIT
-static __init int __attribute__((unused)) in_compat_space_p(long addr)
+static __init int __maybe_unused in_compat_space_p(long addr)
{
/* Is this address in 32bit compat space? */
return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
}
-static __init int __attribute__((unused)) rel_highest(long val)
+static __init int __maybe_unused rel_highest(long val)
{
return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000;
}
-static __init int __attribute__((unused)) rel_higher(long val)
+static __init int __maybe_unused rel_higher(long val)
{
return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000;
}
@@ -556,8 +556,8 @@
i_lui(buf, rs, rel_hi(addr));
}
-static __init void __attribute__((unused)) i_LA(u32 **buf, unsigned int rs,
- long addr)
+static __init void __maybe_unused i_LA(u32 **buf, unsigned int rs,
+ long addr)
{
i_LA_mostly(buf, rs, addr);
if (rel_lo(addr))
@@ -636,8 +636,8 @@
move_labels(lab, first, end, off);
}
-static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel,
- u32 *addr)
+static __init int __maybe_unused insn_has_bdelay(struct reloc *rel,
+ u32 *addr)
{
for (; rel->lab != label_invalid; rel++) {
if (rel->addr == addr
@@ -650,15 +650,15 @@
}
/* convenience functions for labeled branches */
-static void __init __attribute__((unused))
+static void __init __maybe_unused
il_bltz(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
{
r_mips_pc16(r, *p, l);
i_bltz(p, reg, 0);
}
-static void __init __attribute__((unused)) il_b(u32 **p, struct reloc **r,
- enum label_id l)
+static void __init __maybe_unused il_b(u32 **p, struct reloc **r,
+ enum label_id l)
{
r_mips_pc16(r, *p, l);
i_b(p, 0);
@@ -671,7 +671,7 @@
i_beqz(p, reg, 0);
}
-static void __init __attribute__((unused))
+static void __init __maybe_unused
il_beqzl(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
{
r_mips_pc16(r, *p, l);
@@ -692,7 +692,7 @@
i_bgezl(p, reg, 0);
}
-static void __init __attribute__((unused))
+static void __init __maybe_unused
il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
{
r_mips_pc16(r, *p, l);
@@ -810,7 +810,7 @@
*
* As if we MIPS hackers wouldn't know how to nop pipelines happy ...
*/
-static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p)
+static __init void __maybe_unused build_tlb_probe_entry(u32 **p)
{
switch (current_cpu_data.cputype) {
/* Found by experiment: R4600 v2.0 needs this, too. */
@@ -1098,7 +1098,7 @@
* TMP and PTR are scratch.
* TMP will be clobbered, PTR will hold the pgd entry.
*/
-static __init void __attribute__((unused))
+static __init void __maybe_unused
build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
{
long pgdc = (long)pgd_current;
diff --git a/arch/mips/momentum/Kconfig b/arch/mips/momentum/Kconfig
deleted file mode 100644
index 70a61cf..0000000
--- a/arch/mips/momentum/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-config JAGUAR_DMALOW
- bool "Low DMA Mode"
- depends on MOMENCO_JAGUAR_ATX
- help
- Select to Y if jump JP5 is set on your board, N otherwise. Normally
- the jumper is set, so if you feel unsafe, just say Y.
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
deleted file mode 100644
index 2e8cebd..0000000
--- a/arch/mips/momentum/jaguar_atx/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for Momentum Computer's Jaguar-ATX board.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-obj-y += irq.o platform.o prom.o reset.o setup.o
-
-obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
-obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/dbg_io.c b/arch/mips/momentum/jaguar_atx/dbg_io.c
deleted file mode 100644
index b85a652..0000000
--- a/arch/mips/momentum/jaguar_atx/dbg_io.c
+++ /dev/null
@@ -1,125 +0,0 @@
-
-#if defined(CONFIG_REMOTE_DEBUG)
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define UART16550_BAUD_2400 2400
-#define UART16550_BAUD_4800 4800
-#define UART16550_BAUD_9600 9600
-#define UART16550_BAUD_19200 19200
-#define UART16550_BAUD_38400 38400
-#define UART16550_BAUD_57600 57600
-#define UART16550_BAUD_115200 115200
-
-#define UART16550_PARITY_NONE 0
-#define UART16550_PARITY_ODD 0x08
-#define UART16550_PARITY_EVEN 0x18
-#define UART16550_PARITY_MARK 0x28
-#define UART16550_PARITY_SPACE 0x38
-
-#define UART16550_DATA_5BIT 0x0
-#define UART16550_DATA_6BIT 0x1
-#define UART16550_DATA_7BIT 0x2
-#define UART16550_DATA_8BIT 0x3
-
-#define UART16550_STOP_1BIT 0x0
-#define UART16550_STOP_2BIT 0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define BASE OCELOT_SERIAL1_BASE
-#define MAX_BAUD OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define REG_OFFSET 4
-
-/* register offset */
-#define OFS_RCV_BUFFER 0
-#define OFS_TRANS_HOLD 0
-#define OFS_SEND_BUFFER 0
-#define OFS_INTR_ENABLE (1*REG_OFFSET)
-#define OFS_INTR_ID (2*REG_OFFSET)
-#define OFS_DATA_FORMAT (3*REG_OFFSET)
-#define OFS_LINE_CONTROL (3*REG_OFFSET)
-#define OFS_MODEM_CONTROL (4*REG_OFFSET)
-#define OFS_RS232_OUTPUT (4*REG_OFFSET)
-#define OFS_LINE_STATUS (5*REG_OFFSET)
-#define OFS_MODEM_STATUS (6*REG_OFFSET)
-#define OFS_RS232_INPUT (6*REG_OFFSET)
-#define OFS_SCRATCH_PAD (7*REG_OFFSET)
-
-#define OFS_DIVISOR_LSB (0*REG_OFFSET)
-#define OFS_DIVISOR_MSB (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
-#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
- /* disable interrupts */
- UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
- /* set up baud rate */
- {
- uint32 divisor;
-
- /* set DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
- /* set divisor */
- divisor = MAX_BAUD / baud;
- UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
- UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
- /* clear DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
- }
-
- /* set data format */
- UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
- return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
- UART16550_WRITE(OFS_SEND_BUFFER, byte);
- return 1;
-}
-
-#endif
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
deleted file mode 100644
index f2b4325..0000000
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2002 Momentum Computer, Inc.
- * Author: Matthew Dharm, mdharm@momenco.com
- *
- * Based on work by:
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2000, 01, 06 Ralf Baechle (ralf@linux-mips.org)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/time.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status();
-
- if (pending & STATUSF_IP0)
- do_IRQ(0);
- else if (pending & STATUSF_IP1)
- do_IRQ(1);
- else if (pending & STATUSF_IP2)
- do_IRQ(2);
- else if (pending & STATUSF_IP3)
- do_IRQ(3);
- else if (pending & STATUSF_IP4)
- do_IRQ(4);
- else if (pending & STATUSF_IP5)
- do_IRQ(5);
- else if (pending & STATUSF_IP6)
- do_IRQ(6);
- else if (pending & STATUSF_IP7)
- ll_timer_interrupt(7);
- else {
- /*
- * Now look at the extended interrupts
- */
- pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
- if (pending & STATUSF_IP8)
- ll_mv64340_irq();
- }
-}
-
-static struct irqaction cascade_mv64340 = {
- no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
-};
-
-void __init arch_init_irq(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- * int-handler is not on bootstrap
- */
- clear_c0_status(ST0_IM);
-
- mips_cpu_irq_init();
- rm7k_cpu_irq_init();
-
- /* set up the cascading interrupts */
- setup_irq(8, &cascade_mv64340);
-
- mv64340_irq_init(16);
-
- set_c0_status(ST0_IM);
-}
diff --git a/arch/mips/momentum/jaguar_atx/ja-console.c b/arch/mips/momentum/jaguar_atx/ja-console.c
deleted file mode 100644
index 2c30b4f..0000000
--- a/arch/mips/momentum/jaguar_atx/ja-console.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001, 2002, 2004 Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/termios.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <asm/serial.h>
-
-/* SUPERIO uart register map */
-struct ja_uartregs {
- union {
- volatile u8 pad0[3];
- volatile u8 rbr; /* read only, DLAB == 0 */
- volatile u8 pad1[3];
- volatile u8 thr; /* write only, DLAB == 0 */
- volatile u8 pad2[3];
- volatile u8 dll; /* DLAB == 1 */
- } u1;
- union {
- volatile u8 pad0[3];
- volatile u8 ier; /* DLAB == 0 */
- volatile u8 pad1[3];
- volatile u8 dlm; /* DLAB == 1 */
- } u2;
- union {
- volatile u8 pad0[3];
- volatile u8 iir; /* read only */
- volatile u8 pad1[3];
- volatile u8 fcr; /* write only */
- } u3;
- volatile u8 pad0[3];
- volatile u8 iu_lcr;
- volatile u8 pad1[3];
- volatile u8 iu_mcr;
- volatile u8 pad2[3];
- volatile u8 iu_lsr;
- volatile u8 pad3[3];
- volatile u8 iu_msr;
- volatile u8 pad4[3];
- volatile u8 iu_scr;
-} ja_uregs_t;
-
-#define iu_rbr u1.rbr
-#define iu_thr u1.thr
-#define iu_dll u1.dll
-#define iu_ier u2.ier
-#define iu_dlm u2.dlm
-#define iu_iir u3.iir
-#define iu_fcr u3.fcr
-
-extern unsigned long uart_base;
-
-static inline struct ja_uartregs *console_uart(void)
-{
- return (struct ja_uartregs *) (uart_base + 0x23UL);
-}
-
-void prom_putchar(char c)
-{
- struct ja_uartregs *uart = console_uart();
-
- while ((uart->iu_lsr & 0x20) == 0);
- uart->iu_thr = c;
-}
-
-static void inline ja_console_probe(void)
-{
- struct uart_port up;
-
- /*
- * Register to interrupt zero because we share the interrupt with
- * the serial driver which we don't properly support yet.
- */
- memset(&up, 0, sizeof(up));
- up.membase = (unsigned char *) uart_base + 0x23UL;
- up.irq = JAGUAR_ATX_SERIAL1_IRQ;
- up.uartclk = JAGUAR_ATX_UART_CLK;
- up.regshift = 2;
- up.iotype = UPIO_MEM;
- up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
- up.line = 0;
-
- if (early_serial_setup(&up))
- printk(KERN_ERR "Early serial init of port 0 failed\n");
-}
-
-__init void ja_setup_console(void)
-{
- ja_console_probe();
-}
diff --git a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
deleted file mode 100644
index 022f697..0000000
--- a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Jaguar-ATX Board Register Definitions
- *
- * (C) 2002 Momentum Computer 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; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __JAGUAR_ATX_FPGA_H__
-#define __JAGUAR_ATX_FPGA_H__
-
-#define JAGUAR_ATX_REG_BOARDREV 0x0
-#define JAGUAR_ATX_REG_FPGA_REV 0x1
-#define JAGUAR_ATX_REG_FPGA_TYPE 0x2
-#define JAGUAR_ATX_REG_RESET_STATUS 0x3
-#define JAGUAR_ATX_REG_BOARD_STATUS 0x4
-#define JAGUAR_ATX_REG_RESERVED1 0x5
-#define JAGUAR_ATX_REG_SET 0x6
-#define JAGUAR_ATX_REG_CLR 0x7
-#define JAGUAR_ATX_REG_EEPROM_MODE 0x9
-#define JAGUAR_ATX_REG_RESERVED2 0xa
-#define JAGUAR_ATX_REG_RESERVED3 0xb
-#define JAGUAR_ATX_REG_RESERVED4 0xc
-#define JAGUAR_ATX_REG_PHY_INTSTAT 0xd
-#define JAGUAR_ATX_REG_RESERVED5 0xe
-#define JAGUAR_ATX_REG_RESERVED6 0xf
-
-#define JAGUAR_ATX_CS0_ADDR 0xfc000000L
-
-extern unsigned long ja_fpga_base;
-
-#define __FPGA_REG_TO_ADDR(reg) \
- ((void *) ja_fpga_base + JAGUAR_ATX_REG_##reg)
-#define JAGUAR_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define JAGUAR_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
diff --git a/arch/mips/momentum/jaguar_atx/platform.c b/arch/mips/momentum/jaguar_atx/platform.c
deleted file mode 100644
index 5618448..0000000
--- a/arch/mips/momentum/jaguar_atx/platform.c
+++ /dev/null
@@ -1,208 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "jaguar_atx_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
- [0] = {
- .name = "ethernet shared base",
- .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
- .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
- MV643XX_ETH_SHARED_REGS_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
- .name = MV643XX_ETH_SHARED_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
- .resource = mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE 0xfe000000UL
-#define MV_SRAM_SIZE (256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-#define MV64x60_IRQ_ETH_2 50
-
-static struct resource mv64x60_eth0_resources[] = {
- [0] = {
- .name = "eth0 irq",
- .start = MV64x60_IRQ_ETH_0,
- .end = MV64x60_IRQ_ETH_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
- .port_number = 0,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH0,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
- .name = MV643XX_ETH_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv64x60_eth0_resources),
- .resource = mv64x60_eth0_resources,
- .dev = {
- .platform_data = ð0_pd,
- },
-};
-
-static struct resource mv64x60_eth1_resources[] = {
- [0] = {
- .name = "eth1 irq",
- .start = MV64x60_IRQ_ETH_1,
- .end = MV64x60_IRQ_ETH_1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
- .port_number = 1,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH1,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
- .name = MV643XX_ETH_NAME,
- .id = 1,
- .num_resources = ARRAY_SIZE(mv64x60_eth1_resources),
- .resource = mv64x60_eth1_resources,
- .dev = {
- .platform_data = ð1_pd,
- },
-};
-
-static struct resource mv64x60_eth2_resources[] = {
- [0] = {
- .name = "eth2 irq",
- .start = MV64x60_IRQ_ETH_2,
- .end = MV64x60_IRQ_ETH_2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth2_pd = {
- .port_number = 2,
-};
-
-static struct platform_device eth2_device = {
- .name = MV643XX_ETH_NAME,
- .id = 2,
- .num_resources = ARRAY_SIZE(mv64x60_eth2_resources),
- .resource = mv64x60_eth2_resources,
- .dev = {
- .platform_data = ð2_pd,
- },
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
- &mv643xx_eth_shared_device,
- ð0_device,
- ð1_device,
- ð2_device,
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
- /* place the data */
- JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock on */
- JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock off and read-strobe */
- JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
- /* return the data */
- return (JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
- u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i,j;
-
- for (i = 0; i < 12; i++)
- exchange_bit(read_opcode[i], 1);
-
- for (j = 0; j < 6; j++) {
- dest[j] = 0;
- for (i = 0; i < 8; i++) {
- dest[j] <<= 1;
- dest[j] |= exchange_bit(0, 1);
- }
- }
-
- /* turn off CS */
- exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
- unsigned int add)
-{
- int i;
-
- BUG_ON(add >= 256);
-
- for (i = ETH_ALEN; i >= 0; i--) {
- dst[i] = src[i] + add;
- add = dst[i] < src[i]; /* compute carry */
- }
-
- WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
- unsigned char mac[ETH_ALEN];
- int ret;
-
- get_mac(mac);
- eth_mac_add(eth0_pd.mac_addr, mac, 0);
- eth_mac_add(eth1_pd.mac_addr, mac, 1);
- eth_mac_add(eth2_pd.mac_addr, mac, 2);
- ret = platform_add_devices(mv643xx_eth_pd_devs,
- ARRAY_SIZE(mv643xx_eth_pd_devs));
-
- return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
deleted file mode 100644
index 5dd154e..0000000
--- a/arch/mips/momentum/jaguar_atx/prom.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Added changes for SMP - Manish Lachwani (lachwani@pmc-sierra.com)
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-
-#include "jaguar_atx_fpga.h"
-
-extern void ja_setup_console(void);
-
-struct callvectors *debug_vectors;
-
-extern unsigned long cpu_clock;
-
-const char *get_system_type(void)
-{
- return "Momentum Jaguar-ATX";
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
- addr &= 0xffffffff;
- return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
- unsigned long ul;
- unsigned char *puc, uc;
-
- args += (arc * 4);
- ul = (unsigned long)signext(args);
- puc = (unsigned char *)ul;
- if (puc == 0)
- return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
- uc = *puc++;
- l = (unsigned long)uc;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 24);
-#else
- uc = *puc++;
- ul = ((unsigned long)uc) << 24;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= ((unsigned long)uc);
-#endif
- ul = signext(ul);
-
- return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
- unsigned long args;
- char *p;
-
- args = signext(addrin);
- p = (char *)get_arg(args, arg_index);
-
- return p;
-}
-#endif /* CONFIG_64BIT */
-
-/* PMON passes arguments in C main() style */
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **arg = (char **) fw_arg1;
- char **env = (char **) fw_arg2;
- struct callvectors *cv = (struct callvectors *) fw_arg3;
- int i;
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-// ja_setup_console(); /* The very first thing. */
-#endif
-
-#ifdef CONFIG_64BIT
- char *ptr;
-
- printk("Mips64 Jaguar-ATX\n");
- /* save the PROM vectors for debugging use */
- debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
-
- for (i = 1; i < argc; i++) {
- ptr = (char *)arg64((unsigned long)arg, i);
- if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
- sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, ptr);
- strcat(arcs_cmdline, " ");
- }
-
- i = 0;
- while (1) {
- ptr = (char *)arg64((unsigned long)env, i);
- if (! ptr)
- break;
-
- if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(ptr + strlen("gtbase="),
- NULL, 16);
-
- if ((marvell_base & 0xffffffff00000000) == 0)
- marvell_base |= 0xffffffff00000000;
-
- printk("marvell_base set to 0x%016lx\n", marvell_base);
- }
- if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
- NULL, 10);
- printk("cpu_clock set to %d\n", cpu_clock);
- }
- i++;
- }
- printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else /* CONFIG_64BIT */
- /* save the PROM vectors for debugging use */
- debug_vectors = cv;
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
- for (i = 1; i < argc; i++) {
- if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
- >= sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, arg[i]);
- strcat(arcs_cmdline, " ");
- }
-
- while (*env) {
- if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(*env + strlen("gtbase="),
- NULL, 16);
- }
- if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(*env + strlen("cpuclock="),
- NULL, 10);
- }
- env++;
- }
-#endif /* CONFIG_64BIT */
- mips_machgroup = MACH_GROUP_MOMENCO;
- mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
-
-int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp)
-{
- /* Clear the semaphore */
- *(volatile uint32_t *)(0xbb000a68) = 0x80000000;
-
- return 1;
-}
-
-void prom_init_secondary(void)
-{
- clear_c0_config(CONF_CM_CMASK);
- set_c0_config(0x2);
-
- clear_c0_status(ST0_IM);
- set_c0_status(0x1ffff);
-}
-
-void prom_smp_finish(void)
-{
-}
diff --git a/arch/mips/momentum/jaguar_atx/reset.c b/arch/mips/momentum/jaguar_atx/reset.c
deleted file mode 100644
index c73b089..0000000
--- a/arch/mips/momentum/jaguar_atx/reset.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_jaguar_restart(char *command)
-{
- /* base address of timekeeper portion of part */
-#ifdef CONFIG_64BIT
- void *nvram = (void*) 0xfffffffffc807000;
-#else
- void *nvram = (void*) 0xfc807000;
-#endif
- /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
- writeb(0x84, nvram + 0xff7);
-
- /* wait for the watchdog to go off */
- mdelay(100+(1000/16));
-
- /* if the watchdog fails for some reason, let people know */
- printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_jaguar_halt(void)
-{
- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void momenco_jaguar_power_off(void)
-{
- momenco_jaguar_halt();
-}
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
deleted file mode 100644
index 5a51014..0000000
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Jaguar-ATX board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001, 04, 06 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- * mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/pm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-#include <linux/mv643xx.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/tlbflush.h>
-
-#include "jaguar_atx_fpga.h"
-
-extern unsigned long mv64340_sram_base;
-unsigned long cpu_clock;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_jaguar_restart(char *command);
-extern void momenco_jaguar_halt(void);
-extern void momenco_jaguar_power_off(void);
-
-void momenco_time_init(void);
-
-static char reset_reason;
-
-static inline unsigned long ENTRYLO(unsigned long paddr)
-{
- return ((paddr & PAGE_MASK) |
- (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
- _CACHE_UNCACHED)) >> 6;
-}
-
-void __init bus_error_init(void) { /* nothing */ }
-
-/*
- * Load a few TLB entries for the MV64340 and perhiperals. The MV64340 is going
- * to be hit on every IRQ anyway - there's absolutely no point in letting it be
- * a random TLB entry, as it'll just cause needless churning of the TLB. And we
- * use the other half for the serial port, which is just a PITA otherwise :)
- *
- * Device Physical Virtual
- * MV64340 Internal Regs 0xf4000000 0xf4000000
- * Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000
- * NVRAM (CS1) 0xfc800000 0xfc800000
- * UARTs (CS2) 0xfd000000 0xfd000000
- * Internal SRAM 0xfe000000 0xfe000000
- * M-Systems DOC (CS3) 0xff000000 0xff000000
- */
-
-static __init void wire_stupidity_into_tlb(void)
-{
-#ifdef CONFIG_32BIT
- write_c0_wired(0);
- local_flush_tlb_all();
-
- /* marvell and extra space */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000),
- 0xf4000000UL, PM_64K);
- /* fpga, rtc, and uart */
- add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000),
- 0xfc000000UL, PM_16M);
-// /* m-sys and internal SRAM */
-// add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000),
-// 0xfe000000UL, PM_16M);
-
- marvell_base = 0xf4000000;
- //mv64340_sram_base = 0xfe000000; /* Currently unused */
-#endif
-}
-
-unsigned long marvell_base = 0xf4000000L;
-unsigned long ja_fpga_base = JAGUAR_ATX_CS0_ADDR;
-unsigned long uart_base = 0xfd000000L;
-static unsigned char *rtc_base = (unsigned char*) 0xfc800000L;
-
-EXPORT_SYMBOL(marvell_base);
-
-static __init int per_cpu_mappings(void)
-{
- marvell_base = (unsigned long) ioremap(0xf4000000, 0x10000);
- ja_fpga_base = (unsigned long) ioremap(JAGUAR_ATX_CS0_ADDR, 0x1000);
- uart_base = (unsigned long) ioremap(0xfd000000UL, 0x1000);
- rtc_base = ioremap(0xfc000000UL, 0x8000);
- // ioremap(0xfe000000, 32 << 20);
- write_c0_wired(0);
- local_flush_tlb_all();
- ja_setup_console();
-
- return 0;
-}
-arch_initcall(per_cpu_mappings);
-
-unsigned long m48t37y_get_time(void)
-{
- unsigned int year, month, day, hour, min, sec;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* stop the update */
- rtc_base[0x7ff8] = 0x40;
-
- year = BCD2BIN(rtc_base[0x7fff]);
- year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
- month = BCD2BIN(rtc_base[0x7ffe]);
-
- day = BCD2BIN(rtc_base[0x7ffd]);
-
- hour = BCD2BIN(rtc_base[0x7ffb]);
- min = BCD2BIN(rtc_base[0x7ffa]);
- sec = BCD2BIN(rtc_base[0x7ff9]);
-
- /* start the update */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
- struct rtc_time tm;
- unsigned long flags;
-
- /* convert to a more useful format -- note months count from 0 */
- to_tm(sec, &tm);
- tm.tm_mon += 1;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* enable writing */
- rtc_base[0x7ff8] = 0x80;
-
- /* year */
- rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
- rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
- /* month */
- rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
- /* day */
- rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
- /* hour/min/sec */
- rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
- rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
- rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
- /* day of week -- not really used, but let's keep it up-to-date */
- rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
- /* disable writing */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(8, irq);
-}
-
-/*
- * Ugly but the least of all evils. TLB initialization did flush the TLB so
- * We need to setup mappings again before we can touch the RTC.
- */
-void momenco_time_init(void)
-{
- wire_stupidity_into_tlb();
-
- mips_hpt_frequency = cpu_clock / 2;
-
- rtc_mips_get_time = m48t37y_get_time;
- rtc_mips_set_time = m48t37y_set_time;
-}
-
-static struct resource mv_pci_io_mem0_resource = {
- .name = "MV64340 PCI0 IO MEM",
- .flags = IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem0_resource = {
- .name = "MV64340 PCI0 MEM",
- .flags = IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem0_resource,
- .io_resource = &mv_pci_io_mem0_resource,
- },
- .config_addr = MV64340_PCI_0_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static uint32_t mv_io_base, mv_io_size;
-
-static void ja_pci0_init(void)
-{
- uint32_t mem0_base, mem0_size;
- uint32_t io_base, io_size;
-
- io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
- io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
- mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
- mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
-
- mv_pci_io_mem0_resource.start = 0;
- mv_pci_io_mem0_resource.end = io_size - 1;
- mv_pci_mem0_resource.start = mem0_base;
- mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
- mv_bus0_controller.pcic.mem_offset = mem0_base;
- mv_bus0_controller.pcic.io_offset = 0;
-
- ioport_resource.end = io_size - 1;
-
- register_pci_controller(&mv_bus0_controller.pcic);
-
- mv_io_base = io_base;
- mv_io_size = io_size;
-}
-
-static struct resource mv_pci_io_mem1_resource = {
- .name = "MV64340 PCI1 IO MEM",
- .flags = IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem1_resource = {
- .name = "MV64340 PCI1 MEM",
- .flags = IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem1_resource,
- .io_resource = &mv_pci_io_mem1_resource,
- },
- .config_addr = MV64340_PCI_1_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init void ja_pci1_init(void)
-{
- uint32_t mem0_base, mem0_size;
- uint32_t io_base, io_size;
-
- io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
- io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
- mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
- mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
-
- /*
- * Here we assume the I/O window of second bus to be contiguous with
- * the first. A gap is no problem but would waste address space for
- * remapping the port space.
- */
- mv_pci_io_mem1_resource.start = mv_io_size;
- mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
- mv_pci_mem1_resource.start = mem0_base;
- mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
- mv_bus1_controller.pcic.mem_offset = mem0_base;
- mv_bus1_controller.pcic.io_offset = 0;
-
- ioport_resource.end = io_base + io_size -mv_io_base - 1;
-
- register_pci_controller(&mv_bus1_controller.pcic);
-
- mv_io_size = io_base + io_size - mv_io_base;
-}
-
-static __init int __init ja_pci_init(void)
-{
- unsigned long io_v_base;
- uint32_t enable;
-
- enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-
- /*
- * We require at least one enabled I/O or PCI memory window or we
- * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
- */
- if (enable & (0x01 << 9) || enable & (0x01 << 10))
- ja_pci0_init();
-
- if (enable & (0x01 << 14) || enable & (0x01 << 15))
- ja_pci1_init();
-
- if (mv_io_size) {
- io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
- if (!io_v_base)
- panic("Could not ioremap I/O port range");
-
- set_io_port_base(io_v_base);
- }
-
- return 0;
-}
-
-arch_initcall(ja_pci_init);
-
-void __init plat_mem_setup(void)
-{
- unsigned int tmpword;
-
- board_time_init = momenco_time_init;
-
- _machine_restart = momenco_jaguar_restart;
- _machine_halt = momenco_jaguar_halt;
- pm_power_off = momenco_jaguar_power_off;
-
- /*
- * initrd_start = (unsigned long)jaguar_initrd_start;
- * initrd_end = (unsigned long)jaguar_initrd_start + (ulong)jaguar_initrd_size;
- * initrd_below_start_ok = 1;
- */
-
- wire_stupidity_into_tlb();
-
- /*
- * shut down ethernet ports, just to be sure our memory doesn't get
- * corrupted by random ethernet traffic.
- */
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
-
- /* Turn off the Bit-Error LED */
- JAGUAR_FPGA_WRITE(0x80, CLR);
-
- tmpword = JAGUAR_FPGA_READ(BOARDREV);
- if (tmpword < 26)
- printk("Momentum Jaguar-ATX: Board Assembly Rev. %c\n",
- 'A'+tmpword);
- else
- printk("Momentum Jaguar-ATX: Board Assembly Revision #0x%x\n",
- tmpword);
-
- tmpword = JAGUAR_FPGA_READ(FPGA_REV);
- printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
- tmpword = JAGUAR_FPGA_READ(RESET_STATUS);
- printk("Reset reason: 0x%x\n", tmpword);
- switch (tmpword) {
- case 0x1:
- printk(" - Power-up reset\n");
- break;
- case 0x2:
- printk(" - Push-button reset\n");
- break;
- case 0x8:
- printk(" - Watchdog reset\n");
- break;
- case 0x10:
- printk(" - JTAG reset\n");
- break;
- default:
- printk(" - Unknown reset cause\n");
- }
- reset_reason = tmpword;
- JAGUAR_FPGA_WRITE(0xff, RESET_STATUS);
-
- tmpword = JAGUAR_FPGA_READ(BOARD_STATUS);
- printk("Board Status register: 0x%02x\n", tmpword);
- printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
- printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
-
- /* 256MiB of RM9000x2 DDR */
-// add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
-
- /* 128MiB of MV-64340 DDR */
-// add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
-
- /* XXX Memory configuration should be picked up from PMON2k */
-#ifdef CONFIG_JAGUAR_DMALOW
- printk("Jaguar ATX DMA-low mode set\n");
- add_memory_region(0x00000000, 0x08000000, BOOT_MEM_RAM);
- add_memory_region(0x08000000, 0x10000000, BOOT_MEM_RAM);
-#else
- /* 128MiB of MV-64340 DDR RAM */
- printk("Jaguar ATX DMA-low mode is not set\n");
- add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
-#endif
-
-#ifdef GEMDEBUG_TRACEBUFFER
- {
- unsigned int tbControl;
- tbControl =
- 0 << 26 | /* post trigger delay 0 */
- 0x2 << 16 | /* sequential trace mode */
- // 0x0 << 16 | /* non-sequential trace mode */
- // 0xf << 4 | /* watchpoints disabled */
- 2 << 2 | /* armed */
- 2 ; /* interrupt disabled */
- printk ("setting tbControl = %08lx\n", tbControl);
- write_32bit_cp0_set1_register($22, tbControl);
- __asm__ __volatile__(".set noreorder\n\t" \
- "nop; nop; nop; nop; nop; nop;\n\t" \
- "nop; nop; nop; nop; nop; nop;\n\t" \
- ".set reorder\n\t");
-
- }
-#endif
-}
diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile
deleted file mode 100644
index c0a0030..0000000
--- a/arch/mips/momentum/ocelot_g/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-G board.
-#
-
-obj-y += irq.o gt-irq.o prom.o reset.o setup.o
-obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c
deleted file mode 100644
index 32d6fb4..0000000
--- a/arch/mips/momentum/ocelot_g/dbg_io.c
+++ /dev/null
@@ -1,121 +0,0 @@
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define UART16550_BAUD_2400 2400
-#define UART16550_BAUD_4800 4800
-#define UART16550_BAUD_9600 9600
-#define UART16550_BAUD_19200 19200
-#define UART16550_BAUD_38400 38400
-#define UART16550_BAUD_57600 57600
-#define UART16550_BAUD_115200 115200
-
-#define UART16550_PARITY_NONE 0
-#define UART16550_PARITY_ODD 0x08
-#define UART16550_PARITY_EVEN 0x18
-#define UART16550_PARITY_MARK 0x28
-#define UART16550_PARITY_SPACE 0x38
-
-#define UART16550_DATA_5BIT 0x0
-#define UART16550_DATA_6BIT 0x1
-#define UART16550_DATA_7BIT 0x2
-#define UART16550_DATA_8BIT 0x3
-
-#define UART16550_STOP_1BIT 0x0
-#define UART16550_STOP_2BIT 0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define BASE OCELOT_SERIAL1_BASE
-#define MAX_BAUD OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define REG_OFFSET 4
-
-/* register offset */
-#define OFS_RCV_BUFFER 0
-#define OFS_TRANS_HOLD 0
-#define OFS_SEND_BUFFER 0
-#define OFS_INTR_ENABLE (1*REG_OFFSET)
-#define OFS_INTR_ID (2*REG_OFFSET)
-#define OFS_DATA_FORMAT (3*REG_OFFSET)
-#define OFS_LINE_CONTROL (3*REG_OFFSET)
-#define OFS_MODEM_CONTROL (4*REG_OFFSET)
-#define OFS_RS232_OUTPUT (4*REG_OFFSET)
-#define OFS_LINE_STATUS (5*REG_OFFSET)
-#define OFS_MODEM_STATUS (6*REG_OFFSET)
-#define OFS_RS232_INPUT (6*REG_OFFSET)
-#define OFS_SCRATCH_PAD (7*REG_OFFSET)
-
-#define OFS_DIVISOR_LSB (0*REG_OFFSET)
-#define OFS_DIVISOR_MSB (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
-#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
- /* disable interrupts */
- UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
- /* set up baud rate */
- {
- uint32 divisor;
-
- /* set DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
- /* set divisor */
- divisor = MAX_BAUD / baud;
- UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
- UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
- /* clear DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
- }
-
- /* set data format */
- UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
- return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
- UART16550_WRITE(OFS_SEND_BUFFER, byte);
- return 1;
-}
diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c
deleted file mode 100644
index e5576bd..0000000
--- a/arch/mips/momentum/ocelot_g/gt-irq.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- *
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_g/gt_irq.c
- * Interrupt routines for gt64240. Currently it only handles timer irq.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/gt64240.h>
-#include <asm/io.h>
-
-unsigned long bus_clock;
-
-/*
- * These are interrupt handlers for the GT on-chip interrupts. They
- * all come in to the MIPS on a single interrupt line, and have to
- * be handled and ack'ed differently than other MIPS interrupts.
- */
-
-#if 0
-
-struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr);
-
-/*
- * Hooks IRQ handler to the system. When the system is interrupted
- * the interrupt service routine is called.
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num - Indicates which bit number in the cause register
- * isr_ptr - Pointer to the interrupt service routine
- */
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr)
-{
- irq_handlers[int_cause][bit_num].routine = isr_ptr;
-}
-
-
-/*
- * Enables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if successful, 0 if failure
- */
-int enable_galileo_irq(int int_cause, int bit_num)
-{
- if (int_cause == INT_CAUSE_MAIN)
- SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num));
- else if (int_cause == INT_CAUSE_HIGH)
- SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
- (1 << bit_num));
- else
- return 0;
-
- return 1;
-}
-
-/*
- * Disables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if successful, 0 if failure
- */
-int disable_galileo_irq(int int_cause, int bit_num)
-{
- if (int_cause == INT_CAUSE_MAIN)
- RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER,
- (1 << bit_num));
- else if (int_cause == INT_CAUSE_HIGH)
- RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
- (1 << bit_num));
- else
- return 0;
- return 1;
-}
-#endif /* 0 */
-
-/*
- * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#.
- *
- * We route the timer interrupt to P0_INT# (IRQ 6), and that's all this
- * routine can handle, for now.
- *
- * In the future, we'll route more interrupts to this pin, and that's why
- * we keep this particular structure in the function.
- */
-
-static irqreturn_t gt64240_p0int_irq(int irq, void *dev)
-{
- uint32_t irq_src, irq_src_mask;
- int handled;
-
- /* get the low interrupt cause register */
- irq_src = MV_READ(LOW_INTERRUPT_CAUSE_REGISTER);
-
- /* get the mask register for this pin */
- irq_src_mask = MV_READ(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW);
-
- /* mask off only the interrupts we're interested in */
- irq_src = irq_src & irq_src_mask;
-
- handled = IRQ_NONE;
-
- /* Check for timer interrupt */
- if (irq_src & 0x00000100) {
- handled = IRQ_HANDLED;
- irq_src &= ~0x00000100;
-
- /* Clear any pending cause bits */
- MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
-
- /* handle the timer call */
- do_timer(1);
-#ifndef CONFIG_SMP
- update_process_times(user_mode(get_irq_regs()));
-#endif
- }
-
- if (irq_src) {
- printk(KERN_INFO
- "UNKNOWN P0_INT# interrupt received, irq_src=0x%x\n",
- irq_src);
- }
-
- return handled;
-}
-
-/*
- * Initializes timer using galileo's built in timer.
- */
-
-/*
- * This will ignore the standard MIPS timer interrupt handler
- * that is passed in as *irq (=irq0 in ../kernel/time.c).
- * We will do our own timer interrupt handling.
- */
-void gt64240_time_init(void)
-{
- static struct irqaction timer;
-
- /* Stop the timer -- we'll use timer #0 */
- MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x0);
-
- /* Load timer value for 100 Hz */
- MV_WRITE(TIMER_COUNTER0, bus_clock / 100);
-
- /*
- * Create the IRQ structure entry for the timer. Since we're too early
- * in the boot process to use the "request_irq()" call, we'll hard-code
- * the values to the correct interrupt line.
- */
- timer.handler = >64240_p0int_irq;
- timer.flags = IRQF_SHARED | IRQF_DISABLED;
- timer.name = "timer";
- timer.dev_id = NULL;
- timer.next = NULL;
- timer.mask = CPU_MASK_NONE;
- irq_desc[6].action = &timer;
-
- enable_irq(6);
-
- /* Clear any pending cause bits */
- MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
-
- /* Enable the interrupt for timer 0 */
- MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_MASK, 0x1);
-
- /* Enable the timer interrupt for GT-64240 pin P0_INT# */
- MV_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x100);
-
- /* Configure and start the timer */
- MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x3);
-}
-
-void gt64240_irq_init(void)
-{
-#if 0
- int i, j;
-
- /* Reset irq handlers pointers to NULL */
- for (i = 0; i < MAX_CAUSE_REGS; i++) {
- for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
- irq_handlers[i][j].next = NULL;
- irq_handlers[i][j].sync = 0;
- irq_handlers[i][j].routine = NULL;
- irq_handlers[i][j].data = NULL;
- }
- }
-#endif /* 0 */
-}
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
deleted file mode 100644
index 273541f..0000000
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status();
-
- if (pending & STATUSF_IP2)
- do_IRQ(2);
- else if (pending & STATUSF_IP3)
- do_IRQ(3);
- else if (pending & STATUSF_IP4)
- do_IRQ(4);
- else if (pending & STATUSF_IP5)
- do_IRQ(5);
- else if (pending & STATUSF_IP6)
- do_IRQ(6);
- else if (pending & STATUSF_IP7)
- do_IRQ(7);
- else {
- /*
- * Now look at the extended interrupts
- */
- pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
-
- if (pending & STATUSF_IP8)
- do_IRQ(8);
- else if (pending & STATUSF_IP9)
- do_IRQ(9);
- else if (pending & STATUSF_IP10)
- do_IRQ(10);
- else if (pending & STATUSF_IP11)
- do_IRQ(11);
- else
- spurious_interrupt();
- }
-}
-
-extern void gt64240_irq_init(void);
-
-void __init arch_init_irq(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- * int-handler is not on bootstrap
- */
- clear_c0_status(ST0_IM);
- local_irq_disable();
-
- mips_cpu_irq_init();
- rm7k_cpu_irq_init();
-
- gt64240_irq_init();
-}
diff --git a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h
deleted file mode 100644
index 95e0534..0000000
--- a/arch/mips/momentum/ocelot_g/ocelot_pld.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Ocelot Board Register Definitions
- *
- * (C) 2001 Red Hat, Inc.
- *
- * GPL'd
- */
-#ifndef __MOMENCO_OCELOT_PLD_H__
-#define __MOMENCO_OCELOT_PLD_H__
-
-#define OCELOT_CS0_ADDR (0xfc000000)
-
-#define OCELOT_REG_BOARDREV (0)
-#define OCELOT_REG_PLD1_ID (1)
-#define OCELOT_REG_PLD2_ID (2)
-#define OCELOT_REG_RESET_STATUS (3)
-#define OCELOT_REG_BOARD_STATUS (4)
-#define OCELOT_REG_CPCI_ID (5)
-#define OCELOT_REG_I2C_CTRL (8)
-#define OCELOT_REG_EEPROM_MODE (9)
-#define OCELOT_REG_INTMASK (10)
-#define OCELOT_REG_INTSTATUS (11)
-#define OCELOT_REG_INTSET (12)
-#define OCELOT_REG_INTCLR (13)
-
-#define __PLD_REG_TO_ADDR(reg) ((void *) OCELOT_CS0_ADDR + OCELOT_REG_##reg)
-#define OCELOT_PLD_WRITE(x, reg) writeb(x, __PLD_REG_TO_ADDR(reg))
-#define OCELOT_PLD_READ(reg) readb(__PLD_REG_TO_ADDR(reg))
-
-#endif /* __MOMENCO_OCELOT_PLD_H__ */
diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c
deleted file mode 100644
index 836d08307..0000000
--- a/arch/mips/momentum/ocelot_g/prom.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-#include <asm/gt64240.h>
-
-#include "ocelot_pld.h"
-
-struct callvectors* debug_vectors;
-
-extern unsigned long marvell_base;
-extern unsigned long bus_clock;
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
-extern unsigned char prom_mac_addr_base[6];
-#endif
-
-const char *get_system_type(void)
-{
- return "Momentum Ocelot";
-}
-
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **arg = (char **) fw_arg1;
- char **env = (char **) fw_arg2;
- struct callvectors *cv = (struct callvectors *) fw_arg3;
- int i;
-
- /* save the PROM vectors for debugging use */
- debug_vectors = cv;
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
- for (i = 1; i < argc; i++) {
- if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
- >= sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, arg[i]);
- strcat(arcs_cmdline, " ");
- }
-
- mips_machgroup = MACH_GROUP_MOMENCO;
- mips_machtype = MACH_MOMENCO_OCELOT_G;
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
- /* get the base MAC address for on-board ethernet ports */
- memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
-#endif
-
- while (*env) {
- if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(*env + strlen("gtbase="),
- NULL, 16);
- }
- if (strncmp("busclock", *env, strlen("busclock")) == 0) {
- bus_clock = simple_strtol(*env + strlen("busclock="),
- NULL, 10);
- }
- env++;
- }
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
diff --git a/arch/mips/momentum/ocelot_g/reset.c b/arch/mips/momentum/ocelot_g/reset.c
deleted file mode 100644
index 3fd499a..0000000
--- a/arch/mips/momentum/ocelot_g/reset.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_ocelot_restart(char *command)
-{
- void *nvram = ioremap_nocache(0x2c807000, 0x1000);
-
- if (!nvram) {
- printk(KERN_NOTICE "ioremap of reset register failed\n");
- return;
- }
- writeb(0x84, nvram + 0xff7); /* Ask the NVRAM/RTC/watchdog chip to
- assert reset in 1/16 second */
- mdelay(10+(1000/16));
- iounmap(nvram);
- printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
- momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
deleted file mode 100644
index 9db638a..0000000
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-G (CP7000G) - board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001 Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- * mdharm@momenco.com
- *
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/gt64240.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <linux/bootmem.h>
-
-#include "ocelot_pld.h"
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
-extern unsigned char prom_mac_addr_base[6];
-#endif
-
-unsigned long marvell_base;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-extern void gt64240_time_init(void);
-extern void momenco_ocelot_irq_setup(void);
-
-static char reset_reason;
-
-static unsigned long ENTRYLO(unsigned long paddr)
-{
- return ((paddr & PAGE_MASK) |
- (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
- _CACHE_UNCACHED)) >> 6;
-}
-
-/* setup code for a handoff from a version 2 PMON 2000 PROM */
-void PMON_v2_setup(void)
-{
- /* A wired TLB entry for the GT64240 and the serial port. The
- GT64240 is going to be hit on every IRQ anyway - there's
- absolutely no point in letting it be a random TLB entry, as
- it'll just cause needless churning of the TLB. And we use
- the other half for the serial port, which is just a PITA
- otherwise :)
-
- Device Physical Virtual
- GT64240 Internal Regs 0xf4000000 0xe0000000
- UARTs (CS2) 0xfd000000 0xe0001000
- */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000),
- 0xf4000000, PM_64K);
- add_wired_entry(ENTRYLO(0xfd000000), ENTRYLO(0xfd001000),
- 0xfd000000, PM_4K);
-
- /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM
- in the CS[012] region. We can't use ioremap() yet. The NVRAM
- is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions.
-
- Ocelot PLD (CS0) 0xfc000000 0xe0020000
- NVRAM (CS1) 0xfc800000 0xe0030000
- */
- add_temporary_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfc010000),
- 0xfc000000, PM_64K);
- add_temporary_entry(ENTRYLO(0xfc800000), ENTRYLO(0xfc810000),
- 0xfc800000, PM_64K);
-
- marvell_base = 0xf4000000;
-}
-
-extern int rm7k_tcache_enabled;
-
-/*
- * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
- */
-#define Page_Invalidate_T 0x16
-static void __init setup_l3cache(unsigned long size)
-{
- int register i;
-
- printk("Enabling L3 cache...");
-
- /* Enable the L3 cache in the GT64120A's CPU Configuration register */
- MV_WRITE(0, MV_READ(0) | (1<<14));
-
- /* Enable the L3 cache in the CPU */
- set_c0_config(1<<12 /* CONF_TE */);
-
- /* Clear the cache */
- write_c0_taglo(0);
- write_c0_taghi(0);
-
- for (i=0; i < size; i+= 4096) {
- __asm__ __volatile__ (
- ".set noreorder\n\t"
- ".set mips3\n\t"
- "cache %1, (%0)\n\t"
- ".set mips0\n\t"
- ".set reorder"
- :
- : "r" (KSEG0ADDR(i)),
- "i" (Page_Invalidate_T));
- }
-
- /* Let the RM7000 MM code know that the tertiary cache is enabled */
- rm7k_tcache_enabled = 1;
-
- printk("Done\n");
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-}
-
-void __init plat_mem_setup(void)
-{
- void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache);
- unsigned int tmpword;
-
- board_time_init = gt64240_time_init;
-
- _machine_restart = momenco_ocelot_restart;
- _machine_halt = momenco_ocelot_halt;
- pm_power_off = momenco_ocelot_power_off;
-
- /*
- * initrd_start = (unsigned long)ocelot_initrd_start;
- * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size;
- * initrd_below_start_ok = 1;
- */
-
- /* do handoff reconfiguration */
- PMON_v2_setup();
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
- /* get the mac addr */
- memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
-#endif
-
- /* Turn off the Bit-Error LED */
- OCELOT_PLD_WRITE(0x80, INTCLR);
-
- tmpword = OCELOT_PLD_READ(BOARDREV);
- if (tmpword < 26)
- printk("Momenco Ocelot-G: Board Assembly Rev. %c\n", 'A'+tmpword);
- else
- printk("Momenco Ocelot-G: Board Assembly Revision #0x%x\n", tmpword);
-
- tmpword = OCELOT_PLD_READ(PLD1_ID);
- printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15);
- tmpword = OCELOT_PLD_READ(PLD2_ID);
- printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15);
- tmpword = OCELOT_PLD_READ(RESET_STATUS);
- printk("Reset reason: 0x%x\n", tmpword);
- reset_reason = tmpword;
- OCELOT_PLD_WRITE(0xff, RESET_STATUS);
-
- tmpword = OCELOT_PLD_READ(BOARD_STATUS);
- printk("Board Status register: 0x%02x\n", tmpword);
- printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
- printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
- printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not");
- printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
- printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
-
- if (tmpword&12)
- l3func((1<<(((tmpword&12) >> 2)+20)));
-
- switch(tmpword &3) {
- case 3:
- /* 512MiB -- two banks of 256MiB */
- add_memory_region( 0x0<<20, 0x100<<20, BOOT_MEM_RAM);
-/*
- add_memory_region(0x100<<20, 0x100<<20, BOOT_MEM_RAM);
-*/
- break;
- case 2:
- /* 256MiB -- two banks of 128MiB */
- add_memory_region( 0x0<<20, 0x80<<20, BOOT_MEM_RAM);
- add_memory_region(0x80<<20, 0x80<<20, BOOT_MEM_RAM);
- break;
- case 1:
- /* 128MiB -- 64MiB per bank */
- add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM);
- add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM);
- break;
- case 0:
- /* 64MiB */
- add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM);
- break;
- }
-
- /* FIXME: Fix up the DiskOnChip mapping */
- MV_WRITE(0x468, 0xfef73);
-}
-
-/* This needs to be one of the first initcalls, because no I/O port access
- can work before this */
-
-static int io_base_ioremap(void)
-{
- /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */
- unsigned long io_remap_range;
-
- io_remap_range = (unsigned long) ioremap(0xc0000000, 0x30000000);
- if (!io_remap_range)
- panic("Could not ioremap I/O port range");
-
- set_io_port_base(io_remap_range - 0xc0000000);
-
- return 0;
-}
-
-module_init(io_base_ioremap);
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index df487c0..aba3dbf 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -30,11 +30,9 @@
obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o
-obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o
obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o
obj-$(CONFIG_MOMENCO_OCELOT_3) += fixup-ocelot3.o
obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o
-obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o
obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \
pci-yosemite.o
obj-$(CONFIG_SGI_IP27) += ops-bridge.o pci-ip27.o
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index 7d5f6bb..d57ffd7 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -17,9 +17,7 @@
#include <asm/io.h>
#include <asm/gt64120.h>
-#include <asm/mach-cobalt/cobalt.h>
-
-extern int cobalt_board_id;
+#include <cobalt.h>
static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
{
@@ -115,6 +113,27 @@
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
qube_raq_galileo_fixup);
+int cobalt_board_id;
+
+static void qube_raq_via_board_id_fixup(struct pci_dev *dev)
+{
+ u8 id;
+ int retval;
+
+ retval = pci_read_config_byte(dev, VIA_COBALT_BRD_ID_REG, &id);
+ if (retval) {
+ panic("Cannot read board ID");
+ return;
+ }
+
+ cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(id);
+
+ printk(KERN_INFO "Cobalt board ID: %d\n", cobalt_board_id);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0,
+ qube_raq_via_board_id_fixup);
+
static char irq_tab_qube1[] __initdata = {
[COBALT_PCICONF_CPU] = 0,
[COBALT_PCICONF_ETH0] = COBALT_QUBE1_ETH0_IRQ,
diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c
deleted file mode 100644
index 6c5e1d4..0000000
--- a/arch/mips/pci/fixup-jaguar.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Marvell MV64340 interrupt fixup code.
- *
- * Marvell wants an NDA for their docs so this was written without
- * documentation. You've been warned.
- *
- * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#include <asm/mipsregs.h>
-
-/*
- * WARNING: Example of how _NOT_ to do it.
- */
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int bus = dev->bus->number;
-
- if (bus == 0 && slot == 1)
- return 3; /* PCI-X A */
- if (bus == 0 && slot == 2)
- return 4; /* PCI-X B */
- if (bus == 1 && slot == 1)
- return 5; /* PCI A */
- if (bus == 1 && slot == 2)
- return 6; /* PCI B */
-
-return 0;
- panic("Whooops in pcibios_map_irq");
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c
deleted file mode 100644
index d7a652e..0000000
--- a/arch/mips/pci/fixup-ocelot-g.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int bus = dev->bus->number;
-
- if (bus == 0 && slot == 1) /* Intel 82543 Gigabit MAC */
- return 2; /* irq_nr is 2 for INT0 */
-
- if (bus == 0 && slot == 2) /* Intel 82543 Gigabit MAC */
- return 3; /* irq_nr is 3 for INT1 */
-
- if (bus == 1 && slot == 3) /* Intel 21555 bridge */
- return 5; /* irq_nr is 8 for INT6 */
-
- if (bus == 1 && slot == 4) /* PMC Slot */
- return 9; /* irq_nr is 9 for INT7 */
-
- return -1;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c
deleted file mode 100644
index 1e34301..0000000
--- a/arch/mips/pci/pci-ocelot-g.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
- *
- * This doesn't really fly - but I don't have a GT64240 system for testing.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <asm/gt64240.h>
-
-/*
- * We assume these address ranges have been programmed into the GT-64240 by
- * the firmware. PMON in case of the Ocelot G does that. Note the size of
- * the I/O range is completly stupid; I/O mappings are limited to at most
- * 256 bytes by the PCI spec and deprecated; and just to make things worse
- * apparently many devices don't decode more than 64k of I/O space.
- */
-
-#define gt_io_size 0x20000000UL
-#define gt_io_base 0xe0000000UL
-
-static struct resource gt_pci_mem0_resource = {
- .name = "MV64240 PCI0 MEM",
- .start = 0xc0000000UL,
- .end = 0xcfffffffUL,
- .flags = IORESOURCE_MEM
-};
-
-static struct resource gt_pci_io_mem0_resource = {
- .name = "MV64240 PCI0 IO MEM",
- .start = 0xe0000000UL,
- .end = 0xefffffffUL,
- .flags = IORESOURCE_IO
-};
-
-static struct mv_pci_controller gt_bus0_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = >_pci_mem0_resource,
- .mem_offset = 0xc0000000UL,
- .io_resource = >_pci_io_mem0_resource,
- .io_offset = 0x00000000UL
- },
- .config_addr = PCI_0CONFIGURATION_ADDRESS,
- .config_vreg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER,
-};
-
-static struct resource gt_pci_mem1_resource = {
- .name = "MV64240 PCI1 MEM",
- .start = 0xd0000000UL,
- .end = 0xdfffffffUL,
- .flags = IORESOURCE_MEM
-};
-
-static struct resource gt_pci_io_mem1_resource = {
- .name = "MV64240 PCI1 IO MEM",
- .start = 0xf0000000UL,
- .end = 0xffffffffUL,
- .flags = IORESOURCE_IO
-};
-
-static struct mv_pci_controller gt_bus1_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = >_pci_mem1_resource,
- .mem_offset = 0xd0000000UL,
- .io_resource = >_pci_io_mem1_resource,
- .io_offset = 0x10000000UL
- },
- .config_addr = PCI_1CONFIGURATION_ADDRESS,
- .config_vreg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER,
-};
-
-static __init int __init ocelot_g_pci_init(void)
-{
- unsigned long io_v_base;
-
- if (gt_io_size) {
- io_v_base = (unsigned long) ioremap(gt_io_base, gt_io_size);
- if (!io_v_base)
- panic("Could not ioremap I/O port range");
-
- set_io_port_base(io_v_base);
- }
-
- register_pci_controller(>_bus0_controller.pcic);
- register_pci_controller(>_bus1_controller.pcic);
-
- return 0;
-}
-
-arch_initcall(ocelot_g_pci_init);
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index b6d6492..1fb3e35 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -4,6 +4,6 @@
#
obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
- ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
+ ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o
obj-$(CONFIG_EISA) += ip22-eisa.o
diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c
new file mode 100644
index 0000000..78b608d2
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-platform.c
@@ -0,0 +1,177 @@
+#include <linux/init.h>
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <asm/paccess.h>
+#include <asm/sgi/ip22.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/seeq.h>
+#include <asm/sgi/wd.h>
+
+static struct resource sgiwd93_0_resources[] = {
+ {
+ .name = "eth0 irq",
+ .start = SGI_WD93_0_IRQ,
+ .end = SGI_WD93_0_IRQ,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct sgiwd93_platform_data sgiwd93_0_pd = {
+ .unit = 0,
+ .irq = SGI_WD93_0_IRQ,
+};
+
+static struct platform_device sgiwd93_0_device = {
+ .name = "sgiwd93",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(sgiwd93_0_resources),
+ .resource = sgiwd93_0_resources,
+ .dev = {
+ .platform_data = &sgiwd93_0_pd,
+ },
+};
+
+static struct resource sgiwd93_1_resources[] = {
+ {
+ .name = "eth0 irq",
+ .start = SGI_WD93_1_IRQ,
+ .end = SGI_WD93_1_IRQ,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct sgiwd93_platform_data sgiwd93_1_pd = {
+ .unit = 1,
+ .irq = SGI_WD93_1_IRQ,
+};
+
+static struct platform_device sgiwd93_1_device = {
+ .name = "sgiwd93",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(sgiwd93_1_resources),
+ .resource = sgiwd93_1_resources,
+ .dev = {
+ .platform_data = &sgiwd93_1_pd,
+ },
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init sgiwd93_devinit(void)
+{
+ int res;
+
+ sgiwd93_0_pd.hregs = &hpc3c0->scsi_chan0;
+ sgiwd93_0_pd.wdregs = (unsigned char *) hpc3c0->scsi0_ext;
+
+ res = platform_device_register(&sgiwd93_0_device);
+ if (res)
+ return res;
+
+ if (!ip22_is_fullhouse())
+ return 0;
+
+ sgiwd93_1_pd.hregs = &hpc3c0->scsi_chan1;
+ sgiwd93_1_pd.wdregs = (unsigned char *) hpc3c0->scsi1_ext;
+
+ return platform_device_register(&sgiwd93_1_device);
+}
+
+device_initcall(sgiwd93_devinit);
+
+static struct resource sgiseeq_0_resources[] = {
+ {
+ .name = "eth0 irq",
+ .start = SGI_ENET_IRQ,
+ .end = SGI_ENET_IRQ,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct sgiseeq_platform_data eth0_pd;
+
+static struct platform_device eth0_device = {
+ .name = "sgiseeq",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(sgiseeq_0_resources),
+ .resource = sgiseeq_0_resources,
+ .dev = {
+ .platform_data = ð0_pd,
+ },
+};
+
+static struct resource sgiseeq_1_resources[] = {
+ {
+ .name = "eth1 irq",
+ .start = SGI_GIO_0_IRQ,
+ .end = SGI_GIO_0_IRQ,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct sgiseeq_platform_data eth1_pd;
+
+static struct platform_device eth1_device = {
+ .name = "sgiseeq",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(sgiseeq_1_resources),
+ .resource = sgiseeq_1_resources,
+ .dev = {
+ .platform_data = ð1_pd,
+ },
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init sgiseeq_devinit(void)
+{
+ unsigned int tmp;
+ int res, i;
+
+ eth0_pd.hpc = hpc3c0;
+ eth0_pd.irq = SGI_ENET_IRQ;
+#define EADDR_NVOFS 250
+ for (i = 0; i < 3; i++) {
+ unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i);
+
+ eth0_pd.mac[2 * i] = tmp >> 8;
+ eth0_pd.mac[2 * i + 1] = tmp & 0xff;
+ }
+
+ res = platform_device_register(ð0_device);
+ if (res)
+ return res;
+
+ /* Second HPC is missing? */
+ if (ip22_is_fullhouse() ||
+ !get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
+ return 0;
+
+ sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | SGIMC_GIOPAR_EXP164 |
+ SGIMC_GIOPAR_HPC264;
+ hpc3c1->pbus_piocfg[0][0] = 0x3ffff;
+ /* interrupt/config register on Challenge S Mezz board */
+ hpc3c1->pbus_extregs[0][0] = 0x30;
+
+ eth1_pd.hpc = hpc3c1;
+ eth1_pd.irq = SGI_GIO_0_IRQ;
+#define EADDR_NVOFS 250
+ for (i = 0; i < 3; i++) {
+ unsigned short tmp = ip22_eeprom_read(&hpc3c1->eeprom,
+ EADDR_NVOFS / 2 + i);
+
+ eth1_pd.mac[2 * i] = tmp >> 8;
+ eth1_pd.mac[2 * i + 1] = tmp & 0xff;
+ }
+
+ return platform_device_register(ð1_device);
+}
+
+device_initcall(sgiseeq_devinit);
diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c
index 7fe5e63..a4dab7c 100644
--- a/arch/powerpc/kernel/audit.c
+++ b/arch/powerpc/kernel/audit.c
@@ -23,6 +23,20 @@
~0U
};
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_PPC64
+ if (arch == AUDIT_ARCH_PPC)
+ return 1;
+#endif
+ return 0;
+}
+
int audit_classify_syscall(int abi, unsigned syscall)
{
#ifdef CONFIG_PPC64
@@ -51,15 +65,18 @@
extern __u32 ppc32_write_class[];
extern __u32 ppc32_read_class[];
extern __u32 ppc32_chattr_class[];
+ extern __u32 ppc32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL_32, ppc32_signal_class);
#endif
audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0;
}
diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c
index 640d4bb..108ff14 100644
--- a/arch/powerpc/kernel/compat_audit.c
+++ b/arch/powerpc/kernel/compat_audit.c
@@ -21,6 +21,11 @@
~0U
};
+unsigned ppc32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
int ppc32_classify_syscall(unsigned syscall)
{
switch(syscall) {
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 9ed4931..068377a 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -173,7 +173,7 @@
lv1_get_version_info(&tmp);
}
- hard_irq_enable();
+ __hard_irq_enable();
}
#endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/swsusp.c b/arch/powerpc/kernel/swsusp.c
index 064a7ba..77b7b34 100644
--- a/arch/powerpc/kernel/swsusp.c
+++ b/arch/powerpc/kernel/swsusp.c
@@ -36,8 +36,4 @@
#ifdef CONFIG_PPC32
set_context(current->active_mm->context.id, current->active_mm->pgd);
#endif
-
-#ifdef CONFIG_PPC64
- hard_irq_enable();
-#endif
}
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 8c20f0f..812bf56 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -43,12 +43,10 @@
unsigned long ctrl, thread_switch_control;
/*
- * We need to hard disable interrupts, but we also need to mark them
- * hard disabled in the PACA so that the local_irq_enable() done by
- * our caller upon return propertly hard enables.
+ * We need to hard disable interrupts, the local_irq_enable() done by
+ * our caller upon return will hard re-enable.
*/
hard_irq_disable();
- get_paca()->hard_enabled = 0;
ctrl = mfspr(SPRN_CTRLF);
diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c
index 0741d91..d1c76fe 100644
--- a/arch/s390/kernel/audit.c
+++ b/arch/s390/kernel/audit.c
@@ -23,6 +23,20 @@
~0U
};
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_COMPAT
+ if (arch == AUDIT_ARCH_S390)
+ return 1;
+#endif
+ return 0;
+}
+
int audit_classify_syscall(int abi, unsigned syscall)
{
#ifdef CONFIG_COMPAT
@@ -51,15 +65,18 @@
extern __u32 s390_write_class[];
extern __u32 s390_read_class[];
extern __u32 s390_chattr_class[];
+ extern __u32 s390_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL_32, s390_signal_class);
#endif
audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0;
}
diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c
index 16d9436..0569f51 100644
--- a/arch/s390/kernel/compat_audit.c
+++ b/arch/s390/kernel/compat_audit.c
@@ -21,6 +21,11 @@
~0U
};
+unsigned s390_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
int s390_classify_syscall(unsigned syscall)
{
switch(syscall) {
diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc64/kernel/audit.c
index aef19cc..24d7f4b 100644
--- a/arch/sparc64/kernel/audit.c
+++ b/arch/sparc64/kernel/audit.c
@@ -23,6 +23,20 @@
~0U
};
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_SPARC32_COMPAT
+ if (arch == AUDIT_ARCH_SPARC)
+ return 1;
+#endif
+ return 0;
+}
+
int audit_classify_syscall(int abi, unsigned syscall)
{
#ifdef CONFIG_SPARC32_COMPAT
@@ -51,15 +65,18 @@
extern __u32 sparc32_write_class[];
extern __u32 sparc32_read_class[];
extern __u32 sparc32_chattr_class[];
+ extern __u32 sparc32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL_32, sparc32_signal_class);
#endif
audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0;
}
diff --git a/arch/sparc64/kernel/compat_audit.c b/arch/sparc64/kernel/compat_audit.c
index cca96c9..c197948 100644
--- a/arch/sparc64/kernel/compat_audit.c
+++ b/arch/sparc64/kernel/compat_audit.c
@@ -20,6 +20,11 @@
~0U
};
+unsigned sparc32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
int sparc32_classify_syscall(unsigned syscall)
{
switch(syscall) {
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index b9c0f30..c504312 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -277,7 +277,8 @@
config KERNEL_STACK_ORDER
int "Kernel stack size order"
- default 2
+ default 1 if 64BIT
+ default 0 if !64BIT
help
This option determines the size of UML kernel stacks. They will
be 1 << order pages. The default is OK unless you're running Valgrind
diff --git a/arch/um/defconfig b/arch/um/defconfig
index f938fa8..a54d0ef 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -86,7 +86,7 @@
# CONFIG_MAGIC_SYSRQ is not set
CONFIG_NEST_LEVEL=0
# CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_KERNEL_STACK_ORDER=0
CONFIG_UML_REAL_TIME_CLOCK=y
#
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 5593a80..541f4a8 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -28,3 +28,5 @@
/* For crypto assembler code. */
DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
+
+DEFINE(UM_THREAD_SIZE, THREAD_SIZE);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 50a4969..8d7f7c1 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -117,4 +117,7 @@
extern void copy_sc(union uml_pt_regs *regs, void *from);
+unsigned long to_irq_stack(int sig, unsigned long *mask_out);
+unsigned long from_irq_stack(int nested);
+
#endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 688d181..4d9fb263 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -272,7 +272,6 @@
/* util.c */
extern void stack_protections(unsigned long address);
-extern void task_protections(unsigned long address);
extern int raw(int fd);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(char *buf, int len);
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index e36f92b..87a4e44 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -97,6 +97,8 @@
.data : {
. = ALIGN(KERNEL_STACK_SIZE); /* init_task */
*(.data.init_task)
+ . = ALIGN(KERNEL_STACK_SIZE);
+ *(.data.init_irqstack)
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index cda91aa..d4f1d1a 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com)
* Licensed under the GPL
*/
@@ -33,28 +33,20 @@
/*
* Initial thread structure.
*
- * We need to make sure that this is 16384-byte aligned due to the
+ * We need to make sure that this is aligned due to the
* way process stacks are handled. This is done by having a special
* "init_task" linker map entry..
*/
-union thread_union init_thread_union
-__attribute__((__section__(".data.init_task"))) =
-{ INIT_THREAD_INFO(init_task) };
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+ { INIT_THREAD_INFO(init_task) };
+
+union thread_union cpu0_irqstack
+ __attribute__((__section__(".data.init_irqstack"))) =
+ { INIT_THREAD_INFO(init_task) };
void unprotect_stack(unsigned long stack)
{
- os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
- 1, 1, 0);
+ os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 8f2ed36..dba04d8 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
* Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
@@ -32,6 +32,7 @@
#include "sigio.h"
#include "um_malloc.h"
#include "misc_constants.h"
+#include "as-layout.h"
/*
* Generic, controller-independent functions:
@@ -53,7 +54,7 @@
if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
- if (!action)
+ if (!action)
goto skip;
seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
@@ -468,3 +469,113 @@
out:
return err;
}
+
+/*
+ * IRQ stack entry and exit:
+ *
+ * Unlike i386, UML doesn't receive IRQs on the normal kernel stack
+ * and switch over to the IRQ stack after some preparation. We use
+ * sigaltstack to receive signals on a separate stack from the start.
+ * These two functions make sure the rest of the kernel won't be too
+ * upset by being on a different stack. The IRQ stack has a
+ * thread_info structure at the bottom so that current et al continue
+ * to work.
+ *
+ * to_irq_stack copies the current task's thread_info to the IRQ stack
+ * thread_info and sets the tasks's stack to point to the IRQ stack.
+ *
+ * from_irq_stack copies the thread_info struct back (flags may have
+ * been modified) and resets the task's stack pointer.
+ *
+ * Tricky bits -
+ *
+ * What happens when two signals race each other? UML doesn't block
+ * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal
+ * could arrive while a previous one is still setting up the
+ * thread_info.
+ *
+ * There are three cases -
+ * The first interrupt on the stack - sets up the thread_info and
+ * handles the interrupt
+ * A nested interrupt interrupting the copying of the thread_info -
+ * can't handle the interrupt, as the stack is in an unknown state
+ * A nested interrupt not interrupting the copying of the
+ * thread_info - doesn't do any setup, just handles the interrupt
+ *
+ * The first job is to figure out whether we interrupted stack setup.
+ * This is done by xchging the signal mask with thread_info->pending.
+ * If the value that comes back is zero, then there is no setup in
+ * progress, and the interrupt can be handled. If the value is
+ * non-zero, then there is stack setup in progress. In order to have
+ * the interrupt handled, we leave our signal in the mask, and it will
+ * be handled by the upper handler after it has set up the stack.
+ *
+ * Next is to figure out whether we are the outer handler or a nested
+ * one. As part of setting up the stack, thread_info->real_thread is
+ * set to non-NULL (and is reset to NULL on exit). This is the
+ * nesting indicator. If it is non-NULL, then the stack is already
+ * set up and the handler can run.
+ */
+
+static unsigned long pending_mask;
+
+unsigned long to_irq_stack(int sig, unsigned long *mask_out)
+{
+ struct thread_info *ti;
+ unsigned long mask, old;
+ int nested;
+
+ mask = xchg(&pending_mask, 1 << sig);
+ if(mask != 0){
+ /* If any interrupts come in at this point, we want to
+ * make sure that their bits aren't lost by our
+ * putting our bit in. So, this loop accumulates bits
+ * until xchg returns the same value that we put in.
+ * When that happens, there were no new interrupts,
+ * and pending_mask contains a bit for each interrupt
+ * that came in.
+ */
+ old = 1 << sig;
+ do {
+ old |= mask;
+ mask = xchg(&pending_mask, old);
+ } while(mask != old);
+ return 1;
+ }
+
+ ti = current_thread_info();
+ nested = (ti->real_thread != NULL);
+ if(!nested){
+ struct task_struct *task;
+ struct thread_info *tti;
+
+ task = cpu_tasks[ti->cpu].task;
+ tti = task_thread_info(task);
+ *ti = *tti;
+ ti->real_thread = tti;
+ task->stack = ti;
+ }
+
+ mask = xchg(&pending_mask, 0);
+ *mask_out |= mask | nested;
+ return 0;
+}
+
+unsigned long from_irq_stack(int nested)
+{
+ struct thread_info *ti, *to;
+ unsigned long mask;
+
+ ti = current_thread_info();
+
+ pending_mask = 1;
+
+ to = ti->real_thread;
+ current->stack = to;
+ ti->real_thread = NULL;
+ *to = *ti;
+
+ mask = xchg(&pending_mask, 0);
+ return mask & ~1;
+}
+
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index a96ae1a..2a69a7c 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -163,8 +163,12 @@
extern int userspace_pid[];
+extern char cpu0_irqstack[];
+
int start_uml_skas(void)
{
+ stack_protections((unsigned long) &cpu0_irqstack);
+ set_sigstack(cpu0_irqstack, THREAD_SIZE);
if(proc_mm)
userspace_pid[0] = start_userspace(0);
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 98e2174..40126cb 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -57,7 +57,7 @@
enable_timer();
free_page(stack);
protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
- task_protections((unsigned long) current_thread);
+ stack_protections((unsigned long) current_thread);
force_flush_all();
unblock_signals();
}
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index c631303..74347ad 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -209,7 +209,7 @@
if(current->mm != current->parent->mm)
protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
1, 0, 1);
- task_protections((unsigned long) current_thread);
+ stack_protections((unsigned long) current_thread);
free_page(current->thread.temp_stack);
local_irq_disable();
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 1cf954a..ecc458f 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -459,7 +459,7 @@
uml_postsetup();
- task_protections((unsigned long) &init_thread_info);
+ stack_protections((unsigned long) &init_thread_info);
os_flush_stdout();
return CHOOSE_MODE(start_uml_tt(), start_uml_skas());
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index f630127..bc59f97 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -59,6 +59,8 @@
{
. = ALIGN(KERNEL_STACK_SIZE); /* init_task */
*(.data.init_task)
+ . = ALIGN(KERNEL_STACK_SIZE);
+ *(.data.init_irqstack)
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 48d4934..18e5c8b 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -61,15 +61,19 @@
static void real_alarm_handler(int sig, struct sigcontext *sc)
{
+ union uml_pt_regs regs;
+
if(sig == SIGALRM)
switch_timers(0);
- CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
- sig, sc);
+ if(sc != NULL)
+ copy_sc(®s, sc);
+ regs.skas.is_user = 0;
+ unblock_signals();
+ timer_handler(sig, ®s);
if(sig == SIGALRM)
switch_timers(1);
-
}
void alarm_handler(int sig, struct sigcontext *sc)
@@ -113,6 +117,46 @@
void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+void handle_signal(int sig, struct sigcontext *sc)
+{
+ unsigned long pending = 0;
+
+ do {
+ int nested, bail;
+
+ /*
+ * pending comes back with one bit set for each
+ * interrupt that arrived while setting up the stack,
+ * plus a bit for this interrupt, plus the zero bit is
+ * set if this is a nested interrupt.
+ * If bail is true, then we interrupted another
+ * handler setting up the stack. In this case, we
+ * have to return, and the upper handler will deal
+ * with this interrupt.
+ */
+ bail = to_irq_stack(sig, &pending);
+ if(bail)
+ return;
+
+ nested = pending & 1;
+ pending &= ~1;
+
+ while((sig = ffs(pending)) != 0){
+ sig--;
+ pending &= ~(1 << sig);
+ (*handlers[sig])(sig, sc);
+ }
+
+ /* Again, pending comes back with a mask of signals
+ * that arrived while tearing down the stack. If this
+ * is non-zero, we just go back, set up the stack
+ * again, and handle the new interrupts.
+ */
+ if(!nested)
+ pending = from_irq_stack(nested);
+ } while(pending);
+}
+
extern void hard_handler(int sig);
void set_handler(int sig, void (*handler)(int), int flags, ...)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 6a0e466..f9d2f85 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -288,7 +288,8 @@
void userspace(union uml_pt_regs *regs)
{
int err, status, op, pid = userspace_pid[0];
- int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
+ /* To prevent races if using_sysemu changes under us.*/
+ int local_using_sysemu;
while(1){
restore_registers(pid, regs);
@@ -296,7 +297,8 @@
/* Now we set local_using_sysemu to be used for one loop */
local_using_sysemu = get_using_sysemu();
- op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
+ op = SELECT_PTRACE_OPERATION(local_using_sysemu,
+ singlestepping(NULL));
err = ptrace(op, pid, 0, 0);
if(err)
@@ -490,8 +492,8 @@
void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
{
(*buf)[0].JB_IP = (unsigned long) handler;
- (*buf)[0].JB_SP = (unsigned long) stack +
- (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
+ (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE -
+ sizeof(void *);
}
#define INIT_JMP_NEW_THREAD 0
@@ -533,8 +535,7 @@
case INIT_JMP_NEW_THREAD:
(*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
(*switch_buf)[0].JB_SP = (unsigned long) stack +
- (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
- sizeof(void *);
+ UM_THREAD_SIZE - sizeof(void *);
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
index 0d3eae5..f311609 100644
--- a/arch/um/os-Linux/sys-i386/signal.c
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -1,15 +1,13 @@
/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <signal.h>
-extern void (*handlers[])(int sig, struct sigcontext *sc);
+extern void handle_signal(int sig, struct sigcontext *sc);
void hard_handler(int sig)
{
- struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
-
- (*handlers[sig])(sig, sc);
+ handle_signal(sig, (struct sigcontext *) (&sig + 1));
}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
index 3f369e5..82a3888 100644
--- a/arch/um/os-Linux/sys-x86_64/signal.c
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -1,16 +1,16 @@
/*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
* Licensed under the GPL
*/
#include <signal.h>
-extern void (*handlers[])(int sig, struct sigcontext *sc);
+extern void handle_signal(int sig, struct sigcontext *sc);
void hard_handler(int sig)
{
struct ucontext *uc;
asm("movq %%rdx, %0" : "=r" (uc));
- (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext);
+ handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
}
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index c307a89..7cbcf48 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -33,25 +33,8 @@
void stack_protections(unsigned long address)
{
- int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-
- if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0)
- panic("protecting stack failed, errno = %d", errno);
-}
-
-void task_protections(unsigned long address)
-{
- unsigned long guard = address + UM_KERN_PAGE_SIZE;
- unsigned long stack = guard + UM_KERN_PAGE_SIZE;
- int prot = 0, pages;
-
-#ifdef notdef
- if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0)
- panic("protecting guard page failed, errno = %d", errno);
-#endif
- pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
- prot = PROT_READ | PROT_WRITE | PROT_EXEC;
- if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0)
+ if(mprotect((void *) address, UM_THREAD_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
panic("protecting stack failed, errno = %d", errno);
}
@@ -72,7 +55,7 @@
/* XXX tcsetattr could have applied only some changes
* (and cfmakeraw() is a set of changes) */
- return(0);
+ return 0;
}
void setup_machinename(char *machine_out)
diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c
index 92d7d0c..8850fe4 100644
--- a/arch/x86_64/ia32/audit.c
+++ b/arch/x86_64/ia32/audit.c
@@ -20,6 +20,11 @@
~0U
};
+unsigned ia32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
int ia32_classify_syscall(unsigned syscall)
{
switch(syscall) {
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index f210683..52be79b 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -716,4 +716,7 @@
.quad sys_getcpu
.quad sys_epoll_pwait
.quad compat_sys_utimensat /* 320 */
+ .quad sys_signalfd
+ .quad sys_timerfd
+ .quad sys_eventfd
ia32_syscall_end:
diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c
index 21f3338..06d3e5a 100644
--- a/arch/x86_64/kernel/audit.c
+++ b/arch/x86_64/kernel/audit.c
@@ -23,6 +23,20 @@
~0U
};
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_IA32_EMULATION
+ if (arch == AUDIT_ARCH_I386)
+ return 1;
+#endif
+ return 0;
+}
+
int audit_classify_syscall(int abi, unsigned syscall)
{
#ifdef CONFIG_IA32_EMULATION
@@ -49,15 +63,18 @@
extern __u32 ia32_write_class[];
extern __u32 ia32_read_class[];
extern __u32 ia32_chattr_class[];
+ extern __u32 ia32_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
#endif
audit_register_class(AUDIT_CLASS_WRITE, write_class);
audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0;
}
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 213d90e..6c34bdd 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -62,13 +62,6 @@
{
int i;
- /*
- * Make sure kernel is aligned to 2MB address. Catching it at compile
- * time is better. Change your config file and compile the kernel
- * for a 2MB aligned address (CONFIG_PHYSICAL_START)
- */
- BUILD_BUG_ON(CONFIG_PHYSICAL_START & (__KERNEL_ALIGN - 1));
-
/* clear bss before set_intr_gate with early_idt_handler */
clear_bss();
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 17e1889..74a567a 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -3116,7 +3116,7 @@
* bi_sector for remaps as it sees fit. So the values of these fields
* should NOT be depended on after the call to generic_make_request.
*/
-void generic_make_request(struct bio *bio)
+static inline void __generic_make_request(struct bio *bio)
{
request_queue_t *q;
sector_t maxsector;
@@ -3215,6 +3215,57 @@
} while (ret);
}
+/*
+ * We only want one ->make_request_fn to be active at a time,
+ * else stack usage with stacked devices could be a problem.
+ * So use current->bio_{list,tail} to keep a list of requests
+ * submited by a make_request_fn function.
+ * current->bio_tail is also used as a flag to say if
+ * generic_make_request is currently active in this task or not.
+ * If it is NULL, then no make_request is active. If it is non-NULL,
+ * then a make_request is active, and new requests should be added
+ * at the tail
+ */
+void generic_make_request(struct bio *bio)
+{
+ if (current->bio_tail) {
+ /* make_request is active */
+ *(current->bio_tail) = bio;
+ bio->bi_next = NULL;
+ current->bio_tail = &bio->bi_next;
+ return;
+ }
+ /* following loop may be a bit non-obvious, and so deserves some
+ * explanation.
+ * Before entering the loop, bio->bi_next is NULL (as all callers
+ * ensure that) so we have a list with a single bio.
+ * We pretend that we have just taken it off a longer list, so
+ * we assign bio_list to the next (which is NULL) and bio_tail
+ * to &bio_list, thus initialising the bio_list of new bios to be
+ * added. __generic_make_request may indeed add some more bios
+ * through a recursive call to generic_make_request. If it
+ * did, we find a non-NULL value in bio_list and re-enter the loop
+ * from the top. In this case we really did just take the bio
+ * of the top of the list (no pretending) and so fixup bio_list and
+ * bio_tail or bi_next, and call into __generic_make_request again.
+ *
+ * The loop was structured like this to make only one call to
+ * __generic_make_request (which is important as it is large and
+ * inlined) and to keep the structure simple.
+ */
+ BUG_ON(bio->bi_next);
+ do {
+ current->bio_list = bio->bi_next;
+ if (bio->bi_next == NULL)
+ current->bio_tail = ¤t->bio_list;
+ else
+ bio->bi_next = NULL;
+ __generic_make_request(bio);
+ bio = current->bio_list;
+ } while (bio);
+ current->bio_tail = NULL; /* deactivate */
+}
+
EXPORT_SYMBOL(generic_make_request);
/**
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 0f4203b..6055b9c 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -307,7 +307,9 @@
if (hu) {
struct hci_dev *hdev = hu->hdev;
- hci_uart_close(hdev);
+
+ if (hdev)
+ hci_uart_close(hdev);
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
hu->proto->close(hu);
@@ -473,12 +475,18 @@
tty->low_latency = 1;
} else
return -EBUSY;
+ break;
case HCIUARTGETPROTO:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return hu->proto->id;
return -EUNATCH;
+ case HCIUARTGETDEVICE:
+ if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+ return hu->hdev->id;
+ return -EUNATCH;
+
default:
err = n_tty_ioctl(tty, file, cmd, arg);
break;
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index b250e67..1097ce7 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -28,8 +28,9 @@
#endif
/* Ioctls */
-#define HCIUARTSETPROTO _IOW('U', 200, int)
-#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTSETPROTO _IOW('U', 200, int)
+#define HCIUARTGETPROTO _IOR('U', 201, int)
+#define HCIUARTGETDEVICE _IOR('U', 202, int)
/* UART protocols */
#define HCI_UART_MAX_PROTO 4
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 6ac3ca4..b3d4ccc 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1544,21 +1544,18 @@
}
struct tty_ldisc tty_ldisc_N_TTY = {
- TTY_LDISC_MAGIC, /* magic */
- "n_tty", /* name */
- 0, /* num */
- 0, /* flags */
- n_tty_open, /* open */
- n_tty_close, /* close */
- n_tty_flush_buffer, /* flush_buffer */
- n_tty_chars_in_buffer, /* chars_in_buffer */
- read_chan, /* read */
- write_chan, /* write */
- n_tty_ioctl, /* ioctl */
- n_tty_set_termios, /* set_termios */
- normal_poll, /* poll */
- NULL, /* hangup */
- n_tty_receive_buf, /* receive_buf */
- n_tty_write_wakeup /* write_wakeup */
+ .magic = TTY_LDISC_MAGIC,
+ .name = "n_tty",
+ .open = n_tty_open,
+ .close = n_tty_close,
+ .flush_buffer = n_tty_flush_buffer,
+ .chars_in_buffer = n_tty_chars_in_buffer,
+ .read = read_chan,
+ .write = write_chan,
+ .ioctl = n_tty_ioctl,
+ .set_termios = n_tty_set_termios,
+ .poll = normal_poll,
+ .receive_buf = n_tty_receive_buf,
+ .write_wakeup = n_tty_write_wakeup
};
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 245f031..8cc60b6 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -402,7 +402,7 @@
rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number 0x%x\n", rup);
- if (Rup >= (unsigned short) MAX_RUP) {
+ if (Rup < (unsigned short) MAX_RUP) {
rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
} else
rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 61a63da..a3fd7e7 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1014,9 +1014,6 @@
/*
* Info->count is now 1; so it's safe to sleep now.
*/
- info->session = process_session(current);
- info->pgrp = process_group(current);
-
if ((info->flags & ROCKET_INITIALIZED) == 0) {
cp = &info->channel;
sSetRxTrigger(cp, TRIG_1);
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 89b4d7b..b4c53df 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1158,8 +1158,6 @@
int xmit_head;
int xmit_tail;
int xmit_cnt;
- int session;
- int pgrp;
int cd_status;
int ignore_status_mask;
int read_status_mask;
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2a7736b..02b49bc 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1171,6 +1171,112 @@
}
/*
+ * support for 32 bit ioctl calls on 64 bit systems
+ */
+#ifdef CONFIG_COMPAT
+static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params)
+{
+ struct MGSL_PARAMS32 tmp_params;
+
+ DBGINFO(("%s get_params32\n", info->device_name));
+ tmp_params.mode = (compat_ulong_t)info->params.mode;
+ tmp_params.loopback = info->params.loopback;
+ tmp_params.flags = info->params.flags;
+ tmp_params.encoding = info->params.encoding;
+ tmp_params.clock_speed = (compat_ulong_t)info->params.clock_speed;
+ tmp_params.addr_filter = info->params.addr_filter;
+ tmp_params.crc_type = info->params.crc_type;
+ tmp_params.preamble_length = info->params.preamble_length;
+ tmp_params.preamble = info->params.preamble;
+ tmp_params.data_rate = (compat_ulong_t)info->params.data_rate;
+ tmp_params.data_bits = info->params.data_bits;
+ tmp_params.stop_bits = info->params.stop_bits;
+ tmp_params.parity = info->params.parity;
+ if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32)))
+ return -EFAULT;
+ return 0;
+}
+
+static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params)
+{
+ struct MGSL_PARAMS32 tmp_params;
+
+ DBGINFO(("%s set_params32\n", info->device_name));
+ if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32)))
+ return -EFAULT;
+
+ spin_lock(&info->lock);
+ info->params.mode = tmp_params.mode;
+ info->params.loopback = tmp_params.loopback;
+ info->params.flags = tmp_params.flags;
+ info->params.encoding = tmp_params.encoding;
+ info->params.clock_speed = tmp_params.clock_speed;
+ info->params.addr_filter = tmp_params.addr_filter;
+ info->params.crc_type = tmp_params.crc_type;
+ info->params.preamble_length = tmp_params.preamble_length;
+ info->params.preamble = tmp_params.preamble;
+ info->params.data_rate = tmp_params.data_rate;
+ info->params.data_bits = tmp_params.data_bits;
+ info->params.stop_bits = tmp_params.stop_bits;
+ info->params.parity = tmp_params.parity;
+ spin_unlock(&info->lock);
+
+ change_params(info);
+
+ return 0;
+}
+
+static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct slgt_info *info = tty->driver_data;
+ int rc = -ENOIOCTLCMD;
+
+ if (sanity_check(info, tty->name, "compat_ioctl"))
+ return -ENODEV;
+ DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));
+
+ switch (cmd) {
+
+ case MGSL_IOCSPARAMS32:
+ rc = set_params32(info, compat_ptr(arg));
+ break;
+
+ case MGSL_IOCGPARAMS32:
+ rc = get_params32(info, compat_ptr(arg));
+ break;
+
+ case MGSL_IOCGPARAMS:
+ case MGSL_IOCSPARAMS:
+ case MGSL_IOCGTXIDLE:
+ case MGSL_IOCGSTATS:
+ case MGSL_IOCWAITEVENT:
+ case MGSL_IOCGIF:
+ case MGSL_IOCSGPIO:
+ case MGSL_IOCGGPIO:
+ case MGSL_IOCWAITGPIO:
+ case TIOCGICOUNT:
+ rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
+ break;
+
+ case MGSL_IOCSTXIDLE:
+ case MGSL_IOCTXENABLE:
+ case MGSL_IOCRXENABLE:
+ case MGSL_IOCTXABORT:
+ case TIOCMIWAIT:
+ case MGSL_IOCSIF:
+ rc = ioctl(tty, file, cmd, arg);
+ break;
+ }
+
+ DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));
+ return rc;
+}
+#else
+#define slgt_compat_ioctl NULL
+#endif /* ifdef CONFIG_COMPAT */
+
+/*
* proc fs support
*/
static inline int line_info(char *buf, struct slgt_info *info)
@@ -3446,6 +3552,7 @@
.chars_in_buffer = chars_in_buffer,
.flush_buffer = flush_buffer,
.ioctl = ioctl,
+ .compat_ioctl = slgt_compat_ioctl,
.throttle = throttle,
.unthrottle = unthrottle,
.send_xchar = send_xchar,
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index fc662e4..fe62c21 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -151,6 +151,12 @@
static int tty_release(struct inode *, struct file *);
int tty_ioctl(struct inode * inode, struct file * file,
unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+ unsigned long arg);
+#else
+#define tty_compat_ioctl NULL
+#endif
static int tty_fasync(int fd, struct file * filp, int on);
static void release_tty(struct tty_struct *tty, int idx);
static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
@@ -1143,8 +1149,8 @@
return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
}
-static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
- unsigned int cmd, unsigned long arg)
+static long hung_up_tty_ioctl(struct file * file,
+ unsigned int cmd, unsigned long arg)
{
return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
}
@@ -1155,6 +1161,7 @@
.write = tty_write,
.poll = tty_poll,
.ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
@@ -1167,6 +1174,7 @@
.write = tty_write,
.poll = tty_poll,
.ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
.open = ptmx_open,
.release = tty_release,
.fasync = tty_fasync,
@@ -1179,6 +1187,7 @@
.write = redirected_tty_write,
.poll = tty_poll,
.ioctl = tty_ioctl,
+ .compat_ioctl = tty_compat_ioctl,
.open = tty_open,
.release = tty_release,
.fasync = tty_fasync,
@@ -1189,7 +1198,8 @@
.read = hung_up_tty_read,
.write = hung_up_tty_write,
.poll = hung_up_tty_poll,
- .ioctl = hung_up_tty_ioctl,
+ .unlocked_ioctl = hung_up_tty_ioctl,
+ .compat_ioctl = hung_up_tty_ioctl,
.release = tty_release,
};
@@ -3357,6 +3367,32 @@
return retval;
}
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct tty_struct *tty = file->private_data;
+ struct tty_ldisc *ld;
+ int retval = -ENOIOCTLCMD;
+
+ if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+ return -EINVAL;
+
+ if (tty->driver->compat_ioctl) {
+ retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg);
+ if (retval != -ENOIOCTLCMD)
+ return retval;
+ }
+
+ ld = tty_ldisc_ref_wait(tty);
+ if (ld->compat_ioctl)
+ retval = ld->compat_ioctl(tty, file, cmd, arg);
+ tty_ldisc_deref(ld);
+
+ return retval;
+}
+#endif
/*
* This implements the "Secure Attention Key" --- the idea is to
@@ -3689,6 +3725,7 @@
driver->write_room = op->write_room;
driver->chars_in_buffer = op->chars_in_buffer;
driver->ioctl = op->ioctl;
+ driver->compat_ioctl = op->compat_ioctl;
driver->set_termios = op->set_termios;
driver->throttle = op->throttle;
driver->unthrottle = op->unthrottle;
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index a19b65e..7f81789 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -240,11 +240,94 @@
}
#endif
+static inline int match_scancode(int code, int scancode)
+{
+ if (scancode == 0)
+ return 1;
+ return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode);
+}
+
+static inline int match_keycode(int code, int keycode)
+{
+ if (keycode == 0)
+ return 1;
+ return (code == keycode);
+}
+
+static struct hid_usage *hidinput_find_key(struct hid_device *hid,
+ int scancode, int keycode)
+{
+ int i, j, k;
+ struct hid_report *report;
+ struct hid_usage *usage;
+
+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+ list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
+ for (i = 0; i < report->maxfield; i++) {
+ for ( j = 0; j < report->field[i]->maxusage; j++) {
+ usage = report->field[i]->usage + j;
+ if (usage->type == EV_KEY &&
+ match_scancode(usage->hid, scancode) &&
+ match_keycode(usage->code, keycode))
+ return usage;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+static int hidinput_getkeycode(struct input_dev *dev, int scancode,
+ int *keycode)
+{
+ struct hid_device *hid = dev->private;
+ struct hid_usage *usage;
+
+ usage = hidinput_find_key(hid, scancode, 0);
+ if (usage) {
+ *keycode = usage->code;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int hidinput_setkeycode(struct input_dev *dev, int scancode,
+ int keycode)
+{
+ struct hid_device *hid = dev->private;
+ struct hid_usage *usage;
+ int old_keycode;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ usage = hidinput_find_key(hid, scancode, 0);
+ if (usage) {
+ old_keycode = usage->code;
+ usage->code = keycode;
+
+ clear_bit(old_keycode, dev->keybit);
+ set_bit(usage->code, dev->keybit);
+#ifdef CONFIG_HID_DEBUG
+ printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
+#endif
+ /* Set the keybit for the old keycode if the old keycode is used
+ * by another key */
+ if (hidinput_find_key (hid, 0, old_keycode))
+ set_bit(old_keycode, dev->keybit);
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+
static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage)
{
struct input_dev *input = hidinput->input;
- struct hid_device *device = input->private;
+ struct hid_device *device = input_get_drvdata(input);
int max = 0, code;
unsigned long *bit = NULL;
@@ -553,6 +636,7 @@
case 0x1015: map_key_clear(KEY_RECORD); break;
case 0x1016: map_key_clear(KEY_PLAYER); break;
case 0x1017: map_key_clear(KEY_EJECTCD); break;
+ case 0x1018: map_key_clear(KEY_MEDIA); break;
case 0x1019: map_key_clear(KEY_PROG1); break;
case 0x101a: map_key_clear(KEY_PROG2); break;
case 0x101b: map_key_clear(KEY_PROG3); break;
@@ -560,9 +644,12 @@
case 0x1020: map_key_clear(KEY_ZOOMOUT); break;
case 0x1021: map_key_clear(KEY_ZOOMRESET); break;
case 0x1023: map_key_clear(KEY_CLOSE); break;
+ case 0x1027: map_key_clear(KEY_MENU); break;
/* this one is marked as 'Rotate' */
case 0x1028: map_key_clear(KEY_ANGLE); break;
case 0x1029: map_key_clear(KEY_SHUFFLE); break;
+ case 0x102a: map_key_clear(KEY_BACK); break;
+ case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break;
case 0x1041: map_key_clear(KEY_BATTERY); break;
case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break;
case 0x1043: map_key_clear(KEY_SPREADSHEET); break;
@@ -855,13 +942,15 @@
static int hidinput_open(struct input_dev *dev)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
+
return hid->hid_open(hid);
}
static void hidinput_close(struct input_dev *dev)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
+
hid->hid_close(hid);
}
@@ -909,10 +998,12 @@
return -1;
}
- input_dev->private = hid;
+ input_set_drvdata(input_dev, hid);
input_dev->event = hid->hidinput_input_event;
input_dev->open = hidinput_open;
input_dev->close = hidinput_close;
+ input_dev->setkeycode = hidinput_setkeycode;
+ input_dev->getkeycode = hidinput_getkeycode;
input_dev->name = hid->name;
input_dev->phys = hid->phys;
@@ -921,7 +1012,7 @@
input_dev->id.vendor = hid->vendor;
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
- input_dev->cdev.dev = hid->dev;
+ input_dev->dev.parent = hid->dev;
hidinput->input = input_dev;
list_add_tail(&hidinput->list, &hid->inputs);
}
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 7c87bdc..1b4b572 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -25,12 +25,12 @@
depends on USB_HID && INPUT=n
config USB_HIDINPUT_POWERBOOK
- bool "Enable support for iBook/PowerBook special keys"
+ bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys"
default n
depends on USB_HID
help
Say Y here if you want support for the special keys (Fn, Numlock) on
- Apple iBooks and PowerBooks.
+ Apple iBooks, PowerBooks, MacBooks and MacBook Pros.
If unsure, say N.
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 91d6103..d91b9da 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -446,7 +446,7 @@
static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct hid_field *field;
int offset;
@@ -626,14 +626,10 @@
{
struct usbhid_device *usbhid = hid->driver_data;
- if (usbhid->inbuf)
- usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
- if (usbhid->outbuf)
- usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
- if (usbhid->cr)
- usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
- if (usbhid->ctrlbuf)
- usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+ usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}
/*
@@ -692,6 +688,30 @@
}
}
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
+{
+ short fixed = 0;
+ int i;
+
+ for (i = 0; i < rsize - 4; i++) {
+ if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
+ unsigned char tmp;
+
+ rdesc[i] = 0x19; rdesc[i+2] = 0x29;
+ tmp = rdesc[i+3];
+ rdesc[i+3] = rdesc[i+1];
+ rdesc[i+1] = tmp;
+ }
+ }
+
+ if (fixed)
+ info("Fixing up Cypress report descriptor");
+}
+
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
struct usb_host_interface *interface = intf->cur_altsetting;
@@ -758,6 +778,9 @@
if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
hid_fixup_logitech_descriptor(rdesc, rsize);
+ if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
+ hid_fixup_cypress_descriptor(rdesc, rsize);
+
#ifdef CONFIG_HID_DEBUG
printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
index 92d2553..c5cd410 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/usbhid/hid-lgff.c
@@ -60,7 +60,7 @@
static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
int x, y;
diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/usbhid/hid-plff.c
index 76d2e6e..d6a8f2b 100644
--- a/drivers/hid/usbhid/hid-plff.c
+++ b/drivers/hid/usbhid/hid-plff.c
@@ -37,7 +37,7 @@
static int hid_plff_play(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct plff_device *plff = data;
int left, right;
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 17a8755..f6c4145 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -92,6 +92,8 @@
#define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001
#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
+#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
+#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
#define USB_VENDOR_ID_DELL 0x413c
#define USB_DEVICE_ID_DELL_W7658 0x2005
@@ -193,6 +195,7 @@
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
+#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
@@ -422,6 +425,7 @@
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -445,6 +449,9 @@
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
+
{ 0, 0 }
};
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index ab67331..ab5ba6e 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -59,7 +59,7 @@
static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct tmff_device *tmff = data;
int left, right; /* Rumbling */
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
index 7bd8238..a7fbffc 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/usbhid/hid-zpff.c
@@ -37,7 +37,7 @@
static int hid_zpff_play(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct zpff_device *zpff = data;
int left, right;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index a8b3d66..488d61b 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -51,6 +51,7 @@
wait_queue_head_t wait;
struct hid_device *hid;
struct list_head list;
+ spinlock_t list_lock;
};
struct hiddev_list {
@@ -161,7 +162,9 @@
{
struct hiddev *hiddev = hid->hiddev;
struct hiddev_list *list;
+ unsigned long flags;
+ spin_lock_irqsave(&hiddev->list_lock, flags);
list_for_each_entry(list, &hiddev->list, node) {
if (uref->field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
@@ -171,6 +174,7 @@
kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
}
+ spin_unlock_irqrestore(&hiddev->list_lock, flags);
wake_up_interruptible(&hiddev->wait);
}
@@ -235,9 +239,13 @@
static int hiddev_release(struct inode * inode, struct file * file)
{
struct hiddev_list *list = file->private_data;
+ unsigned long flags;
hiddev_fasync(-1, file, 0);
+
+ spin_lock_irqsave(&list->hiddev->list_lock, flags);
list_del(&list->node);
+ spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
if (!--list->hiddev->open) {
if (list->hiddev->exist)
@@ -257,6 +265,7 @@
static int hiddev_open(struct inode *inode, struct file *file)
{
struct hiddev_list *list;
+ unsigned long flags;
int i = iminor(inode) - HIDDEV_MINOR_BASE;
@@ -267,7 +276,11 @@
return -ENOMEM;
list->hiddev = hiddev_table[i];
+
+ spin_lock_irqsave(&list->hiddev->list_lock, flags);
list_add_tail(&list->node, &hiddev_table[i]->list);
+ spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
+
file->private_data = list;
if (!list->hiddev->open++)
@@ -773,6 +786,7 @@
init_waitqueue_head(&hiddev->wait);
INIT_LIST_HEAD(&hiddev->list);
+ spin_lock_init(&hiddev->list_lock);
hiddev->hid = hid;
hiddev->exist = 1;
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 65aa12e8..1309787 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -133,12 +133,11 @@
static int usb_kbd_event(struct input_dev *dev, unsigned int type,
unsigned int code, int value)
{
- struct usb_kbd *kbd = dev->private;
+ struct usb_kbd *kbd = input_get_drvdata(dev);
if (type != EV_LED)
return -1;
-
kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
(!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
(!!test_bit(LED_NUML, dev->led));
@@ -175,7 +174,7 @@
static int usb_kbd_open(struct input_dev *dev)
{
- struct usb_kbd *kbd = dev->private;
+ struct usb_kbd *kbd = input_get_drvdata(dev);
kbd->irq->dev = kbd->usbdev;
if (usb_submit_urb(kbd->irq, GFP_KERNEL))
@@ -186,7 +185,7 @@
static void usb_kbd_close(struct input_dev *dev)
{
- struct usb_kbd *kbd = dev->private;
+ struct usb_kbd *kbd = input_get_drvdata(dev);
usb_kill_urb(kbd->irq);
}
@@ -211,12 +210,9 @@
{
usb_free_urb(kbd->irq);
usb_free_urb(kbd->led);
- if (kbd->new)
- usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
- if (kbd->cr)
- usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
- if (kbd->leds)
- usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
+ usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
+ usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
+ usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
}
static int usb_kbd_probe(struct usb_interface *iface,
@@ -274,8 +270,9 @@
input_dev->name = kbd->name;
input_dev->phys = kbd->phys;
usb_to_input_id(dev, &input_dev->id);
- input_dev->cdev.dev = &iface->dev;
- input_dev->private = kbd;
+ input_dev->dev.parent = &iface->dev;
+
+ input_set_drvdata(input_dev, kbd);
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 573776d..5345c73 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -96,7 +96,7 @@
static int usb_mouse_open(struct input_dev *dev)
{
- struct usb_mouse *mouse = dev->private;
+ struct usb_mouse *mouse = input_get_drvdata(dev);
mouse->irq->dev = mouse->usbdev;
if (usb_submit_urb(mouse->irq, GFP_KERNEL))
@@ -107,7 +107,7 @@
static void usb_mouse_close(struct input_dev *dev)
{
- struct usb_mouse *mouse = dev->private;
+ struct usb_mouse *mouse = input_get_drvdata(dev);
usb_kill_urb(mouse->irq);
}
@@ -171,7 +171,7 @@
input_dev->name = mouse->name;
input_dev->phys = mouse->phys;
usb_to_input_id(dev, &input_dev->id);
- input_dev->cdev.dev = &intf->dev;
+ input_dev->dev.parent = &intf->dev;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
@@ -179,7 +179,8 @@
input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
input_dev->relbit[0] |= BIT(REL_WHEEL);
- input_dev->private = mouse;
+ input_set_drvdata(input_dev, mouse);
+
input_dev->open = usb_mouse_open;
input_dev->close = usb_mouse_close;
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 55a7259..b234729 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -336,7 +336,7 @@
if (compat) {
len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
- if (len < maxlen)
+ if (len > maxlen)
len = maxlen;
for (i = 0; i < len / sizeof(compat_long_t); i++)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 65814b0..c10ce91 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5103,7 +5103,7 @@
*
* Note: the following is an unsigned comparison.
*/
- if ((curr_events - rdev->last_events + 4096) > 8192) {
+ if ((long)curr_events - (long)rdev->last_events > 4096) {
rdev->last_events = curr_events;
idle = 0;
}
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 7c8ccc0..829da9a 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -141,6 +141,20 @@
To activate support for ACTiSYS IR-200L dongle you will have to
start irattach like this: "irattach -d act200l".
+config KINGSUN_DONGLE
+ tristate "KingSun/DonShine DS-620 IrDA-USB dongle"
+ depends on IRDA && USB && EXPERIMENTAL
+ help
+ Say Y or M here if you want to build support for the KingSun/DonShine
+ DS-620 IrDA-USB bridge device driver.
+
+ This USB bridge does not conform to the IrDA-USB device class
+ specification, and therefore needs its own specific driver. This
+ dongle supports SIR speed only (9600 bps).
+
+ To compile it as a module, choose M here: the module will be called
+ kingsun-sir.
+
comment "Old SIR device drivers"
config IRPORT_SIR
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 5be09f1..233a2f9 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -45,6 +45,7 @@
obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
+obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o
# The SIR helper module
sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
new file mode 100644
index 0000000..2174291
--- /dev/null
+++ b/drivers/net/irda/kingsun-sir.c
@@ -0,0 +1,657 @@
+/*****************************************************************************
+*
+* Filename: kingsun-sir.c
+* Version: 0.1.1
+* Description: Irda KingSun/DonShine USB Dongle
+* Status: Experimental
+* Author: Alex Villac�s Lasso <a_villacis@palosanto.com>
+*
+* Based on stir4200 and mcs7780 drivers, with (strange?) differences
+*
+* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+/*
+ * This is my current (2007-04-25) understanding of how this dongle is supposed
+ * to work. This is based on reverse-engineering and examination of the packet
+ * data sent and received by the WinXP driver using USBSnoopy. Feel free to
+ * update here as more of this dongle is known:
+ *
+ * General: Unlike the other USB IrDA dongles, this particular dongle exposes,
+ * not two bulk (in and out) endpoints, but two *interrupt* ones. This dongle,
+ * like the bulk based ones (stir4200.c and mcs7780.c), requires polling in
+ * order to receive data.
+ * Transmission: Just like stir4200, this dongle uses a raw stream of data,
+ * which needs to be wrapped and escaped in a similar way as in stir4200.c.
+ * Reception: Poll-based, as in stir4200. Each read returns the contents of a
+ * 8-byte buffer, of which the first byte (LSB) indicates the number of bytes
+ * (1-7) of valid data contained within the remaining 7 bytes. For example, if
+ * the buffer had the following contents:
+ * 06 ff ff ff c0 01 04 aa
+ * This means that (06) there are 6 bytes of valid data. The byte 0xaa at the
+ * end is garbage (left over from a previous reception) and is discarded.
+ * If a read returns an "impossible" value as the length of valid data (such as
+ * 0x36) in the first byte, then the buffer is uninitialized (as is the case of
+ * first plug-in) and its contents should be discarded. There is currently no
+ * evidence that the top 5 bits of the 1st byte of the buffer can have values
+ * other than 0 once reception begins.
+ * Once valid bytes are collected, the assembled stream is a sequence of
+ * wrapped IrDA frames that is unwrapped and unescaped as in stir4200.c.
+ * BIG FAT WARNING: the dongle does *not* reset the RX buffer in any way after
+ * a successful read from the host, which means that in absence of further
+ * reception, repeated reads from the dongle will return the exact same
+ * contents repeatedly. Attempts to be smart and cache a previous read seem
+ * to result in corrupted packets, so this driver depends on the unwrap logic
+ * to sort out any repeated reads.
+ * Speed change: no commands observed so far to change speed, assumed fixed
+ * 9600bps (SIR).
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+/*
+ * According to lsusb, 0x07c0 is assigned to
+ * "Code Mercenaries Hard- und Software GmbH"
+ */
+#define KING_VENDOR_ID 0x07c0
+#define KING_PRODUCT_ID 0x4200
+
+/* These are the currently known USB ids */
+static struct usb_device_id dongles[] = {
+ /* KingSun Co,Ltd IrDA/USB Bridge */
+ { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, dongles);
+
+#define KINGSUN_MTT 0x07
+
+#define KINGSUN_FIFO_SIZE 4096
+#define KINGSUN_EP_IN 0
+#define KINGSUN_EP_OUT 1
+
+struct kingsun_cb {
+ struct usb_device *usbdev; /* init: probe_irda */
+ struct net_device *netdev; /* network layer */
+ struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct net_device_stats stats; /* network statistics */
+ struct qos_info qos;
+
+ __u8 *in_buf; /* receive buffer */
+ __u8 *out_buf; /* transmit buffer */
+ __u8 max_rx; /* max. atomic read from dongle
+ (usually 8), also size of in_buf */
+ __u8 max_tx; /* max. atomic write to dongle
+ (usually 8) */
+
+ iobuff_t rx_buff; /* receive unwrap state machine */
+ struct timeval rx_time;
+ spinlock_t lock;
+ int receiving;
+
+ __u8 ep_in;
+ __u8 ep_out;
+
+ struct urb *tx_urb;
+ struct urb *rx_urb;
+};
+
+/* Callback transmission routine */
+static void kingsun_send_irq(struct urb *urb)
+{
+ struct kingsun_cb *kingsun = urb->context;
+ struct net_device *netdev = kingsun->netdev;
+
+ /* in process of stopping, just drop data */
+ if (!netif_running(kingsun->netdev)) {
+ err("kingsun_send_irq: Network not running!");
+ return;
+ }
+
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("kingsun_send_irq: urb asynchronously failed - %d",
+ urb->status);
+ }
+ netif_wake_queue(netdev);
+}
+
+/*
+ * Called from net/core when new frame is available.
+ */
+static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct kingsun_cb *kingsun;
+ int wraplen;
+ int ret = 0;
+
+ if (skb == NULL || netdev == NULL)
+ return -EINVAL;
+
+ netif_stop_queue(netdev);
+
+ /* the IRDA wrapping routines don't deal with non linear skb */
+ SKB_LINEAR_ASSERT(skb);
+
+ kingsun = netdev_priv(netdev);
+
+ spin_lock(&kingsun->lock);
+
+ /* Append data to the end of whatever data remains to be transmitted */
+ wraplen = async_wrap_skb(skb,
+ kingsun->out_buf,
+ KINGSUN_FIFO_SIZE);
+
+ /* Calculate how much data can be transmitted in this urb */
+ usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev,
+ usb_sndintpipe(kingsun->usbdev, kingsun->ep_out),
+ kingsun->out_buf, wraplen, kingsun_send_irq,
+ kingsun, 1);
+
+ if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) {
+ err("kingsun_hard_xmit: failed tx_urb submit: %d", ret);
+ switch (ret) {
+ case -ENODEV:
+ case -EPIPE:
+ break;
+ default:
+ kingsun->stats.tx_errors++;
+ netif_start_queue(netdev);
+ }
+ } else {
+ kingsun->stats.tx_packets++;
+ kingsun->stats.tx_bytes += skb->len;
+ }
+
+ dev_kfree_skb(skb);
+ spin_unlock(&kingsun->lock);
+
+ return ret;
+}
+
+/* Receive callback function */
+static void kingsun_rcv_irq(struct urb *urb)
+{
+ struct kingsun_cb *kingsun = urb->context;
+ int ret;
+
+ /* in process of stopping, just drop data */
+ if (!netif_running(kingsun->netdev)) {
+ kingsun->receiving = 0;
+ return;
+ }
+
+ /* unlink, shutdown, unplug, other nasties */
+ if (urb->status != 0) {
+ err("kingsun_rcv_irq: urb asynchronously failed - %d",
+ urb->status);
+ kingsun->receiving = 0;
+ return;
+ }
+
+ if (urb->actual_length == kingsun->max_rx) {
+ __u8 *bytes = urb->transfer_buffer;
+ int i;
+
+ /* The very first byte in the buffer indicates the length of
+ valid data in the read. This byte must be in the range
+ 1..kingsun->max_rx -1 . Values outside this range indicate
+ an uninitialized Rx buffer when the dongle has just been
+ plugged in. */
+ if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) {
+ for (i = 1; i <= bytes[0]; i++) {
+ async_unwrap_char(kingsun->netdev,
+ &kingsun->stats,
+ &kingsun->rx_buff, bytes[i]);
+ }
+ kingsun->netdev->last_rx = jiffies;
+ do_gettimeofday(&kingsun->rx_time);
+ kingsun->receiving =
+ (kingsun->rx_buff.state != OUTSIDE_FRAME)
+ ? 1 : 0;
+ }
+ } else if (urb->actual_length > 0) {
+ err("%s(): Unexpected response length, expected %d got %d",
+ __FUNCTION__, kingsun->max_rx, urb->actual_length);
+ }
+ /* This urb has already been filled in kingsun_net_open */
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/*
+ * Function kingsun_net_open (dev)
+ *
+ * Network device is taken up. Usually this is done by "ifconfig irda0 up"
+ */
+static int kingsun_net_open(struct net_device *netdev)
+{
+ struct kingsun_cb *kingsun = netdev_priv(netdev);
+ int err = -ENOMEM;
+ char hwname[16];
+
+ /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
+ kingsun->receiving = 0;
+
+ /* Initialize for SIR to copy data directly into skb. */
+ kingsun->rx_buff.in_frame = FALSE;
+ kingsun->rx_buff.state = OUTSIDE_FRAME;
+ kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+ kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+ if (!kingsun->rx_buff.skb)
+ goto free_mem;
+
+ skb_reserve(kingsun->rx_buff.skb, 1);
+ kingsun->rx_buff.head = kingsun->rx_buff.skb->data;
+ do_gettimeofday(&kingsun->rx_time);
+
+ kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->rx_urb)
+ goto free_mem;
+
+ kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!kingsun->tx_urb)
+ goto free_mem;
+
+ /*
+ * Now that everything should be initialized properly,
+ * Open new IrLAP layer instance to take care of us...
+ */
+ sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
+ kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
+ if (!kingsun->irlap) {
+ err("kingsun-sir: irlap_open failed");
+ goto free_mem;
+ }
+
+ /* Start first reception */
+ usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev,
+ usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in),
+ kingsun->in_buf, kingsun->max_rx,
+ kingsun_rcv_irq, kingsun, 1);
+ kingsun->rx_urb->status = 0;
+ err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+ if (err) {
+ err("kingsun-sir: first urb-submit failed: %d", err);
+ goto close_irlap;
+ }
+
+ netif_start_queue(netdev);
+
+ /* Situation at this point:
+ - all work buffers allocated
+ - urbs allocated and ready to fill
+ - max rx packet known (in max_rx)
+ - unwrap state machine initialized, in state outside of any frame
+ - receive request in progress
+ - IrLAP layer started, about to hand over packets to send
+ */
+
+ return 0;
+
+ close_irlap:
+ irlap_close(kingsun->irlap);
+ free_mem:
+ if (kingsun->tx_urb) {
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+ }
+ if (kingsun->rx_urb) {
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+ }
+ if (kingsun->rx_buff.skb) {
+ kfree_skb(kingsun->rx_buff.skb);
+ kingsun->rx_buff.skb = NULL;
+ kingsun->rx_buff.head = NULL;
+ }
+ return err;
+}
+
+/*
+ * Function kingsun_net_close (kingsun)
+ *
+ * Network device is taken down. Usually this is done by
+ * "ifconfig irda0 down"
+ */
+static int kingsun_net_close(struct net_device *netdev)
+{
+ struct kingsun_cb *kingsun = netdev_priv(netdev);
+
+ /* Stop transmit processing */
+ netif_stop_queue(netdev);
+
+ /* Mop up receive && transmit urb's */
+ usb_kill_urb(kingsun->tx_urb);
+ usb_kill_urb(kingsun->rx_urb);
+
+ usb_free_urb(kingsun->tx_urb);
+ usb_free_urb(kingsun->rx_urb);
+
+ kingsun->tx_urb = NULL;
+ kingsun->rx_urb = NULL;
+
+ kfree_skb(kingsun->rx_buff.skb);
+ kingsun->rx_buff.skb = NULL;
+ kingsun->rx_buff.head = NULL;
+ kingsun->rx_buff.in_frame = FALSE;
+ kingsun->rx_buff.state = OUTSIDE_FRAME;
+ kingsun->receiving = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (kingsun->irlap)
+ irlap_close(kingsun->irlap);
+
+ kingsun->irlap = NULL;
+
+ return 0;
+}
+
+/*
+ * IOCTLs : Extra out-of-band network commands...
+ */
+static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq,
+ int cmd)
+{
+ struct if_irda_req *irq = (struct if_irda_req *) rq;
+ struct kingsun_cb *kingsun = netdev_priv(netdev);
+ int ret = 0;
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH: /* Set bandwidth */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ /* Check if the device is still there */
+ if (netif_device_present(kingsun->netdev))
+ /* No observed commands for speed change */
+ ret = -EOPNOTSUPP;
+ break;
+
+ case SIOCSMEDIABUSY: /* Set media busy */
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ /* Check if the IrDA stack is still there */
+ if (netif_running(kingsun->netdev))
+ irda_device_set_media_busy(kingsun->netdev, TRUE);
+ break;
+
+ case SIOCGRECEIVING:
+ /* Only approximately true */
+ irq->ifr_receiving = kingsun->receiving;
+ break;
+
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+/*
+ * Get device stats (for /proc/net/dev and ifconfig)
+ */
+static struct net_device_stats *
+kingsun_net_get_stats(struct net_device *netdev)
+{
+ struct kingsun_cb *kingsun = netdev_priv(netdev);
+ return &kingsun->stats;
+}
+
+/*
+ * This routine is called by the USB subsystem for each new device
+ * in the system. We need to check if the device is ours, and in
+ * this case start handling it.
+ */
+static int kingsun_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_host_interface *interface;
+ struct usb_endpoint_descriptor *endpoint;
+
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct kingsun_cb *kingsun = NULL;
+ struct net_device *net = NULL;
+ int ret = -ENOMEM;
+ int pipe, maxp_in, maxp_out;
+ __u8 ep_in;
+ __u8 ep_out;
+
+ /* Check that there really are two interrupt endpoints.
+ Check based on the one in drivers/usb/input/usbmouse.c
+ */
+ interface = intf->cur_altsetting;
+ if (interface->desc.bNumEndpoints != 2) {
+ err("kingsun-sir: expected 2 endpoints, found %d",
+ interface->desc.bNumEndpoints);
+ return -ENODEV;
+ }
+ endpoint = &interface->endpoint[KINGSUN_EP_IN].desc;
+ if (!usb_endpoint_is_int_in(endpoint)) {
+ err("kingsun-sir: endpoint 0 is not interrupt IN");
+ return -ENODEV;
+ }
+
+ ep_in = endpoint->bEndpointAddress;
+ pipe = usb_rcvintpipe(dev, ep_in);
+ maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+ if (maxp_in > 255 || maxp_in <= 1) {
+ err("%s: endpoint 0 has max packet size %d not in range",
+ __FILE__, maxp_in);
+ return -ENODEV;
+ }
+
+ endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc;
+ if (!usb_endpoint_is_int_out(endpoint)) {
+ err("kingsun-sir: endpoint 1 is not interrupt OUT");
+ return -ENODEV;
+ }
+
+ ep_out = endpoint->bEndpointAddress;
+ pipe = usb_sndintpipe(dev, ep_out);
+ maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+ /* Allocate network device container. */
+ net = alloc_irdadev(sizeof(*kingsun));
+ if(!net)
+ goto err_out1;
+
+ SET_MODULE_OWNER(net);
+ SET_NETDEV_DEV(net, &intf->dev);
+ kingsun = netdev_priv(net);
+ kingsun->irlap = NULL;
+ kingsun->tx_urb = NULL;
+ kingsun->rx_urb = NULL;
+ kingsun->ep_in = ep_in;
+ kingsun->ep_out = ep_out;
+ kingsun->in_buf = NULL;
+ kingsun->out_buf = NULL;
+ kingsun->max_rx = (__u8)maxp_in;
+ kingsun->max_tx = (__u8)maxp_out;
+ kingsun->netdev = net;
+ kingsun->usbdev = dev;
+ kingsun->rx_buff.in_frame = FALSE;
+ kingsun->rx_buff.state = OUTSIDE_FRAME;
+ kingsun->rx_buff.skb = NULL;
+ kingsun->receiving = 0;
+ spin_lock_init(&kingsun->lock);
+
+ /* Allocate input buffer */
+ kingsun->in_buf = (__u8 *)kmalloc(kingsun->max_rx, GFP_KERNEL);
+ if (!kingsun->in_buf)
+ goto free_mem;
+
+ /* Allocate output buffer */
+ kingsun->out_buf = (__u8 *)kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL);
+ if (!kingsun->out_buf)
+ goto free_mem;
+
+ printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, "
+ "Vendor: %x, Product: %x\n",
+ dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies(&kingsun->qos);
+
+ /* That's the Rx capability. */
+ kingsun->qos.baud_rate.bits &= IR_9600;
+ kingsun->qos.min_turn_time.bits &= KINGSUN_MTT;
+ irda_qos_bits_to_value(&kingsun->qos);
+
+ /* Override the network functions we need to use */
+ net->hard_start_xmit = kingsun_hard_xmit;
+ net->open = kingsun_net_open;
+ net->stop = kingsun_net_close;
+ net->get_stats = kingsun_net_get_stats;
+ net->do_ioctl = kingsun_net_ioctl;
+
+ ret = register_netdev(net);
+ if (ret != 0)
+ goto free_mem;
+
+ info("IrDA: Registered KingSun/DonShine device %s", net->name);
+
+ usb_set_intfdata(intf, kingsun);
+
+ /* Situation at this point:
+ - all work buffers allocated
+ - urbs not allocated, set to NULL
+ - max rx packet known (in max_rx)
+ - unwrap state machine (partially) initialized, but skb == NULL
+ */
+
+ return 0;
+
+free_mem:
+ if (kingsun->out_buf) kfree(kingsun->out_buf);
+ if (kingsun->in_buf) kfree(kingsun->in_buf);
+ free_netdev(net);
+err_out1:
+ return ret;
+}
+
+/*
+ * The current device is removed, the USB layer tell us to shut it down...
+ */
+static void kingsun_disconnect(struct usb_interface *intf)
+{
+ struct kingsun_cb *kingsun = usb_get_intfdata(intf);
+
+ if (!kingsun)
+ return;
+
+ unregister_netdev(kingsun->netdev);
+
+ /* Mop up receive && transmit urb's */
+ if (kingsun->tx_urb != NULL) {
+ usb_kill_urb(kingsun->tx_urb);
+ usb_free_urb(kingsun->tx_urb);
+ kingsun->tx_urb = NULL;
+ }
+ if (kingsun->rx_urb != NULL) {
+ usb_kill_urb(kingsun->rx_urb);
+ usb_free_urb(kingsun->rx_urb);
+ kingsun->rx_urb = NULL;
+ }
+
+ kfree(kingsun->out_buf);
+ kfree(kingsun->in_buf);
+ free_netdev(kingsun->netdev);
+
+ usb_set_intfdata(intf, NULL);
+}
+
+#ifdef CONFIG_PM
+/* USB suspend, so power off the transmitter/receiver */
+static int kingsun_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct kingsun_cb *kingsun = usb_get_intfdata(intf);
+
+ netif_device_detach(kingsun->netdev);
+ if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb);
+ if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb);
+ return 0;
+}
+
+/* Coming out of suspend, so reset hardware */
+static int kingsun_resume(struct usb_interface *intf)
+{
+ struct kingsun_cb *kingsun = usb_get_intfdata(intf);
+
+ if (kingsun->rx_urb != NULL)
+ usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+ netif_device_attach(kingsun->netdev);
+
+ return 0;
+}
+#endif
+
+/*
+ * USB device callbacks
+ */
+static struct usb_driver irda_driver = {
+ .name = "kingsun-sir",
+ .probe = kingsun_probe,
+ .disconnect = kingsun_disconnect,
+ .id_table = dongles,
+#ifdef CONFIG_PM
+ .suspend = kingsun_suspend,
+ .resume = kingsun_resume,
+#endif
+};
+
+/*
+ * Module insertion
+ */
+static int __init kingsun_init(void)
+{
+ return usb_register(&irda_driver);
+}
+module_init(kingsun_init);
+
+/*
+ * Module removal
+ */
+static void __exit kingsun_cleanup(void)
+{
+ /* Deregister the driver and remove all pending instances */
+ usb_deregister(&irda_driver);
+}
+module_exit(kingsun_cleanup);
+
+MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 1fc7730..2106bec 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -16,11 +16,13 @@
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
+#include <linux/platform_device.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <asm/sgi/hpc3.h>
#include <asm/sgi/ip22.h>
+#include <asm/sgi/seeq.h>
#include "sgiseeq.h"
@@ -92,13 +94,9 @@
struct net_device_stats stats;
- struct net_device *next_module;
spinlock_t tx_lock;
};
-/* A list of all installed seeq devices, for removing the driver module. */
-static struct net_device *root_sgiseeq_dev;
-
static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
{
hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
@@ -624,9 +622,12 @@
#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
-static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom)
+static int __init sgiseeq_probe(struct platform_device *pdev)
{
+ struct sgiseeq_platform_data *pd = pdev->dev.platform_data;
+ struct hpc3_regs *hpcregs = pd->hpc;
struct sgiseeq_init_block *sr;
+ unsigned int irq = pd->irq;
struct sgiseeq_private *sp;
struct net_device *dev;
int err, i;
@@ -637,6 +638,8 @@
err = -ENOMEM;
goto err_out;
}
+
+ platform_set_drvdata(pdev, dev);
sp = netdev_priv(dev);
/* Make private data page aligned */
@@ -648,15 +651,7 @@
}
sp->srings = sr;
-#define EADDR_NVOFS 250
- for (i = 0; i < 3; i++) {
- unsigned short tmp = has_eeprom ?
- ip22_eeprom_read(&hpcregs->eeprom, EADDR_NVOFS / 2+i) :
- ip22_nvram_read(EADDR_NVOFS / 2+i);
-
- dev->dev_addr[2 * i] = tmp >> 8;
- dev->dev_addr[2 * i + 1] = tmp & 0xff;
- }
+ memcpy(dev->dev_addr, pd->mac, ETH_ALEN);
#ifdef DEBUG
gpriv = sp;
@@ -720,9 +715,6 @@
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
- sp->next_module = root_sgiseeq_dev;
- root_sgiseeq_dev = dev;
-
return 0;
err_out_free_page:
@@ -734,43 +726,42 @@
return err;
}
-static int __init sgiseeq_probe(void)
+static void __exit sgiseeq_remove(struct platform_device *pdev)
{
- unsigned int tmp, ret1, ret2 = 0;
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct sgiseeq_private *sp = netdev_priv(dev);
- /* On board adapter on 1st HPC is always present */
- ret1 = sgiseeq_init(hpc3c0, SGI_ENET_IRQ, 0);
- /* Let's see if second HPC is there */
- if (!(ip22_is_fullhouse()) &&
- get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]) == 0) {
- sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 |
- SGIMC_GIOPAR_EXP164 |
- SGIMC_GIOPAR_HPC264;
- hpc3c1->pbus_piocfg[0][0] = 0x3ffff;
- /* interrupt/config register on Challenge S Mezz board */
- hpc3c1->pbus_extregs[0][0] = 0x30;
- ret2 = sgiseeq_init(hpc3c1, SGI_GIO_0_IRQ, 1);
- }
-
- return (ret1 & ret2) ? ret1 : 0;
+ unregister_netdev(dev);
+ free_page((unsigned long) sp->srings);
+ free_netdev(dev);
+ platform_set_drvdata(pdev, NULL);
}
-static void __exit sgiseeq_exit(void)
-{
- struct net_device *next, *dev;
- struct sgiseeq_private *sp;
-
- for (dev = root_sgiseeq_dev; dev; dev = next) {
- sp = (struct sgiseeq_private *) netdev_priv(dev);
- next = sp->next_module;
- unregister_netdev(dev);
- free_page((unsigned long) sp->srings);
- free_netdev(dev);
+static struct platform_driver sgiseeq_driver = {
+ .probe = sgiseeq_probe,
+ .remove = __devexit_p(sgiseeq_remove),
+ .driver = {
+ .name = "sgiseeq"
}
+};
+
+static int __init sgiseeq_module_init(void)
+{
+ if (platform_driver_register(&sgiseeq_driver)) {
+ printk(KERN_ERR "Driver registration failed\n");
+ return -ENODEV;
+ }
+
+ return 0;
}
-module_init(sgiseeq_probe);
-module_exit(sgiseeq_exit);
+static void __exit sgiseeq_module_exit(void)
+{
+ platform_driver_unregister(&sgiseeq_driver);
+}
+
+module_init(sgiseeq_module_init);
+module_exit(sgiseeq_module_exit);
MODULE_DESCRIPTION("SGI Seeq 8003 driver");
MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 1759baa..95ce8f4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -246,7 +246,7 @@
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
- || M32R || ATARI || POWERPC)
+ || M32R || ATARI || POWERPC || MIPS)
help
Say "yes" here to get direct support for the real time clock
found in every PC or ACPI-based system, and some other boards.
@@ -397,7 +397,7 @@
config RTC_DRV_RS5C313
tristate "Ricoh RS5C313"
- depends on RTC_CLASS && BROKEN
+ depends on RTC_CLASS && SH_LANDISK
help
If you say yes here you get support for the Ricoh RS5C313 RTC chips.
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c
index 9d6de37..66eb133 100644
--- a/drivers/rtc/rtc-rs5c313.c
+++ b/drivers/rtc/rtc-rs5c313.c
@@ -126,7 +126,7 @@
static unsigned char rs5c313_read_data(void)
{
int i;
- unsigned char data;
+ unsigned char data = 0;
for (i = 0; i < 8; i++) {
ndelay(700);
@@ -194,7 +194,7 @@
return;
}
-static inline unsigned char rs5c313_read_cntreg(unsigned char addr)
+static inline unsigned char rs5c313_read_cntreg(void)
{
return rs5c313_read_reg(RS5C313_ADDR_CNTREG);
}
@@ -212,7 +212,9 @@
static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
int data;
+ int cnt;
+ cnt = 0;
while (1) {
RS5C313_CEENABLE; /* CE:H */
@@ -225,6 +227,10 @@
RS5C313_CEDISABLE;
ndelay(700); /* CE:L */
+ if (cnt++ > 100) {
+ dev_err(dev, "%s: timeout error\n", __FUNCTION__);
+ return -EIO;
+ }
}
data = rs5c313_read_reg(RS5C313_ADDR_SEC);
@@ -266,7 +272,9 @@
static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
int data;
+ int cnt;
+ cnt = 0;
/* busy check. */
while (1) {
RS5C313_CEENABLE; /* CE:H */
@@ -279,6 +287,11 @@
RS5C313_MISCOP;
RS5C313_CEDISABLE;
ndelay(700); /* CE:L */
+
+ if (cnt++ > 100) {
+ dev_err(dev, "%s: timeout error\n", __FUNCTION__);
+ return -EIO;
+ }
}
data = BIN2BCD(tm->tm_sec);
@@ -317,6 +330,7 @@
static void rs5c313_check_xstp_bit(void)
{
struct rtc_time tm;
+ int cnt;
RS5C313_CEENABLE; /* CE:H */
if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) {
@@ -326,12 +340,16 @@
rs5c313_write_cntreg(0x07);
/* busy check. */
- while (rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)
+ for (cnt = 0; cnt < 100; cnt++) {
+ if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY))
+ break;
RS5C313_MISCOP;
+ }
memset(&tm, 0, sizeof(struct rtc_time));
tm.tm_mday = 1;
- tm.tm_mon = 1;
+ tm.tm_mon = 1 - 1;
+ tm.tm_year = 2000 - 1900;
rs5c313_rtc_set_time(NULL, &tm);
printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to "
@@ -356,7 +374,7 @@
platform_set_drvdata(pdev, rtc);
- return err;
+ return 0;
}
static int __devexit rs5c313_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index a15752b..eef8275 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -6,87 +6,49 @@
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
* Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu)
* Copyright (C) 2001 Florian Lohoff (flo@rfc822.org)
- * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
*
* (In all truth, Jed Schimmel wrote all this code.)
*/
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
+
+#undef DEBUG
+
#include <linux/delay.h>
#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/spinlock.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sgialib.h>
-#include <asm/sgi/sgi.h>
-#include <asm/sgi/mc.h>
#include <asm/sgi/hpc3.h>
#include <asm/sgi/ip22.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <asm/sgi/wd.h>
#include "scsi.h"
-#include <scsi/scsi_host.h>
#include "wd33c93.h"
-#include <linux/stat.h>
-
-#if 0
-#define DPRINTK(args...) printk(args)
-#else
-#define DPRINTK(args...)
-#endif
-
-#define HDATA(ptr) ((struct ip22_hostdata *)((ptr)->hostdata))
-
struct ip22_hostdata {
struct WD33C93_hostdata wh;
struct hpc_data {
dma_addr_t dma;
- void * cpu;
+ void *cpu;
} hd;
};
+#define host_to_hostdata(host) ((struct ip22_hostdata *)((host)->hostdata))
+
struct hpc_chunk {
struct hpc_dma_desc desc;
u32 _padding; /* align to quadword boundary */
};
-struct Scsi_Host *sgiwd93_host;
-struct Scsi_Host *sgiwd93_host1;
-
-/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
-static inline void write_wd33c93_count(const wd33c93_regs regs,
- unsigned long value)
-{
- *regs.SASR = WD_TRANSFER_COUNT_MSB;
- mb();
- *regs.SCMD = ((value >> 16) & 0xff);
- *regs.SCMD = ((value >> 8) & 0xff);
- *regs.SCMD = ((value >> 0) & 0xff);
- mb();
-}
-
-static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
-{
- unsigned long value;
-
- *regs.SASR = WD_TRANSFER_COUNT_MSB;
- mb();
- value = ((*regs.SCMD & 0xff) << 16);
- value |= ((*regs.SCMD & 0xff) << 8);
- value |= ((*regs.SCMD & 0xff) << 0);
- mb();
- return value;
-}
-
static irqreturn_t sgiwd93_intr(int irq, void *dev_id)
{
- struct Scsi_Host * host = (struct Scsi_Host *) dev_id;
+ struct Scsi_Host * host = dev_id;
unsigned long flags;
spin_lock_irqsave(host->host_lock, flags);
@@ -131,12 +93,12 @@
static int dma_setup(struct scsi_cmnd *cmd, int datainp)
{
- struct ip22_hostdata *hdata = HDATA(cmd->device->host);
+ struct ip22_hostdata *hdata = host_to_hostdata(cmd->device->host);
struct hpc3_scsiregs *hregs =
(struct hpc3_scsiregs *) cmd->device->host->base;
struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu;
- DPRINTK("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp);
+ pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp);
hdata->wh.dma_dir = datainp;
@@ -151,7 +113,7 @@
fill_hpc_entries(hcp, cmd, datainp);
- DPRINTK(" HPCGO\n");
+ pr_debug(" HPCGO\n");
/* Start up the HPC. */
hregs->ndptr = hdata->hd.dma;
@@ -166,7 +128,7 @@
static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
int status)
{
- struct ip22_hostdata *hdata = HDATA(instance);
+ struct ip22_hostdata *hdata = host_to_hostdata(instance);
struct hpc3_scsiregs *hregs;
if (!SCpnt)
@@ -174,7 +136,7 @@
hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base;
- DPRINTK("dma_stop: status<%d> ", status);
+ pr_debug("dma_stop: status<%d> ", status);
/* First stop the HPC and flush it's FIFO. */
if (hdata->wh.dma_dir) {
@@ -186,7 +148,7 @@
dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual,
SCpnt->sc_data_direction);
- DPRINTK("\n");
+ pr_debug("\n");
}
void sgiwd93_reset(unsigned long base)
@@ -216,96 +178,6 @@
hcp->desc.pnext = hd->dma;
}
-static struct Scsi_Host * __init sgiwd93_setup_scsi(
- struct scsi_host_template *SGIblows, int unit, int irq,
- struct hpc3_scsiregs *hregs, unsigned char *wdregs)
-{
- struct ip22_hostdata *hdata;
- struct Scsi_Host *host;
- wd33c93_regs regs;
-
- host = scsi_register(SGIblows, sizeof(struct ip22_hostdata));
- if (!host)
- return NULL;
-
- host->base = (unsigned long) hregs;
- host->irq = irq;
-
- hdata = HDATA(host);
- hdata->hd.cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &hdata->hd.dma,
- GFP_KERNEL);
- if (!hdata->hd.cpu) {
- printk(KERN_WARNING "sgiwd93: Could not allocate memory for "
- "host %d buffer.\n", unit);
- goto out_unregister;
- }
- init_hpc_chain(&hdata->hd);
-
- regs.SASR = wdregs + 3;
- regs.SCMD = wdregs + 7;
-
- wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
-
- if (hdata->wh.no_sync == 0xff)
- hdata->wh.no_sync = 0;
-
- if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) {
- printk(KERN_WARNING "sgiwd93: Could not register irq %d "
- "for host %d.\n", irq, unit);
- goto out_free;
- }
- return host;
-
-out_free:
- dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
- wd33c93_release();
-
-out_unregister:
- scsi_unregister(host);
-
- return NULL;
-}
-
-static int __init sgiwd93_detect(struct scsi_host_template *SGIblows)
-{
- int found = 0;
-
- SGIblows->proc_name = "SGIWD93";
- sgiwd93_host = sgiwd93_setup_scsi(SGIblows, 0, SGI_WD93_0_IRQ,
- &hpc3c0->scsi_chan0,
- (unsigned char *)hpc3c0->scsi0_ext);
- if (sgiwd93_host)
- found++;
-
- /* Set up second controller on the Indigo2 */
- if (ip22_is_fullhouse()) {
- sgiwd93_host1 = sgiwd93_setup_scsi(SGIblows, 1, SGI_WD93_1_IRQ,
- &hpc3c0->scsi_chan1,
- (unsigned char *)hpc3c0->scsi1_ext);
- if (sgiwd93_host1)
- found++;
- }
-
- return found;
-}
-
-static int sgiwd93_release(struct Scsi_Host *instance)
-{
- struct ip22_hostdata *hdata = HDATA(instance);
- int irq = 0;
-
- if (sgiwd93_host && sgiwd93_host == instance)
- irq = SGI_WD93_0_IRQ;
- else if (sgiwd93_host1 && sgiwd93_host1 == instance)
- irq = SGI_WD93_1_IRQ;
-
- free_irq(irq, sgiwd93_intr);
- dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
- wd33c93_release();
-
- return 1;
-}
-
static int sgiwd93_bus_reset(struct scsi_cmnd *cmd)
{
/* FIXME perform bus-specific reset */
@@ -325,11 +197,10 @@
* arguments not with pointers. So this is going to blow up beautyfully
* on 64-bit systems with memory outside the compat address spaces.
*/
-static struct scsi_host_template driver_template = {
+static struct scsi_host_template sgiwd93_template = {
+ .module = THIS_MODULE,
.proc_name = "SGIWD93",
.name = "SGI WD93",
- .detect = sgiwd93_detect,
- .release = sgiwd93_release,
.queuecommand = wd33c93_queuecommand,
.eh_abort_handler = wd33c93_abort,
.eh_bus_reset_handler = sgiwd93_bus_reset,
@@ -340,4 +211,109 @@
.cmd_per_lun = 8,
.use_clustering = DISABLE_CLUSTERING,
};
-#include "scsi_module.c"
+
+static int __init sgiwd93_probe(struct platform_device *pdev)
+{
+ struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
+ unsigned char *wdregs = pd->wdregs;
+ struct hpc3_scsiregs *hregs = pd->hregs;
+ struct ip22_hostdata *hdata;
+ struct Scsi_Host *host;
+ wd33c93_regs regs;
+ unsigned int unit = pd->unit;
+ unsigned int irq = pd->irq;
+ int err;
+
+ host = scsi_host_alloc(&sgiwd93_template, sizeof(struct ip22_hostdata));
+ if (!host) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ host->base = (unsigned long) hregs;
+ host->irq = irq;
+
+ hdata = host_to_hostdata(host);
+ hdata->hd.cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+ &hdata->hd.dma, GFP_KERNEL);
+ if (!hdata->hd.cpu) {
+ printk(KERN_WARNING "sgiwd93: Could not allocate memory for "
+ "host %d buffer.\n", unit);
+ err = -ENOMEM;
+ goto out_put;
+ }
+
+ init_hpc_chain(&hdata->hd);
+
+ regs.SASR = wdregs + 3;
+ regs.SCMD = wdregs + 7;
+
+ wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
+
+ if (hdata->wh.no_sync == 0xff)
+ hdata->wh.no_sync = 0;
+
+ err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host);
+ if (err) {
+ printk(KERN_WARNING "sgiwd93: Could not register irq %d "
+ "for host %d.\n", irq, unit);
+ goto out_free;
+ }
+
+ platform_set_drvdata(pdev, host);
+
+ err = scsi_add_host(host, NULL);
+ if (err)
+ goto out_irq;
+
+ scsi_scan_host(host);
+
+ return 0;
+
+out_irq:
+ free_irq(irq, host);
+out_free:
+ dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
+out_put:
+ scsi_host_put(host);
+out:
+
+ return err;
+}
+
+static void __exit sgiwd93_remove(struct platform_device *pdev)
+{
+ struct Scsi_Host *host = platform_get_drvdata(pdev);
+ struct ip22_hostdata *hdata = (struct ip22_hostdata *) host->hostdata;
+ struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
+
+ scsi_remove_host(host);
+ free_irq(pd->irq, host);
+ dma_free_coherent(&pdev->dev, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
+ scsi_host_put(host);
+}
+
+static struct platform_driver sgiwd93_driver = {
+ .probe = sgiwd93_probe,
+ .remove = __devexit_p(sgiwd93_remove),
+ .driver = {
+ .name = "sgiwd93"
+ }
+};
+
+static int __init sgiwd93_module_init(void)
+{
+ return platform_driver_register(&sgiwd93_driver);
+}
+
+static void __exit sgiwd93_module_exit(void)
+{
+ return platform_driver_unregister(&sgiwd93_driver);
+}
+
+module_init(sgiwd93_module_init);
+module_exit(sgiwd93_module_exit);
+
+MODULE_DESCRIPTION("SGI WD33C93 driver");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7c9d37f..5e3f748 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -107,6 +107,13 @@
This enables using the Freescale iMX SPI controller in master
mode.
+config SPI_MPC52xx_PSC
+ tristate "Freescale MPC52xx PSC SPI controller"
+ depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
+ help
+ This enables using the Freescale MPC52xx Programmable Serial
+ Controller in master SPI mode.
+
config SPI_MPC83xx
tristate "Freescale MPC83xx SPI controller"
depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 624b636..5788d86 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@
obj-$(CONFIG_SPI_IMX) += spi_imx.o
obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
+obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o
obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o
obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o
obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
new file mode 100644
index 0000000..052359f
--- /dev/null
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -0,0 +1,654 @@
+/*
+ * MPC52xx SPC in SPI mode driver.
+ *
+ * Maintainer: Dragos Carp
+ *
+ * Copyright (C) 2006 TOPTICA Photonics AG.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+
+#if defined(CONFIG_PPC_MERGE)
+#include <asm/of_platform.h>
+#else
+#include <linux/platform_device.h>
+#endif
+
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+
+#define MCLK 20000000 /* PSC port MClk in hz */
+
+struct mpc52xx_psc_spi {
+ /* fsl_spi_platform data */
+ void (*activate_cs)(u8, u8);
+ void (*deactivate_cs)(u8, u8);
+ u32 sysclk;
+
+ /* driver internal data */
+ struct mpc52xx_psc __iomem *psc;
+ unsigned int irq;
+ u8 bits_per_word;
+ u8 busy;
+
+ struct workqueue_struct *workqueue;
+ struct work_struct work;
+
+ struct list_head queue;
+ spinlock_t lock;
+
+ struct completion done;
+};
+
+/* controller state */
+struct mpc52xx_psc_spi_cs {
+ int bits_per_word;
+ int speed_hz;
+};
+
+/* set clock freq, clock ramp, bits per work
+ * if t is NULL then reset the values to the default values
+ */
+static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+
+ cs->speed_hz = (t && t->speed_hz)
+ ? t->speed_hz : spi->max_speed_hz;
+ cs->bits_per_word = (t && t->bits_per_word)
+ ? t->bits_per_word : spi->bits_per_word;
+ cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
+ return 0;
+}
+
+static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
+{
+ struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+ struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+ struct mpc52xx_psc __iomem *psc = mps->psc;
+ u32 sicr;
+ u16 ccr;
+
+ sicr = in_be32(&psc->sicr);
+
+ /* Set clock phase and polarity */
+ if (spi->mode & SPI_CPHA)
+ sicr |= 0x00001000;
+ else
+ sicr &= ~0x00001000;
+ if (spi->mode & SPI_CPOL)
+ sicr |= 0x00002000;
+ else
+ sicr &= ~0x00002000;
+
+ if (spi->mode & SPI_LSB_FIRST)
+ sicr |= 0x10000000;
+ else
+ sicr &= ~0x10000000;
+ out_be32(&psc->sicr, sicr);
+
+ /* Set clock frequency and bits per word
+ * Because psc->ccr is defined as 16bit register instead of 32bit
+ * just set the lower byte of BitClkDiv
+ */
+ ccr = in_be16(&psc->ccr);
+ ccr &= 0xFF00;
+ if (cs->speed_hz)
+ ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
+ else /* by default SPI Clk 1MHz */
+ ccr |= (MCLK / 1000000 - 1) & 0xFF;
+ out_be16(&psc->ccr, ccr);
+ mps->bits_per_word = cs->bits_per_word;
+
+ if (mps->activate_cs)
+ mps->activate_cs(spi->chip_select,
+ (spi->mode & SPI_CS_HIGH) ? 1 : 0);
+}
+
+static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi)
+{
+ struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+
+ if (mps->deactivate_cs)
+ mps->deactivate_cs(spi->chip_select,
+ (spi->mode & SPI_CS_HIGH) ? 1 : 0);
+}
+
+#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
+/* wake up when 80% fifo full */
+#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100)
+
+static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+ struct mpc52xx_psc __iomem *psc = mps->psc;
+ unsigned rb = 0; /* number of bytes receieved */
+ unsigned sb = 0; /* number of bytes sent */
+ unsigned char *rx_buf = (unsigned char *)t->rx_buf;
+ unsigned char *tx_buf = (unsigned char *)t->tx_buf;
+ unsigned rfalarm;
+ unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
+ unsigned recv_at_once;
+ unsigned bpw = mps->bits_per_word / 8;
+
+ if (!t->tx_buf && !t->rx_buf && t->len)
+ return -EINVAL;
+
+ /* enable transmiter/receiver */
+ out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+ while (rb < t->len) {
+ if (t->len - rb > MPC52xx_PSC_BUFSIZE) {
+ rfalarm = MPC52xx_PSC_RFALARM;
+ } else {
+ send_at_once = t->len - sb;
+ rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb);
+ }
+
+ dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
+ if (tx_buf) {
+ for (; send_at_once; sb++, send_at_once--) {
+ /* set EOF flag */
+ if (mps->bits_per_word
+ && (sb + 1) % bpw == 0)
+ out_8(&psc->ircr2, 0x01);
+ out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]);
+ }
+ } else {
+ for (; send_at_once; sb++, send_at_once--) {
+ /* set EOF flag */
+ if (mps->bits_per_word
+ && ((sb + 1) % bpw) == 0)
+ out_8(&psc->ircr2, 0x01);
+ out_8(&psc->mpc52xx_psc_buffer_8, 0);
+ }
+ }
+
+
+ /* enable interupts and wait for wake up
+ * if just one byte is expected the Rx FIFO genererates no
+ * FFULL interrupt, so activate the RxRDY interrupt
+ */
+ out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+ if (t->len - rb == 1) {
+ out_8(&psc->mode, 0);
+ } else {
+ out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
+ out_be16(&psc->rfalarm, rfalarm);
+ }
+ out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
+ wait_for_completion(&mps->done);
+ recv_at_once = in_be16(&psc->rfnum);
+ dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
+
+ send_at_once = recv_at_once;
+ if (rx_buf) {
+ for (; recv_at_once; rb++, recv_at_once--)
+ rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8);
+ } else {
+ for (; recv_at_once; rb++, recv_at_once--)
+ in_8(&psc->mpc52xx_psc_buffer_8);
+ }
+ }
+ /* disable transmiter/receiver */
+ out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+ return 0;
+}
+
+static void mpc52xx_psc_spi_work(struct work_struct *work)
+{
+ struct mpc52xx_psc_spi *mps =
+ container_of(work, struct mpc52xx_psc_spi, work);
+
+ spin_lock_irq(&mps->lock);
+ mps->busy = 1;
+ while (!list_empty(&mps->queue)) {
+ struct spi_message *m;
+ struct spi_device *spi;
+ struct spi_transfer *t = NULL;
+ unsigned cs_change;
+ int status;
+
+ m = container_of(mps->queue.next, struct spi_message, queue);
+ list_del_init(&m->queue);
+ spin_unlock_irq(&mps->lock);
+
+ spi = m->spi;
+ cs_change = 1;
+ status = 0;
+ list_for_each_entry (t, &m->transfers, transfer_list) {
+ if (t->bits_per_word || t->speed_hz) {
+ status = mpc52xx_psc_spi_transfer_setup(spi, t);
+ if (status < 0)
+ break;
+ }
+
+ if (cs_change)
+ mpc52xx_psc_spi_activate_cs(spi);
+ cs_change = t->cs_change;
+
+ status = mpc52xx_psc_spi_transfer_rxtx(spi, t);
+ if (status)
+ break;
+ m->actual_length += t->len;
+
+ if (t->delay_usecs)
+ udelay(t->delay_usecs);
+
+ if (cs_change)
+ mpc52xx_psc_spi_deactivate_cs(spi);
+ }
+
+ m->status = status;
+ m->complete(m->context);
+
+ if (status || !cs_change)
+ mpc52xx_psc_spi_deactivate_cs(spi);
+
+ mpc52xx_psc_spi_transfer_setup(spi, NULL);
+
+ spin_lock_irq(&mps->lock);
+ }
+ mps->busy = 0;
+ spin_unlock_irq(&mps->lock);
+}
+
+static int mpc52xx_psc_spi_setup(struct spi_device *spi)
+{
+ struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+ struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+ unsigned long flags;
+
+ if (spi->bits_per_word%8)
+ return -EINVAL;
+
+ if (!cs) {
+ cs = kzalloc(sizeof *cs, GFP_KERNEL);
+ if (!cs)
+ return -ENOMEM;
+ spi->controller_state = cs;
+ }
+
+ cs->bits_per_word = spi->bits_per_word;
+ cs->speed_hz = spi->max_speed_hz;
+
+ spin_lock_irqsave(&mps->lock, flags);
+ if (!mps->busy)
+ mpc52xx_psc_spi_deactivate_cs(spi);
+ spin_unlock_irqrestore(&mps->lock, flags);
+
+ return 0;
+}
+
+static int mpc52xx_psc_spi_transfer(struct spi_device *spi,
+ struct spi_message *m)
+{
+ struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+ unsigned long flags;
+
+ m->actual_length = 0;
+ m->status = -EINPROGRESS;
+
+ spin_lock_irqsave(&mps->lock, flags);
+ list_add_tail(&m->queue, &mps->queue);
+ queue_work(mps->workqueue, &mps->work);
+ spin_unlock_irqrestore(&mps->lock, flags);
+
+ return 0;
+}
+
+static void mpc52xx_psc_spi_cleanup(struct spi_device *spi)
+{
+ kfree(spi->controller_state);
+}
+
+static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
+{
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_gpio __iomem *gpio;
+ struct mpc52xx_psc __iomem *psc = mps->psc;
+ u32 ul;
+ u32 mclken_div;
+ int ret = 0;
+
+#if defined(CONFIG_PPC_MERGE)
+ cdm = mpc52xx_find_and_map("mpc52xx-cdm");
+ gpio = mpc52xx_find_and_map("mpc52xx-gpio");
+#else
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+#endif
+ if (!cdm || !gpio) {
+ printk(KERN_ERR "Error mapping CDM/GPIO\n");
+ ret = -EFAULT;
+ goto unmap_regs;
+ }
+
+ /* default sysclk is 512MHz */
+ mclken_div = 0x8000 |
+ (((mps->sysclk ? mps->sysclk : 512000000) / MCLK) & 0x1FF);
+
+ switch (psc_id) {
+ case 1:
+ ul = in_be32(&gpio->port_config);
+ ul &= 0xFFFFFFF8;
+ ul |= 0x00000006;
+ out_be32(&gpio->port_config, ul);
+ out_be16(&cdm->mclken_div_psc1, mclken_div);
+ ul = in_be32(&cdm->clk_enables);
+ ul |= 0x00000020;
+ out_be32(&cdm->clk_enables, ul);
+ break;
+ case 2:
+ ul = in_be32(&gpio->port_config);
+ ul &= 0xFFFFFF8F;
+ ul |= 0x00000060;
+ out_be32(&gpio->port_config, ul);
+ out_be16(&cdm->mclken_div_psc2, mclken_div);
+ ul = in_be32(&cdm->clk_enables);
+ ul |= 0x00000040;
+ out_be32(&cdm->clk_enables, ul);
+ break;
+ case 3:
+ ul = in_be32(&gpio->port_config);
+ ul &= 0xFFFFF0FF;
+ ul |= 0x00000600;
+ out_be32(&gpio->port_config, ul);
+ out_be16(&cdm->mclken_div_psc3, mclken_div);
+ ul = in_be32(&cdm->clk_enables);
+ ul |= 0x00000080;
+ out_be32(&cdm->clk_enables, ul);
+ break;
+ case 6:
+ ul = in_be32(&gpio->port_config);
+ ul &= 0xFF8FFFFF;
+ ul |= 0x00700000;
+ out_be32(&gpio->port_config, ul);
+ out_be16(&cdm->mclken_div_psc6, mclken_div);
+ ul = in_be32(&cdm->clk_enables);
+ ul |= 0x00000010;
+ out_be32(&cdm->clk_enables, ul);
+ break;
+ default:
+ ret = -EINVAL;
+ goto unmap_regs;
+ }
+
+ /* Reset the PSC into a known state */
+ out_8(&psc->command, MPC52xx_PSC_RST_RX);
+ out_8(&psc->command, MPC52xx_PSC_RST_TX);
+ out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+ /* Disable interrupts, interrupts are based on alarm level */
+ out_be16(&psc->mpc52xx_psc_imr, 0);
+ out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+ out_8(&psc->rfcntl, 0);
+ out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
+
+ /* Configure 8bit codec mode as a SPI master and use EOF flags */
+ /* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
+ out_be32(&psc->sicr, 0x0180C800);
+ out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
+
+ /* Set 2ms DTL delay */
+ out_8(&psc->ctur, 0x00);
+ out_8(&psc->ctlr, 0x84);
+
+ mps->bits_per_word = 8;
+
+unmap_regs:
+ if (cdm)
+ iounmap(cdm);
+ if (gpio)
+ iounmap(gpio);
+
+ return ret;
+}
+
+static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
+{
+ struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id;
+ struct mpc52xx_psc __iomem *psc = mps->psc;
+
+ /* disable interrupt and wake up the work queue */
+ if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) {
+ out_be16(&psc->mpc52xx_psc_imr, 0);
+ complete(&mps->done);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+/* bus_num is used only for the case dev->platform_data == NULL */
+static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
+ u32 size, unsigned int irq, s16 bus_num)
+{
+ struct fsl_spi_platform_data *pdata = dev->platform_data;
+ struct mpc52xx_psc_spi *mps;
+ struct spi_master *master;
+ int ret;
+
+ if (pdata == NULL)
+ return -ENODEV;
+
+ master = spi_alloc_master(dev, sizeof *mps);
+ if (master == NULL)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, master);
+ mps = spi_master_get_devdata(master);
+
+ mps->irq = irq;
+ if (pdata == NULL) {
+ dev_warn(dev, "probe called without platform data, no "
+ "(de)activate_cs function will be called\n");
+ mps->activate_cs = NULL;
+ mps->deactivate_cs = NULL;
+ mps->sysclk = 0;
+ master->bus_num = bus_num;
+ master->num_chipselect = 255;
+ } else {
+ mps->activate_cs = pdata->activate_cs;
+ mps->deactivate_cs = pdata->deactivate_cs;
+ mps->sysclk = pdata->sysclk;
+ master->bus_num = pdata->bus_num;
+ master->num_chipselect = pdata->max_chipselect;
+ }
+ master->setup = mpc52xx_psc_spi_setup;
+ master->transfer = mpc52xx_psc_spi_transfer;
+ master->cleanup = mpc52xx_psc_spi_cleanup;
+
+ mps->psc = ioremap(regaddr, size);
+ if (!mps->psc) {
+ dev_err(dev, "could not ioremap I/O port range\n");
+ ret = -EFAULT;
+ goto free_master;
+ }
+
+ ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi",
+ mps);
+ if (ret)
+ goto free_master;
+
+ ret = mpc52xx_psc_spi_port_config(master->bus_num, mps);
+ if (ret < 0)
+ goto free_irq;
+
+ spin_lock_init(&mps->lock);
+ init_completion(&mps->done);
+ INIT_WORK(&mps->work, mpc52xx_psc_spi_work);
+ INIT_LIST_HEAD(&mps->queue);
+
+ mps->workqueue = create_singlethread_workqueue(
+ master->cdev.dev->bus_id);
+ if (mps->workqueue == NULL) {
+ ret = -EBUSY;
+ goto free_irq;
+ }
+
+ ret = spi_register_master(master);
+ if (ret < 0)
+ goto unreg_master;
+
+ return ret;
+
+unreg_master:
+ destroy_workqueue(mps->workqueue);
+free_irq:
+ free_irq(mps->irq, mps);
+free_master:
+ if (mps->psc)
+ iounmap(mps->psc);
+ spi_master_put(master);
+
+ return ret;
+}
+
+static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
+{
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
+
+ flush_workqueue(mps->workqueue);
+ destroy_workqueue(mps->workqueue);
+ spi_unregister_master(master);
+ free_irq(mps->irq, mps);
+ if (mps->psc)
+ iounmap(mps->psc);
+
+ return 0;
+}
+
+#if !defined(CONFIG_PPC_MERGE)
+static int __init mpc52xx_psc_spi_probe(struct platform_device *dev)
+{
+ switch(dev->id) {
+ case 1:
+ case 2:
+ case 3:
+ case 6:
+ return mpc52xx_psc_spi_do_probe(&dev->dev,
+ MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)),
+ MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev)
+{
+ return mpc52xx_psc_spi_do_remove(&dev->dev);
+}
+
+static struct platform_driver mpc52xx_psc_spi_platform_driver = {
+ .remove = __exit_p(mpc52xx_psc_spi_remove),
+ .driver = {
+ .name = "mpc52xx-psc-spi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mpc52xx_psc_spi_init(void)
+{
+ return platform_driver_probe(&mpc52xx_psc_spi_platform_driver,
+ mpc52xx_psc_spi_probe);
+}
+module_init(mpc52xx_psc_spi_init);
+
+static void __exit mpc52xx_psc_spi_exit(void)
+{
+ platform_driver_unregister(&mpc52xx_psc_spi_platform_driver);
+}
+module_exit(mpc52xx_psc_spi_exit);
+
+#else /* defined(CONFIG_PPC_MERGE) */
+
+static int __init mpc52xx_psc_spi_of_probe(struct of_device *op,
+ const struct of_device_id *match)
+{
+ const u32 *regaddr_p;
+ u64 regaddr64, size64;
+ s16 id = -1;
+
+ regaddr_p = of_get_address(op->node, 0, &size64, NULL);
+ if (!regaddr_p) {
+ printk(KERN_ERR "Invalid PSC address\n");
+ return -EINVAL;
+ }
+ regaddr64 = of_translate_address(op->node, regaddr_p);
+
+ if (op->dev.platform_data == NULL) {
+ struct device_node *np;
+ int i = 0;
+
+ for_each_node_by_type(np, "spi") {
+ if (of_find_device_by_node(np) == op) {
+ id = i;
+ break;
+ }
+ i++;
+ }
+ }
+
+ return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
+ irq_of_parse_and_map(op->node, 0), id);
+}
+
+static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op)
+{
+ return mpc52xx_psc_spi_do_remove(&op->dev);
+}
+
+static struct of_device_id mpc52xx_psc_spi_of_match[] = {
+ { .type = "spi", .compatible = "mpc52xx-psc-spi", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
+
+static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
+ .owner = THIS_MODULE,
+ .name = "mpc52xx-psc-spi",
+ .match_table = mpc52xx_psc_spi_of_match,
+ .probe = mpc52xx_psc_spi_of_probe,
+ .remove = __exit_p(mpc52xx_psc_spi_of_remove),
+ .driver = {
+ .name = "mpc52xx-psc-spi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mpc52xx_psc_spi_init(void)
+{
+ return of_register_platform_driver(&mpc52xx_psc_spi_of_driver);
+}
+module_init(mpc52xx_psc_spi_init);
+
+static void __exit mpc52xx_psc_spi_exit(void)
+{
+ of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver);
+}
+module_exit(mpc52xx_psc_spi_exit);
+
+#endif /* defined(CONFIG_PPC_MERGE) */
+
+MODULE_AUTHOR("Dragos Carp");
+MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f544388..eebcb70 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -748,6 +748,22 @@
working with S1D13806). Product specs at
<http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
+config FB_ATMEL
+ tristate "AT91/AT32 LCD Controller support"
+ depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32)
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ This enables support for the AT91/AT32 LCD Controller.
+
+config FB_INTSRAM
+ bool "Frame Buffer in internal SRAM"
+ depends on FB_ATMEL && ARCH_AT91SAM9261
+ help
+ Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
+ to let frame buffer in external SDRAM.
+
config FB_NVIDIA
tristate "nVidia Framebuffer Support"
depends on FB && PCI
@@ -780,6 +796,15 @@
independently validate video mode parameters, you should say Y
here.
+config FB_NVIDIA_DEBUG
+ bool "Lots of debug output"
+ depends on FB_NVIDIA
+ default n
+ help
+ Say Y here if you want the nVidia driver to output all sorts
+ of debugging information to provide to the maintainer when
+ something goes wrong.
+
config FB_NVIDIA_BACKLIGHT
bool "Support for backlight control"
depends on FB_NVIDIA
@@ -819,7 +844,7 @@
here.
config FB_RIVA_DEBUG
- bool "Lots of debug output from Riva(nVidia) driver"
+ bool "Lots of debug output"
depends on FB_RIVA
default n
help
@@ -1431,8 +1456,11 @@
and ICS 5342 RAMDAC.
config FB_PM3
- tristate "Permedia3 support"
- depends on FB && PCI && BROKEN
+ tristate "Permedia3 support (EXPERIMENTAL)"
+ depends on FB && PCI && EXPERIMENTAL
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
help
This is the frame buffer device driver for the 3DLabs Permedia3
chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 0b70567..bd8b052 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -87,6 +87,7 @@
obj-$(CONFIG_FB_SA1100) += sa1100fb.o
obj-$(CONFIG_FB_HIT) += hitfb.o
obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o
+obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
obj-$(CONFIG_FB_PVR2) += pvr2fb.o
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
new file mode 100644
index 0000000..e1d5bd0
--- /dev/null
+++ b/drivers/video/atmel_lcdfb.c
@@ -0,0 +1,752 @@
+/*
+ * Driver for AT91/AT32 LCD Controller
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+
+#include <video/atmel_lcdc.h>
+
+#define lcdc_readl(sinfo, reg) __raw_readl((sinfo)->mmio+(reg))
+#define lcdc_writel(sinfo, reg, val) __raw_writel((val), (sinfo)->mmio+(reg))
+
+/* configurable parameters */
+#define ATMEL_LCDC_CVAL_DEFAULT 0xc8
+#define ATMEL_LCDC_DMA_BURST_LEN 8
+
+#if defined(CONFIG_ARCH_AT91SAM9263)
+#define ATMEL_LCDC_FIFO_SIZE 2048
+#else
+#define ATMEL_LCDC_FIFO_SIZE 512
+#endif
+
+#if defined(CONFIG_ARCH_AT91)
+#define ATMEL_LCDFB_FBINFO_DEFAULT FBINFO_DEFAULT
+
+static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+ struct fb_var_screeninfo *var)
+{
+
+}
+#elif defined(CONFIG_AVR32)
+#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
+ | FBINFO_PARTIAL_PAN_OK \
+ | FBINFO_HWACCEL_XPAN \
+ | FBINFO_HWACCEL_YPAN)
+
+static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+ struct fb_var_screeninfo *var)
+{
+ u32 dma2dcfg;
+ u32 pixeloff;
+
+ pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
+
+ dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
+ dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
+ lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
+
+ /* Update configuration */
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
+ lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
+ | ATMEL_LCDC_DMAUPDT);
+}
+#endif
+
+
+static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+};
+
+
+static void atmel_lcdfb_update_dma(struct fb_info *info,
+ struct fb_var_screeninfo *var)
+{
+ struct atmel_lcdfb_info *sinfo = info->par;
+ struct fb_fix_screeninfo *fix = &info->fix;
+ unsigned long dma_addr;
+
+ dma_addr = (fix->smem_start + var->yoffset * fix->line_length
+ + var->xoffset * var->bits_per_pixel / 8);
+
+ dma_addr &= ~3UL;
+
+ /* Set framebuffer DMA base address and pixel offset */
+ lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
+
+ atmel_lcdfb_update_dma2d(sinfo, var);
+}
+
+static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
+{
+ struct fb_info *info = sinfo->info;
+
+ dma_free_writecombine(info->device, info->fix.smem_len,
+ info->screen_base, info->fix.smem_start);
+}
+
+/**
+ * atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
+ * @sinfo: the frame buffer to allocate memory for
+ */
+static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
+{
+ struct fb_info *info = sinfo->info;
+ struct fb_var_screeninfo *var = &info->var;
+
+ info->fix.smem_len = (var->xres_virtual * var->yres_virtual
+ * ((var->bits_per_pixel + 7) / 8));
+
+ info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
+ (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
+
+ if (!info->screen_base) {
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/**
+ * atmel_lcdfb_check_var - Validates a var passed in.
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Checks to see if the hardware supports the state requested by
+ * var passed in. This function does not alter the hardware
+ * state!!! This means the data stored in struct fb_info and
+ * struct atmel_lcdfb_info do not change. This includes the var
+ * inside of struct fb_info. Do NOT change these. This function
+ * can be called on its own if we intent to only test a mode and
+ * not actually set it. The stuff in modedb.c is a example of
+ * this. If the var passed in is slightly off by what the
+ * hardware can support then we alter the var PASSED in to what
+ * we can do. If the hardware doesn't support mode change a
+ * -EINVAL will be returned by the upper layers. You don't need
+ * to implement this function then. If you hardware doesn't
+ * support changing the resolution then this function is not
+ * needed. In this case the driver would just provide a var that
+ * represents the static state the screen is in.
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct device *dev = info->device;
+ struct atmel_lcdfb_info *sinfo = info->par;
+ unsigned long clk_value_khz;
+
+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+ dev_dbg(dev, "%s:\n", __func__);
+ dev_dbg(dev, " resolution: %ux%u\n", var->xres, var->yres);
+ dev_dbg(dev, " pixclk: %lu KHz\n", PICOS2KHZ(var->pixclock));
+ dev_dbg(dev, " bpp: %u\n", var->bits_per_pixel);
+ dev_dbg(dev, " clk: %lu KHz\n", clk_value_khz);
+
+ if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) {
+ dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
+ return -EINVAL;
+ }
+
+ /* Force same alignment for each line */
+ var->xres = (var->xres + 3) & ~3UL;
+ var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
+
+ var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
+ var->transp.offset = var->transp.length = 0;
+ var->xoffset = var->yoffset = 0;
+
+ switch (var->bits_per_pixel) {
+ case 2:
+ case 4:
+ case 8:
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length
+ = var->bits_per_pixel;
+ break;
+ case 15:
+ case 16:
+ var->red.offset = 0;
+ var->green.offset = 5;
+ var->blue.offset = 10;
+ var->red.length = var->green.length = var->blue.length = 5;
+ break;
+ case 24:
+ case 32:
+ var->red.offset = 0;
+ var->green.offset = 8;
+ var->blue.offset = 16;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ default:
+ dev_err(dev, "color depth %d not supported\n",
+ var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * atmel_lcdfb_set_par - Alters the hardware state.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Using the fb_var_screeninfo in fb_info we set the resolution
+ * of the this particular framebuffer. This function alters the
+ * par AND the fb_fix_screeninfo stored in fb_info. It doesn't
+ * not alter var in fb_info since we are using that data. This
+ * means we depend on the data in var inside fb_info to be
+ * supported by the hardware. atmel_lcdfb_check_var is always called
+ * before atmel_lcdfb_set_par to ensure this. Again if you can't
+ * change the resolution you don't need this function.
+ *
+ */
+static int atmel_lcdfb_set_par(struct fb_info *info)
+{
+ struct atmel_lcdfb_info *sinfo = info->par;
+ unsigned long value;
+ unsigned long clk_value_khz;
+
+ dev_dbg(info->device, "%s:\n", __func__);
+ dev_dbg(info->device, " * resolution: %ux%u (%ux%u virtual)\n",
+ info->var.xres, info->var.yres,
+ info->var.xres_virtual, info->var.yres_virtual);
+
+ /* Turn off the LCD controller and the DMA controller */
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+
+ if (info->var.bits_per_pixel <= 8)
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ else
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+ info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8);
+
+ /* Re-initialize the DMA engine... */
+ dev_dbg(info->device, " * update DMA engine\n");
+ atmel_lcdfb_update_dma(info, &info->var);
+
+ /* ...set frame size and burst length = 8 words (?) */
+ value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
+ value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
+ lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
+
+ /* Now, the LCDC core... */
+
+ /* Set pixel clock */
+ clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+ value = clk_value_khz / PICOS2KHZ(info->var.pixclock);
+
+ if (clk_value_khz % PICOS2KHZ(info->var.pixclock))
+ value++;
+
+ value = (value / 2) - 1;
+
+ if (value <= 0) {
+ dev_notice(info->device, "Bypassing pixel clock divider\n");
+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
+ } else
+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET);
+
+ /* Initialize control register 2 */
+ value = sinfo->default_lcdcon2;
+
+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+ value |= ATMEL_LCDC_INVLINE_INVERTED;
+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+ value |= ATMEL_LCDC_INVFRAME_INVERTED;
+
+ switch (info->var.bits_per_pixel) {
+ case 1: value |= ATMEL_LCDC_PIXELSIZE_1; break;
+ case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
+ case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
+ case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
+ case 15: /* fall through */
+ case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
+ case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
+ case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
+ default: BUG(); break;
+ }
+ dev_dbg(info->device, " * LCDCON2 = %08lx\n", value);
+ lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
+
+ /* Vertical timing */
+ value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
+ value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
+ value |= info->var.lower_margin;
+ dev_dbg(info->device, " * LCDTIM1 = %08lx\n", value);
+ lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
+
+ /* Horizontal timing */
+ value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
+ value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
+ value |= (info->var.left_margin - 1);
+ dev_dbg(info->device, " * LCDTIM2 = %08lx\n", value);
+ lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
+
+ /* Display size */
+ value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
+ value |= info->var.yres - 1;
+ lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
+
+ /* FIFO Threshold: Use formula from data sheet */
+ value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
+ lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
+
+ /* Toggle LCD_MODE every frame */
+ lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
+
+ /* Disable all interrupts */
+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+
+ /* Set contrast */
+ value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE;
+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value);
+ lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
+ /* ...wait for DMA engine to become idle... */
+ while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+ msleep(10);
+
+ dev_dbg(info->device, " * re-enable DMA engine\n");
+ /* ...and enable it with updated configuration */
+ lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+
+ dev_dbg(info->device, " * re-enable LCDC core\n");
+ lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+ (sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+
+ dev_dbg(info->device, " * DONE\n");
+
+ return 0;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+/**
+ * atmel_lcdfb_setcolreg - Optional function. Sets a color register.
+ * @regno: Which register in the CLUT we are programming
+ * @red: The red value which can be up to 16 bits wide
+ * @green: The green value which can be up to 16 bits wide
+ * @blue: The blue value which can be up to 16 bits wide.
+ * @transp: If supported the alpha value which can be up to 16 bits wide.
+ * @info: frame buffer info structure
+ *
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude which needs to be scaled in this function for the hardware.
+ * Things to take into consideration are how many color registers, if
+ * any, are supported with the current color visual. With truecolor mode
+ * no color palettes are supported. Here a psuedo palette is created
+ * which we store the value in pseudo_palette in struct fb_info. For
+ * pseudocolor mode we have a limited color palette. To deal with this
+ * we can program what color is displayed for a particular pixel value.
+ * DirectColor is similar in that we can program each color field. If
+ * we have a static colormap we don't need to implement this function.
+ *
+ * Returns negative errno on error, or zero on success. In an
+ * ideal world, this would have been the case, but as it turns
+ * out, the other drivers return 1 on failure, so that's what
+ * we're going to do.
+ */
+static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
+ unsigned int green, unsigned int blue,
+ unsigned int transp, struct fb_info *info)
+{
+ struct atmel_lcdfb_info *sinfo = info->par;
+ unsigned int val;
+ u32 *pal;
+ int ret = 1;
+
+ if (info->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green
+ + 7471 * blue) >> 16;
+
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ if (regno < 16) {
+ pal = info->pseudo_palette;
+
+ val = chan_to_field(red, &info->var.red);
+ val |= chan_to_field(green, &info->var.green);
+ val |= chan_to_field(blue, &info->var.blue);
+
+ pal[regno] = val;
+ ret = 0;
+ }
+ break;
+
+ case FB_VISUAL_PSEUDOCOLOR:
+ if (regno < 256) {
+ val = ((red >> 11) & 0x001f);
+ val |= ((green >> 6) & 0x03e0);
+ val |= ((blue >> 1) & 0x7c00);
+
+ /*
+ * TODO: intensity bit. Maybe something like
+ * ~(red[10] ^ green[10] ^ blue[10]) & 1
+ */
+
+ lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
+ ret = 0;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ dev_dbg(info->device, "%s\n", __func__);
+
+ atmel_lcdfb_update_dma(info, var);
+
+ return 0;
+}
+
+static struct fb_ops atmel_lcdfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = atmel_lcdfb_check_var,
+ .fb_set_par = atmel_lcdfb_set_par,
+ .fb_setcolreg = atmel_lcdfb_setcolreg,
+ .fb_pan_display = atmel_lcdfb_pan_display,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
+{
+ struct fb_info *info = dev_id;
+ struct atmel_lcdfb_info *sinfo = info->par;
+ u32 status;
+
+ status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
+ lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
+ return IRQ_HANDLED;
+}
+
+static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
+{
+ struct fb_info *info = sinfo->info;
+ int ret = 0;
+
+ memset_io(info->screen_base, 0, info->fix.smem_len);
+ info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
+
+ dev_info(info->device,
+ "%luKiB frame buffer at %08lx (mapped at %p)\n",
+ (unsigned long)info->fix.smem_len / 1024,
+ (unsigned long)info->fix.smem_start,
+ info->screen_base);
+
+ /* Allocate colormap */
+ ret = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (ret < 0)
+ dev_err(info->device, "Alloc color map failed\n");
+
+ return ret;
+}
+
+static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
+{
+ if (sinfo->bus_clk)
+ clk_enable(sinfo->bus_clk);
+ clk_enable(sinfo->lcdc_clk);
+}
+
+static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
+{
+ if (sinfo->bus_clk)
+ clk_disable(sinfo->bus_clk);
+ clk_disable(sinfo->lcdc_clk);
+}
+
+
+static int __init atmel_lcdfb_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct fb_info *info;
+ struct atmel_lcdfb_info *sinfo;
+ struct atmel_lcdfb_info *pdata_sinfo;
+ struct resource *regs = NULL;
+ struct resource *map = NULL;
+ int ret;
+
+ dev_dbg(dev, "%s BEGIN\n", __func__);
+
+ ret = -ENOMEM;
+ info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
+ if (!info) {
+ dev_err(dev, "cannot allocate memory\n");
+ goto out;
+ }
+
+ sinfo = info->par;
+
+ if (dev->platform_data) {
+ pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
+ sinfo->default_bpp = pdata_sinfo->default_bpp;
+ sinfo->default_dmacon = pdata_sinfo->default_dmacon;
+ sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
+ sinfo->default_monspecs = pdata_sinfo->default_monspecs;
+ sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
+ sinfo->guard_time = pdata_sinfo->guard_time;
+ } else {
+ dev_err(dev, "cannot get default configuration\n");
+ goto free_info;
+ }
+ sinfo->info = info;
+ sinfo->pdev = pdev;
+
+ strcpy(info->fix.id, sinfo->pdev->name);
+ info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
+ info->pseudo_palette = sinfo->pseudo_palette;
+ info->fbops = &atmel_lcdfb_ops;
+
+ memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
+ info->fix = atmel_lcdfb_fix;
+
+ /* Enable LCDC Clocks */
+ if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) {
+ sinfo->bus_clk = clk_get(dev, "hck1");
+ if (IS_ERR(sinfo->bus_clk)) {
+ ret = PTR_ERR(sinfo->bus_clk);
+ goto free_info;
+ }
+ }
+ sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
+ if (IS_ERR(sinfo->lcdc_clk)) {
+ ret = PTR_ERR(sinfo->lcdc_clk);
+ goto put_bus_clk;
+ }
+ atmel_lcdfb_start_clock(sinfo);
+
+ ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
+ info->monspecs.modedb_len, info->monspecs.modedb,
+ sinfo->default_bpp);
+ if (!ret) {
+ dev_err(dev, "no suitable video mode found\n");
+ goto stop_clk;
+ }
+
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_err(dev, "resources unusable\n");
+ ret = -ENXIO;
+ goto stop_clk;
+ }
+
+ sinfo->irq_base = platform_get_irq(pdev, 0);
+ if (sinfo->irq_base < 0) {
+ dev_err(dev, "unable to get irq\n");
+ ret = sinfo->irq_base;
+ goto stop_clk;
+ }
+
+ /* Initialize video memory */
+ map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (map) {
+ /* use a pre-allocated memory buffer */
+ info->fix.smem_start = map->start;
+ info->fix.smem_len = map->end - map->start + 1;
+ if (!request_mem_region(info->fix.smem_start,
+ info->fix.smem_len, pdev->name)) {
+ ret = -EBUSY;
+ goto stop_clk;
+ }
+
+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+ if (!info->screen_base)
+ goto release_intmem;
+ } else {
+ /* alocate memory buffer */
+ ret = atmel_lcdfb_alloc_video_memory(sinfo);
+ if (ret < 0) {
+ dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
+ goto stop_clk;
+ }
+ }
+
+ /* LCDC registers */
+ info->fix.mmio_start = regs->start;
+ info->fix.mmio_len = regs->end - regs->start + 1;
+
+ if (!request_mem_region(info->fix.mmio_start,
+ info->fix.mmio_len, pdev->name)) {
+ ret = -EBUSY;
+ goto free_fb;
+ }
+
+ sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
+ if (!sinfo->mmio) {
+ dev_err(dev, "cannot map LCDC registers\n");
+ goto release_mem;
+ }
+
+ /* interrupt */
+ ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
+ if (ret) {
+ dev_err(dev, "request_irq failed: %d\n", ret);
+ goto unmap_mmio;
+ }
+
+ ret = atmel_lcdfb_init_fbinfo(sinfo);
+ if (ret < 0) {
+ dev_err(dev, "init fbinfo failed: %d\n", ret);
+ goto unregister_irqs;
+ }
+
+ /*
+ * This makes sure that our colour bitfield
+ * descriptors are correctly initialised.
+ */
+ atmel_lcdfb_check_var(&info->var, info);
+
+ ret = fb_set_var(info, &info->var);
+ if (ret) {
+ dev_warn(dev, "unable to set display parameters\n");
+ goto free_cmap;
+ }
+
+ dev_set_drvdata(dev, info);
+
+ /*
+ * Tell the world that we're ready to go
+ */
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ dev_err(dev, "failed to register framebuffer device: %d\n", ret);
+ goto free_cmap;
+ }
+
+ /* Power up the LCDC screen */
+ if (sinfo->atmel_lcdfb_power_control)
+ sinfo->atmel_lcdfb_power_control(1);
+
+ dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n",
+ info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
+
+ return 0;
+
+
+free_cmap:
+ fb_dealloc_cmap(&info->cmap);
+unregister_irqs:
+ free_irq(sinfo->irq_base, info);
+unmap_mmio:
+ iounmap(sinfo->mmio);
+release_mem:
+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+free_fb:
+ if (map)
+ iounmap(info->screen_base);
+ else
+ atmel_lcdfb_free_video_memory(sinfo);
+
+release_intmem:
+ if (map)
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
+stop_clk:
+ atmel_lcdfb_stop_clock(sinfo);
+ clk_put(sinfo->lcdc_clk);
+put_bus_clk:
+ if (sinfo->bus_clk)
+ clk_put(sinfo->bus_clk);
+free_info:
+ framebuffer_release(info);
+out:
+ dev_dbg(dev, "%s FAILED\n", __func__);
+ return ret;
+}
+
+static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct atmel_lcdfb_info *sinfo = info->par;
+
+ if (!sinfo)
+ return 0;
+
+ if (sinfo->atmel_lcdfb_power_control)
+ sinfo->atmel_lcdfb_power_control(0);
+ unregister_framebuffer(info);
+ atmel_lcdfb_stop_clock(sinfo);
+ clk_put(sinfo->lcdc_clk);
+ if (sinfo->bus_clk)
+ clk_put(sinfo->bus_clk);
+ fb_dealloc_cmap(&info->cmap);
+ free_irq(sinfo->irq_base, info);
+ iounmap(sinfo->mmio);
+ release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+ if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
+ iounmap(info->screen_base);
+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
+ } else {
+ atmel_lcdfb_free_video_memory(sinfo);
+ }
+
+ dev_set_drvdata(dev, NULL);
+ framebuffer_release(info);
+
+ return 0;
+}
+
+static struct platform_driver atmel_lcdfb_driver = {
+ .remove = __exit_p(atmel_lcdfb_remove),
+ .driver = {
+ .name = "atmel_lcdfb",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init atmel_lcdfb_init(void)
+{
+ return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
+}
+
+static void __exit atmel_lcdfb_exit(void)
+{
+ platform_driver_unregister(&atmel_lcdfb_driver);
+}
+
+module_init(atmel_lcdfb_init);
+module_exit(atmel_lcdfb_exit);
+
+MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@rfo.atmel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index aa3935d..63b85bf 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -19,13 +19,6 @@
Say Y.
-# if [ "$CONFIG_PCI" = "y" -a "$CONFIG_VGA_CONSOLE" = "y" ]; then
-# bool ' Allow VGA on any bus?' CONFIG_VGA_HOSE
-# if [ "$CONFIG_VGA_HOSE" = "y" ]; then
-# define_bool CONFIG_DUMMY_CONSOLE y
-# fi
-# fi
-
config VGACON_SOFT_SCROLLBACK
bool "Enable Scrollback Buffer in System RAM"
depends on VGA_CONSOLE
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index c627955..aff11bb 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -149,7 +149,9 @@
pll = NV_RD32(par->PMC, 0x4024);
M = pll & 0xFF;
N = (pll >> 8) & 0xFF;
- if (((par->Chipset & 0xfff0) == 0x0290) || ((par->Chipset & 0xfff0) == 0x0390) || ((par->Chipset & 0xfff0) == 0x02E0)) {
+ if (((par->Chipset & 0xfff0) == 0x0290) ||
+ ((par->Chipset & 0xfff0) == 0x0390) ||
+ ((par->Chipset & 0xfff0) == 0x02E0)) {
MB = 1;
NB = 1;
} else {
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index f85edf0..41f6365 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -37,7 +37,6 @@
#include "nv_proto.h"
#include "nv_dma.h"
-#undef CONFIG_FB_NVIDIA_DEBUG
#ifdef CONFIG_FB_NVIDIA_DEBUG
#define NVTRACE printk
#else
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 1ac5264..ab5e668 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -204,17 +204,6 @@
}
#endif
-static void wait_pm2(struct pm2fb_par* par) {
-
- WAIT_FIFO(par, 1);
- pm2_WR(par, PM2R_SYNC, 0);
- mb();
- do {
- while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0);
- rmb();
- } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
-}
-
/*
* partial products for the supported horizontal resolutions.
*/
@@ -1050,13 +1039,30 @@
return 0;
}
+static int pm2fb_sync(struct fb_info *info)
+{
+ struct pm2fb_par *par = info->par;
+
+ WAIT_FIFO(par, 1);
+ pm2_WR(par, PM2R_SYNC, 0);
+ mb();
+ do {
+ while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0)
+ udelay(10);
+ rmb();
+ } while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
+
+ return 0;
+}
+
/*
* block operation. copy=0: rectangle fill, copy=1: rectangle copy.
*/
-static void pm2fb_block_op(struct pm2fb_par* par, int copy,
+static void pm2fb_block_op(struct fb_info* info, int copy,
s32 xsrc, s32 ysrc,
s32 x, s32 y, s32 w, s32 h,
u32 color) {
+ struct pm2fb_par *par = info->par;
if (!w || !h)
return;
@@ -1076,13 +1082,11 @@
(x<xsrc ? PM2F_INCREASE_X : 0) |
(y<ysrc ? PM2F_INCREASE_Y : 0) |
(copy ? 0 : PM2F_RENDER_FASTFILL));
- wait_pm2(par);
}
static void pm2fb_fillrect (struct fb_info *info,
const struct fb_fillrect *region)
{
- struct pm2fb_par *par = info->par;
struct fb_fillrect modded;
int vxres, vyres;
u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
@@ -1116,7 +1120,7 @@
color |= color << 16;
if(info->var.bits_per_pixel != 24)
- pm2fb_block_op(par, 0, 0, 0,
+ pm2fb_block_op(info, 0, 0, 0,
modded.dx, modded.dy,
modded.width, modded.height, color);
else
@@ -1126,7 +1130,6 @@
static void pm2fb_copyarea(struct fb_info *info,
const struct fb_copyarea *area)
{
- struct pm2fb_par *par = info->par;
struct fb_copyarea modded;
u32 vxres, vyres;
@@ -1156,7 +1159,7 @@
if(modded.dy + modded.height > vyres)
modded.height = vyres - modded.dy;
- pm2fb_block_op(par, 1, modded.sx, modded.sy,
+ pm2fb_block_op(info, 1, modded.sx, modded.sy,
modded.dx, modded.dy,
modded.width, modded.height, 0);
}
@@ -1177,6 +1180,7 @@
.fb_fillrect = pm2fb_fillrect,
.fb_copyarea = pm2fb_copyarea,
.fb_imageblit = cfb_imageblit,
+ .fb_sync = pm2fb_sync,
};
/*
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index bd787e8..6c4dfcb0 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -1,55 +1,25 @@
/*
* linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device
- *
- * Copyright (C) 2001 Romain Dolbeau <dolbeau@irisa.fr>
+ *
+ * Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>.
+ *
+ * Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl>
+ * based on pm2fb.c
+ *
* Based on code written by:
- * Sven Luther, <luther@dpt-info.u-strasbg.fr>
- * Alan Hourihane, <alanh@fairlite.demon.co.uk>
- * Russell King, <rmk@arm.linux.org.uk>
+ * Sven Luther, <luther@dpt-info.u-strasbg.fr>
+ * Alan Hourihane, <alanh@fairlite.demon.co.uk>
+ * Russell King, <rmk@arm.linux.org.uk>
* Based on linux/drivers/video/skeletonfb.c:
* Copyright (C) 1997 Geert Uytterhoeven
* Based on linux/driver/video/pm2fb.c:
- * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
- * $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
- *
- * CHANGELOG:
- * Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
- * Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
- * Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
- * Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings.
- * Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes.
- * Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix.
- * Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG.
- * Wed Jun 20 11:13:08 MET DST 2001, v 1.4.5: Fixed missing blinking cursor in 8bpp, code cleaning, memory erase IOCTL.
- * Mon Jun 18 16:00:27 CEST 2001, v 1.4.4: Depth 12 (RGBA 4444) support, code cleaning.
- * Fri Jun 15 13:53:01 CEST 2001, v 1.4.3: Removed warnings, depth 15 support, add 'depth' option.
- * Thu Jun 14 10:13:52 MET DST 2001, v 1.4.2: Fixed depth switching bug, preliminary 15bpp (RGB5551) support.
- * Thu Apr 12 11:16:45 MET DST 2001, v 1.4.1B: Doc updates.
- * Fri Apr 6 11:12:53 MET DST 2001, v 1.4.1: Configure.help, minor cleanup
- * Thu Mar 29 10:56:50 MET DST 2001, v 1.4.0: Module & module options support (note: linux patch changed, 2.2.19 added).
- * Thu Mar 15 15:30:31 MET 2001, v 1.3.2: Fixed mirroring bug on little-endian.
- * Wed Mar 14 21:25:54 CET 2001, v 1.3.1: Fixed bug in BlockMove (_bmov).
- * Tue Mar 13 10:53:19 MET 2001, v 1.3.0: Character drawing hardware support (in all width between 1 and 16), fixes.
- * Thu Mar 8 10:20:16 MET 2001, v 1.2.2: Better J2000 support, "font:" option.
- * Tue Mar 6 21:25:04 CET 2001, v 1.2.1: Better acceleration support.
- * Mon Mar 5 21:54:17 CET 2001, v 1.2.0: Partial acceleration support (clear & bmove)
- * Mon Mar 5 12:52:15 CET 2001, v 1.1.3: Big pan_display fix.
- * Sun Mar 4 22:21:50 CET 2001, v 1.1.2: (numerous) bug fixes.
- * Fri Mar 2 15:54:07 CET 2001, v 1.1.1: Might have Appian J2000 support, resource mangement in 2.4
- * Wed Feb 28 18:21:35 CET 2001, v 1.1.0: Might have multiple boards support (added, but not yest tested)
- * Tue Feb 27 17:31:12 CET 2001, v 1.0.6: fixes boot-time mode select, add more default mode
- * Tue Feb 27 14:01:36 CET 2001, v 1.0.5: fixes (1.0.4 was broken for 2.2), cleaning up
- * Mon Feb 26 23:17:36 CET 2001, v 1.0.4: preliminary 2.4.x support, dropped (useless on pm3) partial product, more OF fix
- * Mon Feb 26 20:59:05 CET 2001, v 1.0.3: No more shadow register (and wasted memory), endianess fix, use OF-preset resolution by default
- * Wed Feb 21 22:09:30 CET 2001, v 1.0.2: Code cleaning for future multiboard support, better OF support, bugs fix
- * Wed Feb 21 19:58:56 CET 2001, v 1.0.1: OpenFirmware support, fixed memory detection, better debug support, code cleaning
- * Wed Feb 21 14:47:06 CET 2001, v 1.0.0: First working version
*/
#include <linux/module.h>
@@ -58,856 +28,155 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/delay.h>
-#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/ctype.h>
-#include <video/fbcon.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon-cfb2.h>
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb24.h>
-#include <video/fbcon-cfb32.h>
#include <video/pm3fb.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#ifdef CONFIG_FB_OF
-#include <asm/prom.h>
+#if !defined(CONFIG_PCI)
+#error "Only generic PCI cards supported."
#endif
-/* ************************************* */
-/* ***** The various "global" data ***** */
-/* ************************************* */
+#undef PM3FB_MASTER_DEBUG
+#ifdef PM3FB_MASTER_DEBUG
+#define DPRINTK(a,b...) printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif
-/* those will need a rework for multiple board support */
-/* Driver name */
-static const char permedia3_name[16] = "Permedia3";
+/*
+ * Driver data
+ */
+static char *mode_option __devinitdata;
-/* the fb_par struct, mandatory */
-struct pm3fb_par {
- u32 pixclock; /* pixclock in KHz */
+/*
+ * If your driver supports multiple boards, you should make the
+ * below data types arrays, or allocate them dynamically (using kmalloc()).
+ */
- u32 width; /* width of virtual screen */
- u32 height; /* height of virtual screen */
-
- u32 hsstart; /* horiz. sync start */
- u32 hsend; /* horiz. sync end */
- u32 hbend; /* horiz. blank end (also gate end) */
- u32 htotal; /* total width (w/ sync & blank) */
-
- u32 vsstart; /* vert. sync start */
- u32 vsend; /* vert. sync end */
- u32 vbend; /* vert. blank end */
- u32 vtotal; /* total height (w/ sync & blank) */
-
- u32 stride; /* screen stride */
- u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */
- /* NOTE : unlike other pm3 stuff above, stored *after* shiftbpp. don't ask */
- u32 depth; /* screen depth (8, 12, 15, 16 or 32) */
- u32 video; /* video control (hsync,vsync) */
+/*
+ * This structure defines the hardware state of the graphics card. Normally
+ * you place this in a header file in linux/include/video. This file usually
+ * also includes register information. That allows other driver subsystems
+ * and userland applications the ability to use the same header file to
+ * avoid duplicate work and easy porting of software.
+ */
+struct pm3_par {
+ unsigned char __iomem *v_regs;/* virtual address of p_regs */
+ u32 video; /* video flags before blanking */
+ u32 base; /* screen base (xoffset+yoffset) in 128 bits unit */
+ u32 palette[16];
};
-/* memory timings */
-struct pm3fb_timings
+/*
+ * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
+ * if we don't use modedb. If we do use modedb see pm3fb_init how to use it
+ * to get a fb_var_screeninfo. Otherwise define a default var as well.
+ */
+static struct fb_fix_screeninfo pm3fb_fix __devinitdata = {
+ .id = "Permedia3",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .xpanstep = 1,
+ .ypanstep = 1,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+};
+
+/*
+ * Utility functions
+ */
+
+static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off)
{
- unsigned long caps;
- unsigned long timings;
- unsigned long control;
- unsigned long refresh;
- unsigned long powerdown;
-};
-typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result;
-#define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1)
-#define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE }
-
-/* the fb_info struct, mandatory */
-struct pm3fb_info {
- struct fb_info_gen gen;
- unsigned long board_num; /* internal board number */
- unsigned long use_current;
- struct pm3fb_par *current_par;
- struct pci_dev *dev; /* PCI device */
- unsigned long board_type; /* index in the cardbase */
- unsigned char *fb_base; /* framebuffer memory base */
- u32 fb_size; /* framebuffer memory size */
- unsigned char *p_fb; /* physical address of frame buffer */
- unsigned char *v_fb; /* virtual address of frame buffer */
- unsigned char *pIOBase; /* physical address of registers region, must be rg_base or rg_base+PM2_REGS_SIZE depending on the host endianness */
- unsigned char *vIOBase; /* address of registers after ioremap() */
- struct {
- u8 transp;
- u8 red;
- u8 green;
- u8 blue;
- } palette[256];
- union {
-#ifdef FBCON_HAS_CFB16
- u16 cmap12[16]; /* RGBA 4444 */
- u16 cmap15[16]; /* RGBA 5551 */
- u16 cmap16[16]; /* RGBA 5650 */
-#endif
-#ifdef FBCON_HAS_CFB32
- u32 cmap32[16];
-#endif
- } cmap;
- struct pm3fb_timings memt;
-};
-
-/* regular resolution database*/
-static struct {
- char name[16];
- struct pm3fb_par user_mode;
-} mode_base[] __initdata = {
- {
- "default-800x600", {
- 49500, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625,
- 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}}, {
- "1024x768-74", {
- 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
- 806, 1024, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}}, {
- "1024x768-74-32", {
- 78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
- 806, 1024, 0, 32,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_32BIT}},
-/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/
- {
- "SGI1600SW", {
- 108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32,
- 1056, 1600, 0, 8,
- PM3VideoControl_ENABLE|
- PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW|
- PM3VideoControl_PIXELSIZE_32BIT}},
-/* ##### auto-generated mode, by fbtimings2pm3 */
-/* Generated mode : "640x480-60" */
- {
- "640x480-60", {
- 25174, 640, 480, 16, 112, 160, 800, 10, 12, 45,
- 525, 640, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-72" */
- {
- "640x480-72", {
- 31199, 640, 480, 24, 64, 192, 832, 9, 12, 40, 520,
- 640, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-75" */
- {
- "640x480-75", {
- 31499, 640, 480, 16, 80, 200, 840, 1, 4, 20, 500,
- 640, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-90" */
- {
- "640x480-90", {
- 39909, 640, 480, 32, 72, 192, 832, 25, 39, 53, 533,
- 640, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-100" */
- {
- "640x480-100", {
- 44899, 640, 480, 32, 160, 208, 848, 22, 34, 51,
- 531, 640, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-48-lace" */
-/* INTERLACED NOT SUPPORTED
- {"800x600-48-lace", {35999, 800, 600, 80, 208, 264, 1064, 11, 23, 102, 702, 800, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}},
- INTERLACED NOT SUPPORTED */
-/* Generated mode : "800x600-56" */
- {
- "800x600-56", {
- 35999, 800, 600, 24, 96, 224, 1024, 1, 3, 25, 625,
- 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-60" */
- {
- "800x600-60", {
- 40000, 800, 600, 40, 168, 256, 1056, 1, 5, 28, 628,
- 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-70" */
- {
- "800x600-70", {
- 44899, 800, 600, 24, 168, 208, 1008, 9, 21, 36,
- 636, 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-72" */
- {
- "800x600-72", {
- 50000, 800, 600, 56, 176, 240, 1040, 37, 43, 66,
- 666, 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-75" */
- {
- "800x600-75", {
- 49497, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625,
- 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-90" */
- {
- "800x600-90", {
- 56637, 800, 600, 8, 72, 192, 992, 8, 19, 35, 635,
- 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-100", from /etc/fb.modes */
-/* DISABLED, hsstart == 0
- {
- "800x600-100", {
- 67499, 800, 600, 0, 64, 280, 1080, 7, 11, 25, 625,
- 800, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-*/
-/* Generated mode : "800x600-100", from ??? */
- {
- "800x600-100", {
- 69650, 800, 600, 64, 128, 288, 1088, 4, 10, 40, 640, 800, 0, 8,
- PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW|
- PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-43-lace" */
-/* INTERLACED NOT SUPPORTED
- {"1024x768-43-lace", {44899, 1024, 768, 8, 184, 240, 1264, 1, 9, 49, 817, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}},
- INTERLACED NOT SUPPORTED */
-/* Generated mode : "1024x768-60" */
- {
- "1024x768-60", {
- 64998, 1024, 768, 24, 160, 320, 1344, 3, 9, 38,
- 806, 1024, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-70" */
- {
- "1024x768-70", {
- 74996, 1024, 768, 24, 160, 304, 1328, 3, 9, 38,
- 806, 1024, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-72" */
- {
- "1024x768-72", {
- 74996, 10224, 768, 24, 160, 264, 10488, 3, 9, 38,
- 806, 10224, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-75" */
- {
- "1024x768-75", {
- 78746, 1024, 768, 16, 112, 288, 1312, 1, 4, 32,
- 800, 1024, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-90" */
- {
- "1024x768-90", {
- 100000, 1024, 768, 0, 96, 288, 1312, 21, 36, 77,
- 845, 1024, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-100", from /etc/fb.modes */
-/* DISABLED, vsstart == 0
- {
- "1024x768-100", {
- 109998, 1024, 768, 0, 88, 368, 1392, 0, 8, 24, 792,
- 1024, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-*/
-/* Generated mode : "1024x768-100", from ??? */
- {
- "1024x768-100", {
- 115500, 1024, 768, 32, 224, 416, 1440, 3, 13, 34, 802, 1024, 0, 8,
- PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW|
- PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-43-lace" */
-/* INTERLACED NOT SUPPORTED
- {"1152x864-43-lace", {64998, 1152, 864, 72, 200, 264, 1416, 78, 87, 191, 1055, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}},
- INTERLACED NOT SUPPORTED */
-/* Generated mode : "1152x864-47-lace" */
-/* INTERLACED NOT SUPPORTED
- {"1152x864-47-lace", {64998, 1152, 864, 88, 216, 296, 1448, 30, 39, 83, 947, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}},
- INTERLACED NOT SUPPORTED */
-/* Generated mode : "1152x864-60" */
- {
- "1152x864-60", {
- 80000, 1152, 864, 64, 176, 304, 1456, 6, 11, 52,
- 916, 1152, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-70" */
- {
- "1152x864-70", {
- 100000, 1152, 864, 40, 192, 360, 1512, 13, 24, 81,
- 945, 1152, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-75" */
- {
- "1152x864-75", {
- 109998, 1152, 864, 24, 168, 312, 1464, 45, 53, 138,
- 1002, 1152, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-80" */
- {
- "1152x864-80", {
- 109998, 1152, 864, 16, 128, 288, 1440, 30, 37, 94,
- 958, 1152, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-43-lace" */
-/* INTERLACED NOT SUPPORTED
- {"1280x1024-43-lace", {80000, 1024, 1024, 80, 160, 320, 1344, 50, 60, 125, 1149, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}},
- INTERLACED NOT SUPPORTED */
-/* Generated mode : "1280x1024-47-lace" */
-/* INTERLACED NOT SUPPORTED
- {"1280x1024-47-lace", {80000, 1280, 1024, 80, 160, 320, 1600, 1, 11, 29, 1053, 1280, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}},
- INTERLACED NOT SUPPORTED */
-/* Generated mode : "1280x1024-60" */
- {
- "1280x1024-60", {
- 107991, 1280, 1024, 48, 160, 408, 1688, 1, 4, 42,
- 1066, 1280, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-70" */
- {
- "1280x1024-70", {
- 125992, 1280, 1024, 80, 192, 408, 1688, 1, 6, 42,
- 1066, 1280, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-74" */
- {
- "1280x1024-74", {
- 134989, 1280, 1024, 32, 176, 432, 1712, 0, 30, 40,
- 1064, 1280, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-75" */
- {
- "1280x1024-75", {
- 134989, 1280, 1024, 16, 160, 408, 1688, 1, 4, 42,
- 1066, 1280, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_HIGH
- |
- PM3VideoControl_VSYNC_ACTIVE_HIGH
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1600x1200-60" */
- {
- "1600x1200-60", {
- 155981, 1600, 1200, 32, 192, 448, 2048, 10, 18, 70,
- 1270, 1600, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1600x1200-66" */
- {
- "1600x1200-66", {
- 171998, 1600, 1200, 40, 176, 480, 2080, 3, 6, 53,
- 1253, 1600, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1600x1200-76" */
- {
- "1600x1200-76", {
- 197980, 1600, 1200, 40, 176, 480, 2080, 3, 8, 50,
- 1250, 1600, 0, 8,
- PM3VideoControl_ENABLE |
- PM3VideoControl_HSYNC_ACTIVE_LOW
- |
- PM3VideoControl_VSYNC_ACTIVE_LOW
- | PM3VideoControl_PIXELSIZE_8BIT}},
-/* ##### end of auto-generated mode */
- {
- "\0",}
-};
-
-/* more mandatory stuff (see skeletonfb.c + framebuffer driver HOWTO */
-static struct pm3fb_info fb_info[PM3_MAX_BOARD];
-static struct pm3fb_par current_par[PM3_MAX_BOARD];
-static int current_par_valid[PM3_MAX_BOARD];
-/* to allow explicit filtering of board */
-short bus[PM3_MAX_BOARD];
-short slot[PM3_MAX_BOARD];
-short func[PM3_MAX_BOARD];
-short disable[PM3_MAX_BOARD];
-short noaccel[PM3_MAX_BOARD];
-char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE];
-short depth[PM3_MAX_BOARD];
-short flatpanel[PM3_MAX_BOARD];
-static struct display disp[PM3_MAX_BOARD];
-static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy";
-short printtimings = 0;
-short forcesize[PM3_MAX_BOARD];
-
-/* ********************* */
-/* ***** prototype ***** */
-/* ********************* */
-/* card-specific */
-static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info);
-/* permedia3-specific */
-static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
-static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info);
-static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info);
-static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
- unsigned long r);
-static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock, /* In kHz units */
- unsigned long refclock, /* In kHz units */
- unsigned char *prescale, /* ClkPreScale */
- unsigned char *feedback, /* ClkFeedBackScale */
- unsigned char *postscale
- /* ClkPostScale */ );
-static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc);
-static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b);
-static void pm3fb_common_init(struct pm3fb_info *l_fb_info);
-static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info,
- unsigned long depth, int v);
-static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info,
- unsigned long depth, int v);
-static void pm3fb_mapIO(struct pm3fb_info *l_fb_info);
-static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info);
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2)
-static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info);
-#endif
-static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info);
-static void pm3fb_write_mode(struct pm3fb_info *l_fb_info);
-static void pm3fb_read_mode(struct pm3fb_info *l_fb_info,
- struct pm3fb_par *curpar);
-static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info);
-/* accelerated permedia3-specific */
-#ifdef PM3FB_USE_ACCEL
-static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info);
-static void pm3fb_init_engine(struct pm3fb_info *l_fb_info);
-#ifdef FBCON_HAS_CFB32
-static void pm3fb_cfb32_clear(struct vc_data *conp,
- struct display *p,
- int sy, int sx, int height, int width);
-static void pm3fb_cfb32_clear_margins(struct vc_data *conp,
- struct display *p, int bottom_only);
-#endif /* FBCON_HAS_CFB32 */
-#ifdef FBCON_HAS_CFB16
-static void pm3fb_cfb16_clear(struct vc_data *conp,
- struct display *p,
- int sy, int sx, int height, int width);
-static void pm3fb_cfb16_clear_margins(struct vc_data *conp,
- struct display *p, int bottom_only);
-#endif /* FBCON_HAS_CFB16 */
-#ifdef FBCON_HAS_CFB8
-static void pm3fb_cfb8_clear(struct vc_data *conp,
- struct display *p,
- int sy, int sx, int height, int width);
-static void pm3fb_cfb8_clear_margins(struct vc_data *conp,
- struct display *p, int bottom_only);
-#endif /* FBCON_HAS_CFB8 */
-#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
-static void pm3fb_cfbX_bmove(struct display *p,
- int sy, int sx,
- int dy, int dx, int height, int width);
-static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p,
- int c, int yy, int xx);
-static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p,
- const unsigned short *s, int count, int yy,
- int xx);
-static void pm3fb_cfbX_revc(struct display *p, int xx, int yy);
-#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
-#endif /* PM3FB_USE_ACCEL */
-/* pre-init */
-static void pm3fb_mode_setup(char *mode, unsigned long board_num);
-static void pm3fb_pciid_setup(char *pciid, unsigned long board_num);
-static char *pm3fb_boardnum_setup(char *options, unsigned long *bn);
-static void pm3fb_real_setup(char *options);
-/* fbdev */
-static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix,
- const void *par, struct fb_info_gen *info);
-static int pm3fb_decode_var(const struct fb_var_screeninfo *var,
- void *par, struct fb_info_gen *info);
-static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d);
-static int pm3fb_encode_var(struct fb_var_screeninfo *var,
- const void *par, struct fb_info_gen *info);
-static void pm3fb_get_par(void *par, struct fb_info_gen *info);
-static void pm3fb_set_par(const void *par, struct fb_info_gen *info);
-static void pm3fb_set_color(struct pm3fb_info *l_fb_info,
- unsigned char regno, unsigned char r,
- unsigned char g, unsigned char b);
-static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *info);
-static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info);
-static int pm3fb_blank(int blank_mode, struct fb_info_gen *info);
-static void pm3fb_set_disp(const void *par, struct display *disp,
- struct fb_info_gen *info);
-static void pm3fb_detect(void);
-static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
- struct fb_info_gen *info);
-static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
-
-
-/* the struct that hold them together */
-struct fbgen_hwswitch pm3fb_switch = {
- pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
- pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg,
- pm3fb_pan_display, pm3fb_blank, pm3fb_set_disp
-};
-
-static struct fb_ops pm3fb_ops = {
- .owner = THIS_MODULE,
- .fb_get_fix = fbgen_get_fix,
- .fb_get_var = fbgen_get_var,
- .fb_set_var = fbgen_set_var,
- .fb_get_cmap = fbgen_get_cmap,
- .fb_set_cmap = fbgen_set_cmap,
- .fb_setcolreg = pm3fb_setcolreg,
- .fb_pan_display =fbgen_pan_display,
- .fb_blank = fbgen_blank,
- .fb_ioctl = pm3fb_ioctl,
-};
-
-#ifdef PM3FB_USE_ACCEL
-#ifdef FBCON_HAS_CFB32
-static struct display_switch pm3fb_cfb32 = {
- fbcon_cfb32_setup, pm3fb_cfbX_bmove, pm3fb_cfb32_clear,
- pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc,
- NULL /* cursor() */ , NULL /* set_font() */ ,
- pm3fb_cfb32_clear_margins,
- FONTWIDTHRANGE(1, 16) /* true only if accelerated... */
-};
-#endif /* FBCON_HAS_CFB32 */
-#ifdef FBCON_HAS_CFB16
-static struct display_switch pm3fb_cfb16 = {
- fbcon_cfb16_setup, pm3fb_cfbX_bmove, pm3fb_cfb16_clear,
- pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc,
- NULL /* cursor() */ , NULL /* set_font() */ ,
- pm3fb_cfb16_clear_margins,
- FONTWIDTHRANGE(1, 16) /* true only if accelerated... */
-};
-#endif /* FBCON_HAS_CFB16 */
-#ifdef FBCON_HAS_CFB8
-static struct display_switch pm3fb_cfb8 = {
- fbcon_cfb8_setup, pm3fb_cfbX_bmove, pm3fb_cfb8_clear,
- pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc,
- NULL /* cursor() */ , NULL /* set_font() */ ,
- pm3fb_cfb8_clear_margins,
- FONTWIDTHRANGE(1, 16) /* true only if accelerated... */
-};
-#endif /* FBCON_HAS_CFB8 */
-#endif /* PM3FB_USE_ACCEL */
-
-/* ****************************** */
-/* ***** card-specific data ***** */
-/* ****************************** */
-struct pm3fb_card_timings {
- unsigned long memsize; /* 0 for last value (i.e. default) */
- struct pm3fb_timings memt;
-};
-
-static struct pm3fb_card_timings t_FormacProFormance3[] = {
- { 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} },
- { 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */
-};
-
-static struct pm3fb_card_timings t_AppianJeronimo2000[] = {
- { 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} },
- { 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */
-};
-
-static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = {
- { 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} },
- { 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */
-};
-
-static struct {
- char cardname[32]; /* recognized card name */
- u16 subvendor; /* subvendor of the card */
- u16 subdevice; /* subdevice of the card */
- u8 func; /* function of the card to which the extra init apply */
- void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */
- struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */
-} cardbase[] = {
- { "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL },
- { "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL,
- t_AppianJeronimo2000
- },
- { "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup,
- t_AppianJeronimo2000
- },
- { "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */
- t_FormacProFormance3
- },
- { "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL },
- { "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL,
- t_3DLabsOxygenVX1
- },
- { "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL },
- { "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL },
- { "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL },
- { "\0", 0x0, 0x0, 0, NULL, NULL }
-};
-
-/* ********************************** */
-/* ***** card-specific function ***** */
-/* ********************************** */
-static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info)
-{ /* the appian j2000 require more initialization of the second head */
- /* l_fb_info must point to the _second_ head of the J2000 */
-
- DTRACE;
-
- l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */
-
- pm3fb_write_memory_timings(l_fb_info);
+ return fb_readl(par->v_regs + off);
}
-/* *************************************** */
-/* ***** permedia3-specific function ***** */
-/* *************************************** */
-static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
+static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
{
- l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps);
- l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings);
- l_fb_info->memt.control = PM3_READ_REG(PM3LocalMemControl);
- l_fb_info->memt.refresh = PM3_READ_REG(PM3LocalMemRefresh);
- l_fb_info->memt.powerdown = PM3_READ_REG(PM3LocalMemPowerDown);
+ fb_writel(v, par->v_regs + off);
+}
- if ((l_fb_info->memt.caps == PM3FB_UNKNOWN_TIMING_VALUE) ||
- (l_fb_info->memt.timings == PM3FB_UNKNOWN_TIMING_VALUE) ||
- (l_fb_info->memt.control == PM3FB_UNKNOWN_TIMING_VALUE) ||
- (l_fb_info->memt.refresh == PM3FB_UNKNOWN_TIMING_VALUE) ||
- (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE))
- {
- printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num);
- return(pm3fb_try_memory_timings(l_fb_info));
+static inline void PM3_WAIT(struct pm3_par *par, u32 n)
+{
+ while (PM3_READ_REG(par, PM3InFIFOSpace) < n);
+}
+
+static inline void PM3_SLOW_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
+{
+ if (par->v_regs) {
+ mb();
+ PM3_WAIT(par, 1);
+ wmb();
+ PM3_WRITE_REG(par, off, v);
}
- return(pm3fb_timing_ok);
}
-static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info)
+static inline void PM3_SET_INDEX(struct pm3_par *par, unsigned index)
{
- if (cardbase[l_fb_info->board_type].c_memt)
- {
- int i = 0, done = 0;
- while (!done)
- {
- if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size)
- || !(cardbase[l_fb_info->board_type].c_memt[i].memsize))
- { /* will use the 0-sized timings by default */
- done = 1;
- l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt;
- printk(KERN_WARNING "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n",
- l_fb_info->board_num,
- cardbase[l_fb_info->board_type].cardname,
- cardbase[l_fb_info->board_type].c_memt[i].memsize);
- pm3fb_write_memory_timings(l_fb_info);
- return(pm3fb_timing_retry);
- }
- i++;
- }
- } else
- return(pm3fb_timing_problem);
- return(pm3fb_timing_ok);
+ PM3_SLOW_WRITE_REG(par, PM3RD_IndexHigh, (index >> 8) & 0xff);
+ PM3_SLOW_WRITE_REG(par, PM3RD_IndexLow, index & 0xff);
}
-static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info)
+static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
{
- unsigned char m, n, p;
- unsigned long clockused;
-
- PM3_SLOW_WRITE_REG(PM3LocalMemCaps, l_fb_info->memt.caps);
- PM3_SLOW_WRITE_REG(PM3LocalMemTimings, l_fb_info->memt.timings);
- PM3_SLOW_WRITE_REG(PM3LocalMemControl, l_fb_info->memt.control);
- PM3_SLOW_WRITE_REG(PM3LocalMemRefresh, l_fb_info->memt.refresh);
- PM3_SLOW_WRITE_REG(PM3LocalMemPowerDown, l_fb_info->memt.powerdown);
-
- clockused =
- pm3fb_CalculateClock(l_fb_info, 2 * 105000, PM3_REF_CLOCK, &m,
- &n, &p);
-
- PM3_WRITE_DAC_REG(PM3RD_KClkPreScale, m);
- PM3_WRITE_DAC_REG(PM3RD_KClkFeedbackScale, n);
- PM3_WRITE_DAC_REG(PM3RD_KClkPostScale, p);
- PM3_WRITE_DAC_REG(PM3RD_KClkControl,
- PM3RD_KClkControl_STATE_RUN |
- PM3RD_KClkControl_SOURCE_PLL |
- PM3RD_KClkControl_ENABLE);
- PM3_WRITE_DAC_REG(PM3RD_MClkControl,
- PM3RD_MClkControl_STATE_RUN |
- PM3RD_MClkControl_SOURCE_KCLK |
- PM3RD_MClkControl_ENABLE);
- PM3_WRITE_DAC_REG(PM3RD_SClkControl,
- PM3RD_SClkControl_STATE_RUN |
- PM3RD_SClkControl_SOURCE_PCLK |
- PM3RD_SClkControl_ENABLE);
+ PM3_SET_INDEX(par, r);
+ wmb();
+ PM3_WRITE_REG(par, PM3RD_IndexedData, v);
}
-static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
- unsigned long r)
+static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
+ unsigned char r, unsigned char g, unsigned char b)
{
- DASSERT((l_fb_info->vIOBase != (unsigned char *) (-1)),
- "l_fb_info->vIOBase mapped in read dac reg\n");
- PM3_SET_INDEX(r);
- mb();
- return (PM3_READ_REG(PM3RD_IndexedData));
+ PM3_SLOW_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
+ PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, r);
+ PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, g);
+ PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, b);
+}
+
+static void pm3fb_clear_colormap(struct pm3_par *par,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ int i;
+
+ for (i = 0; i < 256 ; i++) /* fill color map with white */
+ pm3fb_set_color(par, i, r, g, b);
+
}
/* Calculating various clock parameter */
-static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock, /* In kHz units */
- unsigned long refclock, /* In kHz units */
- unsigned char *prescale, /* ClkPreScale */
- unsigned char *feedback, /* ClkFeedBackScale */
- unsigned char *postscale
- /* ClkPostScale */ )
+static void pm3fb_calculate_clock(unsigned long reqclock,
+ unsigned char *prescale,
+ unsigned char *feedback,
+ unsigned char *postscale)
{
int f, pre, post;
unsigned long freq;
long freqerr = 1000;
- unsigned long actualclock = 0;
-
- DTRACE;
+ long currerr;
for (f = 1; f < 256; f++) {
for (pre = 1; pre < 256; pre++) {
for (post = 0; post < 5; post++) {
- freq =
- ((2 * refclock * f) /
- (pre * (1 << post)));
- if ((reqclock > freq - freqerr)
- && (reqclock < freq + freqerr)) {
- freqerr =
- (reqclock >
- freq) ? reqclock -
- freq : freq - reqclock;
+ freq = ((2*PM3_REF_CLOCK * f) >> post) / pre;
+ currerr = (reqclock > freq)
+ ? reqclock - freq
+ : freq - reqclock;
+ if (currerr < freqerr) {
+ freqerr = currerr;
*feedback = f;
*prescale = pre;
*postscale = post;
- actualclock = freq;
}
}
}
}
-
- return (actualclock);
}
-static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info,
- unsigned long depth, int v)
+static inline int pm3fb_shift_bpp(unsigned long depth, int v)
{
- DTRACE;
-
switch (depth) {
case 8:
return (v >> 4);
@@ -918,181 +187,59 @@
case 32:
return (v >> 2);
}
- DPRINTK(1, "Unsupported depth %ld\n", depth);
- return (0);
-}
-
-static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info,
- unsigned long depth, int v)
-{
- DTRACE;
-
- switch (depth) {
- case 8:
- return (v << 4);
- case 12:
- case 15:
- case 16:
- return (v << 3);
- case 32:
- return (v << 2);
- }
- DPRINTK(1, "Unsupported depth %ld\n", depth);
- return (0);
-}
-
-static void pm3fb_mapIO(struct pm3fb_info *l_fb_info)
-{
- DTRACE;
-
- l_fb_info->vIOBase =
- ioremap((unsigned long) l_fb_info->pIOBase, PM3_REGS_SIZE);
- l_fb_info->v_fb =
- ioremap((unsigned long) l_fb_info->p_fb, l_fb_info->fb_size);
- DPRINTK(2, "IO mapping : IOBase %lx / %lx, fb %lx / %lx\n",
- (unsigned long) l_fb_info->pIOBase,
- (unsigned long) l_fb_info->vIOBase,
- (unsigned long) l_fb_info->p_fb,
- (unsigned long) l_fb_info->v_fb);
-}
-
-static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info)
-{
- DTRACE;
-
- iounmap(l_fb_info->vIOBase);
- iounmap(l_fb_info->v_fb);
- l_fb_info->vIOBase = (unsigned char *) -1;
- l_fb_info->v_fb = (unsigned char *) -1;
-}
-
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2)
-static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info)
-{
- DPRINTK(2, "PM3Aperture0: 0x%08x\n", PM3_READ_REG(PM3Aperture0));
- DPRINTK(2, "PM3Aperture1: 0x%08x\n", PM3_READ_REG(PM3Aperture1));
- DPRINTK(2, "PM3ByAperture1Mode: 0x%08x\n",
- PM3_READ_REG(PM3ByAperture1Mode));
- DPRINTK(2, "PM3ByAperture2Mode: 0x%08x\n",
- PM3_READ_REG(PM3ByAperture2Mode));
- DPRINTK(2, "PM3ChipConfig: 0x%08x\n", PM3_READ_REG(PM3ChipConfig));
- DPRINTK(2, "PM3FIFODis: 0x%08x\n", PM3_READ_REG(PM3FIFODis));
- DPRINTK(2, "PM3HTotal: 0x%08x\n", PM3_READ_REG(PM3HTotal));
- DPRINTK(2, "PM3HbEnd: 0x%08x\n", PM3_READ_REG(PM3HbEnd));
- DPRINTK(2, "PM3HgEnd: 0x%08x\n", PM3_READ_REG(PM3HgEnd));
- DPRINTK(2, "PM3HsEnd: 0x%08x\n", PM3_READ_REG(PM3HsEnd));
- DPRINTK(2, "PM3HsStart: 0x%08x\n", PM3_READ_REG(PM3HsStart));
- DPRINTK(2, "PM3MemBypassWriteMask: 0x%08x\n",
- PM3_READ_REG(PM3MemBypassWriteMask));
- DPRINTK(2, "PM3RD_IndexControl: 0x%08x\n",
- PM3_READ_REG(PM3RD_IndexControl));
- DPRINTK(2, "PM3ScreenBase: 0x%08x\n", PM3_READ_REG(PM3ScreenBase));
- DPRINTK(2, "PM3ScreenStride: 0x%08x\n",
- PM3_READ_REG(PM3ScreenStride));
- DPRINTK(2, "PM3VClkCtl: 0x%08x\n", PM3_READ_REG(PM3VClkCtl));
- DPRINTK(2, "PM3VTotal: 0x%08x\n", PM3_READ_REG(PM3VTotal));
- DPRINTK(2, "PM3VbEnd: 0x%08x\n", PM3_READ_REG(PM3VbEnd));
- DPRINTK(2, "PM3VideoControl: 0x%08x\n",
- PM3_READ_REG(PM3VideoControl));
- DPRINTK(2, "PM3VsEnd: 0x%08x\n", PM3_READ_REG(PM3VsEnd));
- DPRINTK(2, "PM3VsStart: 0x%08x\n", PM3_READ_REG(PM3VsStart));
-
- DPRINTK(2, "PM3RD_ColorFormat: %ld\n",
- PM3_READ_DAC_REG(PM3RD_ColorFormat));
- DPRINTK(2, "PM3RD_DACControl: %ld\n",
- PM3_READ_DAC_REG(PM3RD_DACControl));
- DPRINTK(2, "PM3RD_DClk0FeedbackScale: %ld\n",
- PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale));
- DPRINTK(2, "PM3RD_DClk0PostScale: %ld\n",
- PM3_READ_DAC_REG(PM3RD_DClk0PostScale));
- DPRINTK(2, "PM3RD_DClk0PreScale: %ld\n",
- PM3_READ_DAC_REG(PM3RD_DClk0PreScale));
- DPRINTK(2, "[not set] PM3RD_IndexControl: %ld\n",
- PM3_READ_DAC_REG(PM3RD_IndexControl));
- DPRINTK(2, "PM3RD_MiscControl: %ld\n",
- PM3_READ_DAC_REG(PM3RD_MiscControl));
- DPRINTK(2, "PM3RD_PixelSize: %ld\n",
- PM3_READ_DAC_REG(PM3RD_PixelSize));
- DPRINTK(2, "PM3RD_SyncControl: %ld\n",
- PM3_READ_DAC_REG(PM3RD_SyncControl));
-}
-
-#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) */
-static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info)
-{
- u16 subvendor, subdevice;
-
- if ((!pci_read_config_word
- (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor))
- &&
- (!pci_read_config_word
- (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) {
- /* well, nothing... */
- } else {
- subvendor = subdevice = (u16)-1;
- }
-
- printk(KERN_INFO "pm3fb: memory timings for board #%ld (subvendor: 0x%hx, subdevice: 0x%hx)\n", l_fb_info->board_num, subvendor, subdevice);
- printk(KERN_INFO " PM3LocalMemCaps: 0x%08x\n",
- PM3_READ_REG(PM3LocalMemCaps));
- printk(KERN_INFO " PM3LocalMemTimings: 0x%08x\n",
- PM3_READ_REG(PM3LocalMemTimings));
- printk(KERN_INFO " PM3LocalMemControl: 0x%08x\n",
- PM3_READ_REG(PM3LocalMemControl));
- printk(KERN_INFO " PM3LocalMemRefresh: 0x%08x\n",
- PM3_READ_REG(PM3LocalMemRefresh));
- printk(KERN_INFO " PM3LocalMemPowerDown: 0x%08x\n",
- PM3_READ_REG(PM3LocalMemPowerDown));
+ DPRINTK("Unsupported depth %ld\n", depth);
+ return 0;
}
/* write the mode to registers */
-static void pm3fb_write_mode(struct pm3fb_info *l_fb_info)
+static void pm3fb_write_mode(struct fb_info *info)
{
+ struct pm3_par *par = info->par;
char tempsync = 0x00, tempmisc = 0x00;
- DTRACE;
+ const u32 hsstart = info->var.right_margin;
+ const u32 hsend = hsstart + info->var.hsync_len;
+ const u32 hbend = hsend + info->var.left_margin;
+ const u32 xres = (info->var.xres + 31) & ~31;
+ const u32 htotal = xres + hbend;
+ const u32 vsstart = info->var.lower_margin;
+ const u32 vsend = vsstart + info->var.vsync_len;
+ const u32 vbend = vsend + info->var.upper_margin;
+ const u32 vtotal = info->var.yres + vbend;
+ const u32 width = (info->var.xres_virtual + 7) & ~7;
- PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff);
- PM3_SLOW_WRITE_REG(PM3Aperture0, 0x00000000);
- PM3_SLOW_WRITE_REG(PM3Aperture1, 0x00000000);
- PM3_SLOW_WRITE_REG(PM3FIFODis, 0x00000007);
+ PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
+ PM3_SLOW_WRITE_REG(par, PM3Aperture0, 0x00000000);
+ PM3_SLOW_WRITE_REG(par, PM3Aperture1, 0x00000000);
+ PM3_SLOW_WRITE_REG(par, PM3FIFODis, 0x00000007);
- PM3_SLOW_WRITE_REG(PM3HTotal,
- pm3fb_Shiftbpp(l_fb_info,
- l_fb_info->current_par->depth,
- l_fb_info->current_par->htotal -
- 1));
- PM3_SLOW_WRITE_REG(PM3HsEnd,
- pm3fb_Shiftbpp(l_fb_info,
- l_fb_info->current_par->depth,
- l_fb_info->current_par->hsend));
- PM3_SLOW_WRITE_REG(PM3HsStart,
- pm3fb_Shiftbpp(l_fb_info,
- l_fb_info->current_par->depth,
- l_fb_info->current_par->
+ PM3_SLOW_WRITE_REG(par, PM3HTotal,
+ pm3fb_shift_bpp(info->var.bits_per_pixel,
+ htotal - 1));
+ PM3_SLOW_WRITE_REG(par, PM3HsEnd,
+ pm3fb_shift_bpp(info->var.bits_per_pixel,
+ hsend));
+ PM3_SLOW_WRITE_REG(par, PM3HsStart,
+ pm3fb_shift_bpp(info->var.bits_per_pixel,
hsstart));
- PM3_SLOW_WRITE_REG(PM3HbEnd,
- pm3fb_Shiftbpp(l_fb_info,
- l_fb_info->current_par->depth,
- l_fb_info->current_par->hbend));
- PM3_SLOW_WRITE_REG(PM3HgEnd,
- pm3fb_Shiftbpp(l_fb_info,
- l_fb_info->current_par->depth,
- l_fb_info->current_par->hbend));
- PM3_SLOW_WRITE_REG(PM3ScreenStride,
- pm3fb_Shiftbpp(l_fb_info,
- l_fb_info->current_par->depth,
- l_fb_info->current_par->stride));
- PM3_SLOW_WRITE_REG(PM3VTotal, l_fb_info->current_par->vtotal - 1);
- PM3_SLOW_WRITE_REG(PM3VsEnd, l_fb_info->current_par->vsend - 1);
- PM3_SLOW_WRITE_REG(PM3VsStart,
- l_fb_info->current_par->vsstart - 1);
- PM3_SLOW_WRITE_REG(PM3VbEnd, l_fb_info->current_par->vbend);
+ PM3_SLOW_WRITE_REG(par, PM3HbEnd,
+ pm3fb_shift_bpp(info->var.bits_per_pixel,
+ hbend));
+ PM3_SLOW_WRITE_REG(par, PM3HgEnd,
+ pm3fb_shift_bpp(info->var.bits_per_pixel,
+ hbend));
+ PM3_SLOW_WRITE_REG(par, PM3ScreenStride,
+ pm3fb_shift_bpp(info->var.bits_per_pixel,
+ width));
+ PM3_SLOW_WRITE_REG(par, PM3VTotal, vtotal - 1);
+ PM3_SLOW_WRITE_REG(par, PM3VsEnd, vsend - 1);
+ PM3_SLOW_WRITE_REG(par, PM3VsStart, vsstart - 1);
+ PM3_SLOW_WRITE_REG(par, PM3VbEnd, vbend);
- switch (l_fb_info->current_par->depth) {
+ switch (info->var.bits_per_pixel) {
case 8:
- PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_8BIT);
- PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_8BIT);
break;
@@ -1100,15 +247,15 @@
case 15:
case 16:
#ifndef __BIG_ENDIAN
- PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_16BIT);
- PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_16BIT);
#else
- PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_16BIT |
PM3ByApertureMode_BYTESWAP_BADC);
- PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_16BIT |
PM3ByApertureMode_BYTESWAP_BADC);
#endif /* ! __BIG_ENDIAN */
@@ -1116,23 +263,23 @@
case 32:
#ifndef __BIG_ENDIAN
- PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_32BIT);
- PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_32BIT);
#else
- PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
PM3ByApertureMode_PIXELSIZE_32BIT |
PM3ByApertureMode_BYTESWAP_DCBA);
- PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+ PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
PM3ByApertureMode_PIXELSIZE_32BIT |
PM3ByApertureMode_BYTESWAP_DCBA);
#endif /* ! __BIG_ENDIAN */
break;
default:
- DPRINTK(1, "Unsupported depth %d\n",
- l_fb_info->current_par->depth);
+ DPRINTK("Unsupported depth %d\n",
+ info->var.bits_per_pixel);
break;
}
@@ -1143,95 +290,86 @@
* sync options in PM3RD_SyncControl. --rmk
*/
{
- unsigned int video = l_fb_info->current_par->video;
+ unsigned int video = par->video;
video &= ~(PM3VideoControl_HSYNC_MASK |
PM3VideoControl_VSYNC_MASK);
video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
PM3VideoControl_VSYNC_ACTIVE_HIGH;
- PM3_SLOW_WRITE_REG(PM3VideoControl, video);
+ PM3_SLOW_WRITE_REG(par, PM3VideoControl, video);
}
- PM3_SLOW_WRITE_REG(PM3VClkCtl,
- (PM3_READ_REG(PM3VClkCtl) & 0xFFFFFFFC));
- PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base);
- PM3_SLOW_WRITE_REG(PM3ChipConfig,
- (PM3_READ_REG(PM3ChipConfig) & 0xFFFFFFFD));
+ PM3_SLOW_WRITE_REG(par, PM3VClkCtl,
+ (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
+ PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
+ PM3_SLOW_WRITE_REG(par, PM3ChipConfig,
+ (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
{
- unsigned char m; /* ClkPreScale */
- unsigned char n; /* ClkFeedBackScale */
- unsigned char p; /* ClkPostScale */
- (void)pm3fb_CalculateClock(l_fb_info, l_fb_info->current_par->pixclock, PM3_REF_CLOCK, &m, &n, &p);
+ unsigned char uninitialized_var(m); /* ClkPreScale */
+ unsigned char uninitialized_var(n); /* ClkFeedBackScale */
+ unsigned char uninitialized_var(p); /* ClkPostScale */
+ unsigned long pixclock = PICOS2KHZ(info->var.pixclock);
- DPRINTK(2,
- "Pixclock: %d, Pre: %d, Feedback: %d, Post: %d\n",
- l_fb_info->current_par->pixclock, (int) m, (int) n,
- (int) p);
+ (void)pm3fb_calculate_clock(pixclock, &m, &n, &p);
- PM3_WRITE_DAC_REG(PM3RD_DClk0PreScale, m);
- PM3_WRITE_DAC_REG(PM3RD_DClk0FeedbackScale, n);
- PM3_WRITE_DAC_REG(PM3RD_DClk0PostScale, p);
+ DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n",
+ pixclock, (int) m, (int) n, (int) p);
+
+ PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m);
+ PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n);
+ PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p);
}
/*
- PM3_WRITE_DAC_REG(PM3RD_IndexControl, 0x00);
+ PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00);
*/
/*
- PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00);
+ PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00);
*/
- if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) ==
+ if ((par->video & PM3VideoControl_HSYNC_MASK) ==
PM3VideoControl_HSYNC_ACTIVE_HIGH)
tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
- if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) ==
+ if ((par->video & PM3VideoControl_VSYNC_MASK) ==
PM3VideoControl_VSYNC_ACTIVE_HIGH)
tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
-
- PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
- DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
-
- if (flatpanel[l_fb_info->board_num])
- {
- PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE);
- PM3_WAIT(2);
- PM3_WRITE_REG(PM3VSConfiguration, 0x06);
- PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */
- tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE;
- }
- else
- PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
- switch (l_fb_info->current_par->depth) {
+ PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync);
+ DPRINTK("PM3RD_SyncControl: %d\n", tempsync);
+
+ PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
+
+ switch (info->var.bits_per_pixel) {
case 8:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+ PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
PM3RD_PixelSize_8_BIT_PIXELS);
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+ PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
PM3RD_ColorFormat_CI8_COLOR |
PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
break;
case 12:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+ PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
PM3RD_PixelSize_16_BIT_PIXELS);
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+ PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
PM3RD_ColorFormat_4444_COLOR |
PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
- break;
+ break;
case 15:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+ PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
PM3RD_PixelSize_16_BIT_PIXELS);
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+ PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
PM3RD_ColorFormat_5551_FRONT_COLOR |
PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
- break;
+ break;
case 16:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+ PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
PM3RD_PixelSize_16_BIT_PIXELS);
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+ PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
PM3RD_ColorFormat_565_FRONT_COLOR |
PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
@@ -1239,1936 +377,280 @@
PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
break;
case 32:
- PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+ PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
PM3RD_PixelSize_32_BIT_PIXELS);
- PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+ PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
PM3RD_ColorFormat_8888_COLOR |
PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
break;
}
- PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc);
-
- PM3_SHOW_CUR_MODE;
+ PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc);
}
-static void pm3fb_read_mode(struct pm3fb_info *l_fb_info,
- struct pm3fb_par *curpar)
+/*
+ * hardware independent functions
+ */
+int pm3fb_init(void);
+int pm3fb_setup(char*);
+
+static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- unsigned long pixsize1, pixsize2, clockused;
- unsigned long pre, feedback, post;
+ u32 lpitch;
- DTRACE;
-
- clockused = PM3_READ_REG(PM3VClkCtl);
-
- switch (clockused) {
- case 3:
- pre = PM3_READ_DAC_REG(PM3RD_DClk3PreScale);
- feedback = PM3_READ_DAC_REG(PM3RD_DClk3FeedbackScale);
- post = PM3_READ_DAC_REG(PM3RD_DClk3PostScale);
-
- DPRINTK(2,
- "DClk3 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
- pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
- feedback,
- post));
- break;
- case 2:
- pre = PM3_READ_DAC_REG(PM3RD_DClk2PreScale);
- feedback = PM3_READ_DAC_REG(PM3RD_DClk2FeedbackScale);
- post = PM3_READ_DAC_REG(PM3RD_DClk2PostScale);
-
- DPRINTK(2,
- "DClk2 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
- pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
- feedback,
- post));
- break;
- case 1:
- pre = PM3_READ_DAC_REG(PM3RD_DClk1PreScale);
- feedback = PM3_READ_DAC_REG(PM3RD_DClk1FeedbackScale);
- post = PM3_READ_DAC_REG(PM3RD_DClk1PostScale);
-
- DPRINTK(2,
- "DClk1 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
- pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
- feedback,
- post));
- break;
- case 0:
- pre = PM3_READ_DAC_REG(PM3RD_DClk0PreScale);
- feedback = PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale);
- post = PM3_READ_DAC_REG(PM3RD_DClk0PostScale);
-
- DPRINTK(2,
- "DClk0 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
- pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
- feedback,
- post));
- break;
- default:
- pre = feedback = post = 0;
- DPRINTK(1, "Unknowk D clock used : %ld\n", clockused);
- break;
- }
-
- curpar->pixclock = PM3_SCALE_TO_CLOCK(pre, feedback, post);
-
- pixsize1 =
- PM3ByApertureMode_PIXELSIZE_MASK &
- (PM3_READ_REG(PM3ByAperture1Mode));
- pixsize2 =
- PM3ByApertureMode_PIXELSIZE_MASK &
- (PM3_READ_REG(PM3ByAperture2Mode));
-
- DASSERT((pixsize1 == pixsize2),
- "pixsize the same in both aperture\n");
-
- if (pixsize1 & PM3ByApertureMode_PIXELSIZE_32BIT)
- curpar->depth = 32;
- else if (pixsize1 & PM3ByApertureMode_PIXELSIZE_16BIT)
- {
- curpar->depth = 16;
- }
- else
- curpar->depth = 8;
-
- /* not sure if I need to add one on the next ; it give better result with */
- curpar->htotal =
- pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
- 1 + PM3_READ_REG(PM3HTotal));
- curpar->hsend =
- pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
- PM3_READ_REG(PM3HsEnd));
- curpar->hsstart =
- pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
- PM3_READ_REG(PM3HsStart));
- curpar->hbend =
- pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
- PM3_READ_REG(PM3HbEnd));
-
- curpar->stride =
- pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
- PM3_READ_REG(PM3ScreenStride));
-
- curpar->vtotal = 1 + PM3_READ_REG(PM3VTotal);
- curpar->vsend = 1 + PM3_READ_REG(PM3VsEnd);
- curpar->vsstart = 1 + PM3_READ_REG(PM3VsStart);
- curpar->vbend = PM3_READ_REG(PM3VbEnd);
-
- curpar->video = PM3_READ_REG(PM3VideoControl);
-
- curpar->base = PM3_READ_REG(PM3ScreenBase);
- curpar->width = curpar->htotal - curpar->hbend; /* make virtual == displayed resolution */
- curpar->height = curpar->vtotal - curpar->vbend;
-
- DPRINTK(2, "Found : %d * %d, %d Khz, stride is %08x\n",
- curpar->width, curpar->height, curpar->pixclock,
- curpar->stride);
-}
-
-static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
-{
- unsigned long memsize = 0, tempBypass, i, temp1, temp2;
- u16 subvendor, subdevice;
- pm3fb_timing_result ptr;
-
- DTRACE;
-
- l_fb_info->fb_size = 64 * 1024 * 1024; /* pm3 aperture always 64 MB */
- pm3fb_mapIO(l_fb_info); /* temporary map IO */
-
- DASSERT((l_fb_info->vIOBase != NULL),
- "IO successfully mapped before mem detect\n");
- DASSERT((l_fb_info->v_fb != NULL),
- "FB successfully mapped before mem detect\n");
-
- /* card-specific stuff, *before* accessing *any* FB memory */
- if ((!pci_read_config_word
- (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor))
- &&
- (!pci_read_config_word
- (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) {
- i = 0; l_fb_info->board_type = 0;
- while ((cardbase[i].cardname[0]) && !(l_fb_info->board_type)) {
- if ((cardbase[i].subvendor == subvendor) &&
- (cardbase[i].subdevice == subdevice) &&
- (cardbase[i].func == PCI_FUNC(l_fb_info->dev->devfn))) {
- DPRINTK(2, "Card #%ld is an %s\n",
- l_fb_info->board_num,
- cardbase[i].cardname);
- if (cardbase[i].specific_setup)
- cardbase[i].specific_setup(l_fb_info);
- l_fb_info->board_type = i;
- }
- i++;
- }
- if (!l_fb_info->board_type) {
- DPRINTK(1, "Card #%ld is an unknown 0x%04x / 0x%04x\n",
- l_fb_info->board_num, subvendor, subdevice);
- }
- } else {
- printk(KERN_ERR "pm3fb: Error: pci_read_config_word failed, board #%ld\n",
- l_fb_info->board_num);
- }
-
- if (printtimings)
- pm3fb_show_cur_timing(l_fb_info);
-
- /* card-specific setup is done, we preserve the final
- memory timing for future reference */
- if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */
- return(0);
- }
-
- tempBypass = PM3_READ_REG(PM3MemBypassWriteMask);
-
- DPRINTK(2, "PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
-
- PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xFFFFFFFF);
-
- /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
- for (i = 0; i < 32; i++) {
- fb_writel(i * 0x00345678,
- (l_fb_info->v_fb + (i * 1048576)));
- mb();
- temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576)));
-
- /* Let's check for wrapover, write will fail at 16MB boundary */
- if (temp1 == (i * 0x00345678))
- memsize = i;
- else
- break;
- }
-
- DPRINTK(2, "First detect pass already got %ld MB\n", memsize + 1);
-
- if (memsize == i) {
- for (i = 0; i < 32; i++) {
- /* Clear first 32MB ; 0 is 0, no need to byteswap */
- writel(0x0000000,
- (l_fb_info->v_fb + (i * 1048576)));
- mb();
- }
-
- for (i = 32; i < 64; i++) {
- fb_writel(i * 0x00345678,
- (l_fb_info->v_fb + (i * 1048576)));
- mb();
- temp1 =
- fb_readl((l_fb_info->v_fb + (i * 1048576)));
- temp2 =
- fb_readl((l_fb_info->v_fb +
- ((i - 32) * 1048576)));
- if ((temp1 == (i * 0x00345678)) && (temp2 == 0)) /* different value, different RAM... */
- memsize = i;
- else
- break;
- }
- }
-
- DPRINTK(2, "Second detect pass got %ld MB\n", memsize + 1);
-
- PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, tempBypass);
-
- pm3fb_unmapIO(l_fb_info);
- memsize = 1048576 * (memsize + 1);
-
- DPRINTK(2, "Returning 0x%08lx bytes\n", memsize);
-
- if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize))
- {
- printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]);
- memsize = 1048576 * forcesize[l_fb_info->board_num];
- }
-
- l_fb_info->fb_size = memsize;
-
- if (ptr == pm3fb_timing_retry)
- {
- printk(KERN_WARNING "pm3fb: retrying memory timings check");
- if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem)
- return(0);
- }
-
- return (memsize);
-}
-
-static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc)
-{
- int i;
-
- DTRACE;
-
- for (i = 0; i < (l_fb_info->fb_size / sizeof(u32)) ; i++) /* clear entire FB memory to black */
- {
- fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
- }
-}
-
-static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b)
-{
- int i;
-
- DTRACE;
-
- for (i = 0; i < 256 ; i++) /* fill color map with white */
- pm3fb_set_color(l_fb_info, i, r, g, b);
-
-}
-
-/* common initialisation */
-static void pm3fb_common_init(struct pm3fb_info *l_fb_info)
-{
- DTRACE;
-
- DPRINTK(2, "Initializing board #%ld @ %lx\n", l_fb_info->board_num,
- (unsigned long) l_fb_info);
-
- strcpy(l_fb_info->gen.info.modename, permedia3_name);
- disp[l_fb_info->board_num].scrollmode = 0; /* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */
- l_fb_info->gen.parsize = sizeof(struct pm3fb_par);
- l_fb_info->gen.info.changevar = NULL;
- l_fb_info->gen.info.fbops = &pm3fb_ops;
- l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]);
- if (fontn[l_fb_info->board_num][0])
- strcpy(l_fb_info->gen.info.fontname,
- fontn[l_fb_info->board_num]);
- l_fb_info->gen.info.switch_con = &fbgen_switch;
- l_fb_info->gen.info.updatevar = &fbgen_update_var; /* */
- l_fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
-
- pm3fb_mapIO(l_fb_info);
-
- pm3fb_clear_memory(l_fb_info, 0);
- pm3fb_clear_colormap(l_fb_info, 0, 0, 0);
-
- (void) fbgen_get_var(&(disp[l_fb_info->board_num]).var, -1,
- &l_fb_info->gen.info);
-
- if (depth[l_fb_info->board_num]) /* override mode-defined depth */
- {
- pm3fb_encode_depth(&(disp[l_fb_info->board_num]).var, depth[l_fb_info->board_num]);
- (disp[l_fb_info->board_num]).var.bits_per_pixel = depth2bpp(depth[l_fb_info->board_num]);
- }
-
- (void) fbgen_do_set_var(&(disp[l_fb_info->board_num]).var, 1,
- &l_fb_info->gen);
-
- fbgen_set_disp(-1, &l_fb_info->gen);
-
- do_install_cmap(0, &l_fb_info->gen.info);
-
- if (register_framebuffer(&l_fb_info->gen.info) < 0) {
- DPRINTK(1, "Couldn't register framebuffer\n");
- return;
- }
-
- PM3_WRITE_DAC_REG(PM3RD_CursorMode,
- PM3RD_CursorMode_CURSOR_DISABLE);
-
- PM3_SHOW_CUR_MODE;
-
- pm3fb_write_mode(l_fb_info);
-
- printk("fb%d: %s, using %uK of video memory (%s)\n",
- l_fb_info->gen.info.node,
- permedia3_name, (u32) (l_fb_info->fb_size >> 10),
- cardbase[l_fb_info->board_type].cardname);
-}
-
-/* **************************************************** */
-/* ***** accelerated permedia3-specific functions ***** */
-/* **************************************************** */
-#ifdef PM3FB_USE_ACCEL
-static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info)
-{
- DTRACE;
-
- PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync);
- PM3_SLOW_WRITE_REG(PM3Sync, 0);
- mb();
- do {
- while ((PM3_READ_REG(PM3OutFIFOWords)) == 0);
- rmb();
- } while ((PM3_READ_REG(PM3OutputFifo)) != PM3Sync_Tag);
-}
-
-static void pm3fb_init_engine(struct pm3fb_info *l_fb_info)
-{
- PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync);
- PM3_SLOW_WRITE_REG(PM3StatisticMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3DeltaMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3RasterizerMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3ScissorMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3LineStippleMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3AreaStippleMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3GIDMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3DepthMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3StencilMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3StencilData, 0x0);
- PM3_SLOW_WRITE_REG(PM3ColorDDAMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureCoordMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureIndexMode0, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureIndexMode1, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureReadMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3LUTMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureFilterMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureCompositeMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureApplicationMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode1, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode1, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode0, 0x0);
- PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode0, 0x0);
- PM3_SLOW_WRITE_REG(PM3FogMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3ChromaTestMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3AlphaTestMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3AntialiasMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3YUVMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3AlphaBlendColorMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3AlphaBlendAlphaMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3DitherMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3LogicalOpMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3RouterMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3Window, 0x0);
-
- PM3_SLOW_WRITE_REG(PM3Config2D, 0x0);
-
- PM3_SLOW_WRITE_REG(PM3SpanColorMask, 0xffffffff);
-
- PM3_SLOW_WRITE_REG(PM3XBias, 0x0);
- PM3_SLOW_WRITE_REG(PM3YBias, 0x0);
- PM3_SLOW_WRITE_REG(PM3DeltaControl, 0x0);
-
- PM3_SLOW_WRITE_REG(PM3BitMaskPattern, 0xffffffff);
-
- PM3_SLOW_WRITE_REG(PM3FBDestReadEnables,
- PM3FBDestReadEnables_E(0xff) |
- PM3FBDestReadEnables_R(0xff) |
- PM3FBDestReadEnables_ReferenceAlpha(0xff));
- PM3_SLOW_WRITE_REG(PM3FBDestReadBufferAddr0, 0x0);
- PM3_SLOW_WRITE_REG(PM3FBDestReadBufferOffset0, 0x0);
- PM3_SLOW_WRITE_REG(PM3FBDestReadBufferWidth0,
- PM3FBDestReadBufferWidth_Width(l_fb_info->
- current_par->
- width));
-
- PM3_SLOW_WRITE_REG(PM3FBDestReadMode,
- PM3FBDestReadMode_ReadEnable |
- PM3FBDestReadMode_Enable0);
- PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferAddr, 0x0);
- PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferOffset, 0x0);
- PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferWidth,
- PM3FBSourceReadBufferWidth_Width(l_fb_info->
- current_par->
- width));
- PM3_SLOW_WRITE_REG(PM3FBSourceReadMode,
- PM3FBSourceReadMode_Blocking |
- PM3FBSourceReadMode_ReadEnable);
-
- {
- unsigned long rm = 1;
- switch (l_fb_info->current_par->depth) {
- case 8:
- PM3_SLOW_WRITE_REG(PM3PixelSize,
- PM3PixelSize_GLOBAL_8BIT);
- break;
- case 12:
- case 15:
- case 16:
- PM3_SLOW_WRITE_REG(PM3PixelSize,
- PM3PixelSize_GLOBAL_16BIT);
- break;
- case 32:
- PM3_SLOW_WRITE_REG(PM3PixelSize,
- PM3PixelSize_GLOBAL_32BIT);
- break;
- default:
- DPRINTK(1, "Unsupported depth %d\n",
- l_fb_info->current_par->depth);
- break;
- }
- PM3_SLOW_WRITE_REG(PM3RasterizerMode, rm);
- }
-
- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff);
- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
- PM3_SLOW_WRITE_REG(PM3FBWriteMode,
- PM3FBWriteMode_WriteEnable |
- PM3FBWriteMode_OpaqueSpan |
- PM3FBWriteMode_Enable0);
- PM3_SLOW_WRITE_REG(PM3FBWriteBufferAddr0, 0x0);
- PM3_SLOW_WRITE_REG(PM3FBWriteBufferOffset0, 0x0);
- PM3_SLOW_WRITE_REG(PM3FBWriteBufferWidth0,
- PM3FBWriteBufferWidth_Width(l_fb_info->
- current_par->
- width));
-
- PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 0x0);
- {
- unsigned long sofb = (8UL * l_fb_info->fb_size) /
- ((depth2bpp(l_fb_info->current_par->depth))
- * l_fb_info->current_par->width); /* size in lines of FB */
- if (sofb > 4095)
- PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095);
- else
- PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb);
-
- switch (l_fb_info->current_par->depth) {
- case 8:
- PM3_SLOW_WRITE_REG(PM3DitherMode,
- (1 << 10) | (2 << 3));
- break;
- case 12:
- case 15:
- case 16:
- PM3_SLOW_WRITE_REG(PM3DitherMode,
- (1 << 10) | (1 << 3));
- break;
- case 32:
- PM3_SLOW_WRITE_REG(PM3DitherMode,
- (1 << 10) | (0 << 3));
- break;
- default:
- DPRINTK(1, "Unsupported depth %d\n",
- l_fb_info->current_par->depth);
- break;
- }
- }
-
- PM3_SLOW_WRITE_REG(PM3dXDom, 0x0);
- PM3_SLOW_WRITE_REG(PM3dXSub, 0x0);
- PM3_SLOW_WRITE_REG(PM3dY, (1 << 16));
- PM3_SLOW_WRITE_REG(PM3StartXDom, 0x0);
- PM3_SLOW_WRITE_REG(PM3StartXSub, 0x0);
- PM3_SLOW_WRITE_REG(PM3StartY, 0x0);
- PM3_SLOW_WRITE_REG(PM3Count, 0x0);
-
-/* Disable LocalBuffer. better safe than sorry */
- PM3_SLOW_WRITE_REG(PM3LBDestReadMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3LBDestReadEnables, 0x0);
- PM3_SLOW_WRITE_REG(PM3LBSourceReadMode, 0x0);
- PM3_SLOW_WRITE_REG(PM3LBWriteMode, 0x0);
-
- pm3fb_wait_pm3(l_fb_info);
-}
-
-#ifdef FBCON_HAS_CFB32
-static void pm3fb_cfb32_clear(struct vc_data *conp,
- struct display *p,
- int sy, int sx, int height, int width)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- u32 c;
-
- DTRACE;
-
- sx = sx * fontwidth(p);
- width = width * fontwidth(p);
- sy = sy * fontheight(p);
- height = height * fontheight(p);
- c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-
- /* block fills in 32bpp are hard, but in low res (width <= 1600 :-)
- we can use 16bpp operations, but not if NoWriteMask is on (SDRAM) */
- if ((l_fb_info->current_par->width > 1600) ||
- (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) {
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3ForegroundColor, c);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx)) |
- (PM3RectanglePosition_YOffset(sy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(width)) |
- (PM3Render2D_Height(height)));
- } else {
- PM3_WAIT(8);
-
- PM3_WRITE_REG(PM3FBBlockColor, c);
-
- PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_16BIT);
-
- PM3_WRITE_REG(PM3FBWriteBufferWidth0,
- PM3FBWriteBufferWidth_Width(l_fb_info->
- current_par->
- width << 1));
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx << 1)) |
- (PM3RectanglePosition_YOffset(sy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- (PM3Render2D_Width(width << 1)) |
- (PM3Render2D_Height(height)));
-
- PM3_WRITE_REG(PM3FBWriteBufferWidth0,
- PM3FBWriteBufferWidth_Width(l_fb_info->
- current_par->
- width));
-
- PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_32BIT);
- }
-
- pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfb32_clear_margins(struct vc_data *conp,
- struct display *p, int bottom_only)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- int sx, sy;
- u32 c;
-
- DTRACE;
-
- sx = conp->vc_cols * fontwidth(p); /* right margin */
- sy = conp->vc_rows * fontheight(p); /* bottom margin */
- c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-
- if (!bottom_only) { /* right margin top->bottom */
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3ForegroundColor, c);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset
- (p->var.xoffset +
- sx)) | (PM3RectanglePosition_YOffset(p->
- var.
- yoffset)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(p->var.xres - sx)) |
- (PM3Render2D_Height(p->var.yres)));
- }
-
- /* bottom margin left -> right */
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3ForegroundColor, c);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(p->var.xoffset)) |
- (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(p->var.xres)) |
- (PM3Render2D_Height(p->var.yres - sy)));
-
- pm3fb_wait_pm3(l_fb_info);
-}
-#endif /* FBCON_HAS_CFB32 */
-#ifdef FBCON_HAS_CFB16
-static void pm3fb_cfb16_clear(struct vc_data *conp,
- struct display *p,
- int sy, int sx, int height, int width)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- u32 c;
-
- DTRACE;
-
- sx = sx * fontwidth(p);
- width = width * fontwidth(p);
- sy = sy * fontheight(p);
- height = height * fontheight(p);
- c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
- c = c | (c << 16);
-
- PM3_WAIT(4);
-
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_WRITE_REG(PM3ForegroundColor, c);
- else
- PM3_WRITE_REG(PM3FBBlockColor, c);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx)) |
- (PM3RectanglePosition_YOffset(sy)));
-
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(width)) |
- (PM3Render2D_Height(height)));
- else
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- (PM3Render2D_Width(width)) |
- (PM3Render2D_Height(height)));
-
- pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfb16_clear_margins(struct vc_data *conp,
- struct display *p, int bottom_only)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- int sx, sy;
- u32 c;
-
- DTRACE;
-
- sx = conp->vc_cols * fontwidth(p); /* right margin */
- sy = conp->vc_rows * fontheight(p); /* bottom margin */
- c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
- c = c | (c << 16);
-
- if (!bottom_only) { /* right margin top->bottom */
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_WRITE_REG(PM3ForegroundColor, c);
- else
- PM3_WRITE_REG(PM3FBBlockColor, c);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset
- (p->var.xoffset +
- sx)) | (PM3RectanglePosition_YOffset(p->
- var.
- yoffset)));
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(p->var.xres - sx)) |
- (PM3Render2D_Height(p->var.yres)));
- else
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- (PM3Render2D_Width(p->var.xres - sx)) |
- (PM3Render2D_Height(p->var.yres)));
- }
-
- /* bottom margin left -> right */
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_WRITE_REG(PM3ForegroundColor, c);
- else
- PM3_WRITE_REG(PM3FBBlockColor, c);
-
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(p->var.xoffset)) |
- (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
-
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(p->var.xres)) |
- (PM3Render2D_Height(p->var.yres - sy)));
- else
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- (PM3Render2D_Width(p->var.xres)) |
- (PM3Render2D_Height(p->var.yres - sy)));
-
- pm3fb_wait_pm3(l_fb_info);
-}
-#endif /* FBCON_HAS_CFB16 */
-#ifdef FBCON_HAS_CFB8
-static void pm3fb_cfb8_clear(struct vc_data *conp,
- struct display *p,
- int sy, int sx, int height, int width)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- u32 c;
-
- DTRACE;
-
- sx = sx * fontwidth(p);
- width = width * fontwidth(p);
- sy = sy * fontheight(p);
- height = height * fontheight(p);
-
- c = attr_bgcol_ec(p, conp);
- c |= c << 8;
- c |= c << 16;
-
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3ForegroundColor, c);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx)) |
- (PM3RectanglePosition_YOffset(sy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(width)) |
- (PM3Render2D_Height(height)));
-
- pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfb8_clear_margins(struct vc_data *conp,
- struct display *p, int bottom_only)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- int sx, sy;
- u32 c;
-
- DTRACE;
-
- sx = conp->vc_cols * fontwidth(p); /* right margin */
- sy = conp->vc_rows * fontheight(p); /* bottom margin */
- c = attr_bgcol_ec(p, conp);
- c |= c << 8;
- c |= c << 16;
-
- if (!bottom_only) { /* right margin top->bottom */
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3ForegroundColor, c);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset
- (p->var.xoffset +
- sx)) | (PM3RectanglePosition_YOffset(p->
- var.
- yoffset)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(p->var.xres - sx)) |
- (PM3Render2D_Height(p->var.yres)));
- }
-
- /* bottom margin left -> right */
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3ForegroundColor, c);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(p->var.xoffset)) |
- (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(p->var.xres)) |
- (PM3Render2D_Height(p->var.yres - sy)));
-
- pm3fb_wait_pm3(l_fb_info);
-}
-#endif /* FBCON_HAS_CFB8 */
-#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
-static void pm3fb_cfbX_bmove(struct display *p,
- int sy, int sx,
- int dy, int dx, int height, int width)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- int x_align, o_x, o_y;
-
- DTRACE;
-
- sx = sx * fontwidth(p);
- dx = dx * fontwidth(p);
- width = width * fontwidth(p);
- sy = sy * fontheight(p);
- dy = dy * fontheight(p);
- height = height * fontheight(p);
-
- o_x = sx - dx; /*(sx > dx ) ? (sx - dx) : (dx - sx); */
- o_y = sy - dy; /*(sy > dy ) ? (sy - dy) : (dy - sy); */
-
- x_align = (sx & 0x1f);
-
- PM3_WAIT(6);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UserScissorEnable |
- PM3Config2D_ForegroundROPEnable |
- PM3Config2D_Blocking |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3ScissorMinXY,
- ((dy & 0x0fff) << 16) | (dx & 0x0fff));
- PM3_WRITE_REG(PM3ScissorMaxXY,
- (((dy + height) & 0x0fff) << 16) |
- ((dx + width) & 0x0fff));
-
- PM3_WRITE_REG(PM3FBSourceReadBufferOffset,
- PM3FBSourceReadBufferOffset_XOffset(o_x) |
- PM3FBSourceReadBufferOffset_YOffset(o_y));
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(dx - x_align)) |
- (PM3RectanglePosition_YOffset(dy)));
-
- PM3_WRITE_REG(PM3Render2D,
- ((sx > dx) ? PM3Render2D_XPositive : 0) |
- ((sy > dy) ? PM3Render2D_YPositive : 0) |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- PM3Render2D_FBSourceReadEnable |
- (PM3Render2D_Width(width + x_align)) |
- (PM3Render2D_Height(height)));
-
- pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p,
- int c, int yy, int xx)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
- u32 fgx, bgx, ldat;
- int sx, sy, i;
-
- DTRACE;
-
- if (l_fb_info->current_par->depth == 8)
- fgx = attr_fgcol(p, c);
- else if (depth2bpp(l_fb_info->current_par->depth) == 16)
- fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, c)];
- else
- fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, c)];
-
- PM3_COLOR(fgx);
-
- if (l_fb_info->current_par->depth == 8)
- bgx = attr_bgcol(p, c);
- else if (depth2bpp(l_fb_info->current_par->depth) == 16)
- bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, c)];
- else
- bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, c)];
-
- PM3_COLOR(bgx);
-
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable | PM3Config2D_OpaqueSpan);
-
- PM3_WRITE_REG(PM3ForegroundColor, fgx);
- PM3_WRITE_REG(PM3FillBackgroundColor, bgx);
-
- /* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */
- /* and 16 bits for fontwidth <= 16 */
- /* same in _putcs, same for Y and fontheight */
- if (fontwidth(p) <= 8)
- asx = 2;
- else if (fontwidth(p) <= 16)
- asx = 3; /* look OK */
- if (fontheight(p) <= 8)
- asy = 2;
- else if (fontheight(p) <= 16)
- asy = 3; /* look OK */
- else if (fontheight(p) <= 32)
- asy = 4; /* look OK */
-
- sx = xx * fontwidth(p);
- sy = yy * fontheight(p);
-
- if (fontwidth(p) <= 8)
- o_x = (8 - (sx & 0x7)) & 0x7;
- else if (fontwidth(p) <= 16)
- o_x = (16 - (sx & 0xF)) & 0xF;
- if (fontheight(p) <= 8)
- o_y = (8 - (sy & 0x7)) & 0x7;
- else if (fontheight(p) <= 16)
- o_y = (16 - (sy & 0xF)) & 0xF;
- else if (fontheight(p) <= 32)
- o_y = (32 - (sy & 0x1F)) & 0x1F;
-
- PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) | /* x_offset, y_offset in pattern */
- (1 << 18) | /* BE */
- 1 | (asx << 1) | (asy << 4) | /* address select x/y */
- (1 << 20)); /* OpaqueSpan */
-
- if (fontwidth(p) <= 8) {
- cdat = p->fontdata + (c & p->charmask) * fontheight(p);
- } else {
- cdat =
- p->fontdata +
- ((c & p->charmask) * (fontheight(p) << 1));
- }
-
- PM3_WAIT(2 + fontheight(p));
-
- for (i = 0; i < fontheight(p); i++) { /* assume fontheight <= 32 */
- if (fontwidth(p) <= 8) {
- ldat = *cdat++;
- } else { /* assume fontwidth <= 16 ATM */
-
- ldat = ((*cdat++) << 8);
- ldat |= *cdat++;
- }
- PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat);
- }
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx)) |
- (PM3RectanglePosition_YOffset(sy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_AreaStippleEnable |
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(fontwidth(p))) |
- (PM3Render2D_Height(fontheight(p))));
-
- pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p,
- const unsigned short *s, int count, int yy,
- int xx)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
- u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
- u32 fgx, bgx, ldat;
- int sx, sy, i, j;
- u16 sc;
-
- DTRACE;
-
- sc = scr_readw(s);
- if (l_fb_info->current_par->depth == 8)
- fgx = attr_fgcol(p, sc);
- else if (depth2bpp(l_fb_info->current_par->depth) == 16)
- fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, sc)];
- else
- fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, sc)];
-
- PM3_COLOR(fgx);
-
- if (l_fb_info->current_par->depth == 8)
- bgx = attr_bgcol(p, sc);
- else if (depth2bpp(l_fb_info->current_par->depth) == 16)
- bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, sc)];
- else
- bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, sc)];
-
- PM3_COLOR(bgx);
-
- PM3_WAIT(4);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0x3)) | /* Ox3 is GXcopy */
- PM3Config2D_FBWriteEnable |
- PM3Config2D_OpaqueSpan);
-
- PM3_WRITE_REG(PM3ForegroundColor, fgx);
- PM3_WRITE_REG(PM3FillBackgroundColor, bgx);
-
- /* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */
- /* and 16 bits for fontwidth <= 16 */
- /* same in _putc, same for Y and fontheight */
- if (fontwidth(p) <= 8)
- asx = 2;
- else if (fontwidth(p) <= 16)
- asx = 3; /* look OK */
- if (fontheight(p) <= 8)
- asy = 2;
- else if (fontheight(p) <= 16)
- asy = 3; /* look OK */
- else if (fontheight(p) <= 32)
- asy = 4; /* look OK */
-
- sy = yy * fontheight(p);
-
- if (fontheight(p) <= 8)
- o_y = (8 - (sy & 0x7)) & 0x7;
- else if (fontheight(p) <= 16)
- o_y = (16 - (sy & 0xF)) & 0xF;
- else if (fontheight(p) <= 32)
- o_y = (32 - (sy & 0x1F)) & 0x1F;
-
- for (j = 0; j < count; j++) {
- sc = scr_readw(s + j);
- if (fontwidth(p) <= 8)
- cdat = p->fontdata +
- (sc & p->charmask) * fontheight(p);
- else
- cdat = p->fontdata +
- ((sc & p->charmask) * fontheight(p) << 1);
-
- sx = (xx + j) * fontwidth(p);
-
- if (fontwidth(p) <= 8)
- o_x = (8 - (sx & 0x7)) & 0x7;
- else if (fontwidth(p) <= 16)
- o_x = (16 - (sx & 0xF)) & 0xF;
-
- PM3_WAIT(3 + fontheight(p));
-
- PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) | /* x_offset, y_offset in pattern */
- (1 << 18) | /* BE */
- 1 | (asx << 1) | (asy << 4) | /* address select x/y */
- (1 << 20)); /* OpaqueSpan */
-
- for (i = 0; i < fontheight(p); i++) { /* assume fontheight <= 32 */
- if (fontwidth(p) <= 8) {
- ldat = *cdat++;
- } else { /* assume fontwidth <= 16 ATM */
- ldat = ((*cdat++) << 8);
- ldat |= *cdat++;
- }
- PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat);
- }
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(sx)) |
- (PM3RectanglePosition_YOffset(sy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_AreaStippleEnable |
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(fontwidth(p))) |
- (PM3Render2D_Height(fontheight(p))));
- }
- pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfbX_revc(struct display *p, int xx, int yy)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-
- xx = xx * fontwidth(p);
- yy = yy * fontheight(p);
-
- if (l_fb_info->current_par->depth == 8)
- {
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F);
- else
- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
- }
-
- PM3_WAIT(3);
-
- PM3_WRITE_REG(PM3Config2D,
- PM3Config2D_UseConstantSource |
- PM3Config2D_ForegroundROPEnable |
- (PM3Config2D_ForegroundROP(0xa)) | /* Oxa is GXinvert */
- PM3Config2D_FBDestReadEnable |
- PM3Config2D_FBWriteEnable);
-
- PM3_WRITE_REG(PM3RectanglePosition,
- (PM3RectanglePosition_XOffset(xx)) |
- (PM3RectanglePosition_YOffset(yy)));
-
- PM3_WRITE_REG(PM3Render2D,
- PM3Render2D_XPositive |
- PM3Render2D_YPositive |
- PM3Render2D_Operation_Normal |
- PM3Render2D_SpanOperation |
- (PM3Render2D_Width(fontwidth(p))) |
- (PM3Render2D_Height(fontheight(p))));
-
- pm3fb_wait_pm3(l_fb_info);
-
- if (l_fb_info->current_par->depth == 8)
- {
- if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
- PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF);
- else
- PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
- }
-}
-
-#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
-#endif /* PM3FB_USE_ACCEL */
-/* *********************************** */
-/* ***** pre-init board(s) setup ***** */
-/* *********************************** */
-
-static void pm3fb_mode_setup(char *mode, unsigned long board_num)
-{
- struct pm3fb_info *l_fb_info = &(fb_info[board_num]);
- struct pm3fb_par *l_fb_par = &(current_par[board_num]);
- unsigned long i = 0;
-
- current_par_valid[board_num] = 0;
-
- if (!strncmp(mode, "current", 7)) {
- l_fb_info->use_current = 1; /* default w/ OpenFirmware */
- } else {
- while ((mode_base[i].name[0])
- && (!current_par_valid[board_num])) {
- if (!
- (strncmp
- (mode, mode_base[i].name,
- strlen(mode_base[i].name)))) {
- memcpy(l_fb_par, &(mode_base[i].user_mode),
- sizeof(struct pm3fb_par));
- current_par_valid[board_num] = 1;
- DPRINTK(2, "Mode set to %s\n",
- mode_base[i].name);
- }
- i++;
- }
- DASSERT(current_par_valid[board_num],
- "Valid mode on command line\n");
- }
-}
-
-static void pm3fb_pciid_setup(char *pciid, unsigned long board_num)
-{
- short l_bus = -1, l_slot = -1, l_func = -1;
- char *next;
-
- if (pciid) {
- l_bus = simple_strtoul(pciid, &next, 10);
- if (next && (next[0] == ':')) {
- pciid = next + 1;
- l_slot = simple_strtoul(pciid, &next, 10);
- if (next && (next[0] == ':')) {
- pciid = next + 1;
- l_func =
- simple_strtoul(pciid, (char **) NULL,
- 10);
- }
- }
- } else
- return;
-
- if ((l_bus >= 0) && (l_slot >= 0) && (l_func >= 0)) {
- bus[board_num] = l_bus;
- slot[board_num] = l_slot;
- func[board_num] = l_func;
- DPRINTK(2, "Board #%ld will be PciId: %hd:%hd:%hd\n",
- board_num, l_bus, l_slot, l_func);
- } else {
- DPRINTK(1, "Invalid PciId: %hd:%hd:%hd for board #%ld\n",
- l_bus, l_slot, l_func, board_num);
- }
-}
-
-static void pm3fb_font_setup(char *lf, unsigned long board_num)
-{
- unsigned long lfs = strlen(lf);
-
- if (lfs > (PM3_FONTNAME_SIZE - 1)) {
- DPRINTK(1, "Fontname %s too long\n", lf);
- return;
- }
- strlcpy(fontn[board_num], lf, lfs + 1);
-}
-
-static void pm3fb_bootdepth_setup(char *bds, unsigned long board_num)
-{
- unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
-
- if (!(depth_supported(bd))) {
- printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n",
- bds, board_num);
- return;
- }
- depth[board_num] = bd;
-}
-
-static void pm3fb_forcesize_setup(char *bds, unsigned long board_num)
-{
- unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
-
- if (bd > 64) {
- printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n",
- bds, board_num);
- return;
- }
- forcesize[board_num] = bd;
-}
-
-static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
-{
- char *next;
-
- if (!(isdigit(options[0]))) {
- (*bn) = 0;
- return (options);
- }
-
- (*bn) = simple_strtoul(options, &next, 10);
-
- if (next && (next[0] == ':') && ((*bn) >= 0)
- && ((*bn) <= PM3_MAX_BOARD)) {
- DPRINTK(2, "Board_num seen as %ld\n", (*bn));
- return (next + 1);
- } else {
- (*bn) = 0;
- DPRINTK(2, "Board_num default to %ld\n", (*bn));
- return (options);
- }
-}
-
-static void pm3fb_real_setup(char *options)
-{
- char *next;
- unsigned long i, bn;
- struct pm3fb_info *l_fb_info;
-
- DTRACE;
-
- DPRINTK(2, "Options : %s\n", options);
-
- for (i = 0; i < PM3_MAX_BOARD; i++) {
- l_fb_info = &(fb_info[i]);
- memset(l_fb_info, 0, sizeof(struct pm3fb_info));
- l_fb_info->gen.fbhw = &pm3fb_switch;
- l_fb_info->board_num = i;
- current_par_valid[i] = 0;
- slot[i] = -1;
- func[i] = -1;
- bus[i] = -1;
- disable[i] = 0;
- noaccel[i] = 0;
- fontn[i][0] = '\0';
- depth[i] = 0;
- l_fb_info->current_par = &(current_par[i]);
- }
-
- /* eat up prefix pm3fb and whatever is used as separator i.e. :,= */
- if (!strncmp(options, "pm3fb", 5)) {
- options += 5;
- while (((*options) == ',') || ((*options) == ':')
- || ((*options) == '='))
- options++;
- }
-
- while (options) {
- bn = 0;
- if ((next = strchr(options, ','))) {
- (*next) = '\0';
- next++;
- }
-
- if (!strncmp(options, "mode:", 5)) {
- options = pm3fb_boardnum_setup(options + 5, &bn);
- DPRINTK(2, "Setting mode for board #%ld\n", bn);
- pm3fb_mode_setup(options, bn);
- } else if (!strncmp(options, "off:", 4)) {
- options = pm3fb_boardnum_setup(options + 4, &bn);
- DPRINTK(2, "Disabling board #%ld\n", bn);
- disable[bn] = 1;
- } else if (!strncmp(options, "off", 3)) { /* disable everything */
- for (i = 0; i < PM3_MAX_BOARD; i++)
- disable[i] = 1;
- } else if (!strncmp(options, "disable:", 8)) {
- options = pm3fb_boardnum_setup(options + 8, &bn);
- DPRINTK(2, "Disabling board #%ld\n", bn);
- disable[bn] = 1;
- } else if (!strncmp(options, "pciid:", 6)) {
- options = pm3fb_boardnum_setup(options + 6, &bn);
- DPRINTK(2, "Setting PciID for board #%ld\n", bn);
- pm3fb_pciid_setup(options, bn);
- } else if (!strncmp(options, "noaccel:", 8)) {
- options = pm3fb_boardnum_setup(options + 8, &bn);
- noaccel[bn] = 1;
- } else if (!strncmp(options, "font:", 5)) {
- options = pm3fb_boardnum_setup(options + 5, &bn);
- pm3fb_font_setup(options, bn);
- } else if (!strncmp(options, "depth:", 6)) {
- options = pm3fb_boardnum_setup(options + 6, &bn);
- pm3fb_bootdepth_setup(options, bn);
- } else if (!strncmp(options, "printtimings", 12)) {
- printtimings = 1;
- } else if (!strncmp(options, "flatpanel:", 10)) {
- options = pm3fb_boardnum_setup(options + 10, &bn);
- flatpanel[bn] = 1;
- } else if (!strncmp(options, "forcesize:", 10)) {
- options = pm3fb_boardnum_setup(options + 10, &bn);
- pm3fb_forcesize_setup(options, bn);
- }
- options = next;
- }
-}
-
-/* ********************************************** */
-/* ***** framebuffer API standard functions ***** */
-/* ********************************************** */
-
-static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix,
- const void *par, struct fb_info_gen *info)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
- struct pm3fb_par *p = (struct pm3fb_par *) par;
-
- DTRACE;
-
- strcpy(fix->id, permedia3_name);
- fix->smem_start = (unsigned long)l_fb_info->p_fb;
- fix->smem_len = l_fb_info->fb_size;
- fix->mmio_start = (unsigned long)l_fb_info->pIOBase;
- fix->mmio_len = PM3_REGS_SIZE;
-#ifdef PM3FB_USE_ACCEL
- if (!(noaccel[l_fb_info->board_num]))
- fix->accel = FB_ACCEL_3DLABS_PERMEDIA3;
- else
-#endif /* PM3FB_USE_ACCEL */
- fix->accel = FB_ACCEL_NONE;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual =
- (p->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
- if (current_par_valid[l_fb_info->board_num])
- fix->line_length =
- l_fb_info->current_par->width *
- depth2ByPP(l_fb_info->current_par->depth);
- else
- fix->line_length = 0;
- fix->xpanstep = 64 / depth2bpp(p->depth);
- fix->ypanstep = 1;
- fix->ywrapstep = 0;
- return (0);
-}
-
-static int pm3fb_decode_var(const struct fb_var_screeninfo *var,
- void *par, struct fb_info_gen *info)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
- struct pm3fb_par *p = (struct pm3fb_par *) par;
- struct pm3fb_par temp_p;
- u32 xres;
-
- DTRACE;
-
- DASSERT((var != NULL), "fb_var_screeninfo* not NULL");
- DASSERT((p != NULL), "pm3fb_par* not NULL");
- DASSERT((l_fb_info != NULL), "pm3fb_info* not NULL");
-
- memset(&temp_p, 0, sizeof(struct pm3fb_par));
- temp_p.width = (var->xres_virtual + 7) & ~7;
- temp_p.height = var->yres_virtual;
-
- if (!(depth_supported(var->bits_per_pixel))) /* round unsupported up to a multiple of 8 */
- temp_p.depth = depth2bpp(var->bits_per_pixel);
- else
- temp_p.depth = var->bits_per_pixel;
-
- temp_p.depth = (temp_p.depth > 32) ? 32 : temp_p.depth; /* max 32 */
- temp_p.depth = (temp_p.depth == 24) ? 32 : temp_p.depth; /* 24 unsupported, round-up to 32 */
-
- if ((temp_p.depth == 16) && (var->red.length == 5) && (var->green.length == 5) && (var->blue.length == 5))
- temp_p.depth = 15; /* RGBA 5551 is stored as depth 15 */
-
- if ((temp_p.depth == 16) && (var->red.length == 4) && (var->green.length == 4) && (var->blue.length == 4))
- temp_p.depth = 12; /* RGBA 4444 is stored as depth 12 */
-
-
- DPRINTK(2,
- "xres: %d, yres: %d, vxres: %d, vyres: %d ; xoffset:%d, yoffset: %d\n",
- var->xres, var->yres, var->xres_virtual, var->yres_virtual,
- var->xoffset, var->yoffset);
-
- xres = (var->xres + 31) & ~31;
- if (temp_p.width < xres + var->xoffset)
- temp_p.width = xres + var->xoffset;
- if (temp_p.height < var->yres + var->yoffset)
- temp_p.height = var->yres + var->yoffset;
-
- if (temp_p.width > 2048) {
- DPRINTK(1, "virtual width not supported: %u\n",
- temp_p.width);
- return (-EINVAL);
- }
- if (var->yres < 200) {
- DPRINTK(1, "height not supported: %u\n", (u32) var->yres);
- return (-EINVAL);
- }
- if (temp_p.height < 200 || temp_p.height > 4095) {
- DPRINTK(1, "virtual height not supported: %u\n",
- temp_p.height);
- return (-EINVAL);
- }
- if (!(depth_supported(temp_p.depth))) {
- DPRINTK(1, "depth not supported: %u\n", temp_p.depth);
- return (-EINVAL);
- }
- if ((temp_p.width * temp_p.height * depth2ByPP(temp_p.depth)) >
- l_fb_info->fb_size) {
- DPRINTK(1, "no memory for screen (%ux%ux%u)\n",
- temp_p.width, temp_p.height, temp_p.depth);
- return (-EINVAL);
- }
-
- if ((!var->pixclock) ||
- (!var->right_margin) ||
- (!var->hsync_len) ||
- (!var->left_margin) ||
- (!var->lower_margin) ||
- (!var->vsync_len) || (!var->upper_margin)
- ) {
- unsigned long i = 0, done = 0;
- printk(KERN_WARNING "pm3fb: refusing to use a likely wrong timing\n");
-
- while ((mode_base[i].user_mode.width) && !done) {
- if ((mode_base[i].user_mode.width == temp_p.width)
- && (mode_base[i].user_mode.height ==
- temp_p.height)) {
- printk(KERN_NOTICE "pm3fb: using close match %s\n",
- mode_base[i].name);
- temp_p = mode_base[i].user_mode;
- done = 1;
- }
- i++;
- }
- if (!done)
- return (-EINVAL);
- } else {
- temp_p.pixclock = PICOS2KHZ(var->pixclock);
- if (temp_p.pixclock > PM3_MAX_PIXCLOCK) {
- DPRINTK(1, "pixclock too high (%uKHz)\n",
- temp_p.pixclock);
- return (-EINVAL);
- }
-
- temp_p.hsstart = var->right_margin;
- temp_p.hsend = var->right_margin + var->hsync_len;
- temp_p.hbend =
- var->right_margin + var->hsync_len + var->left_margin;
- temp_p.htotal = xres + temp_p.hbend;
-
- temp_p.vsstart = var->lower_margin;
- temp_p.vsend = var->lower_margin + var->vsync_len;
- temp_p.vbend =
- var->lower_margin + var->vsync_len + var->upper_margin;
- temp_p.vtotal = var->yres + temp_p.vbend;
-
- temp_p.stride = temp_p.width;
-
- DPRINTK(2, "Using %d * %d, %d Khz, stride is %08x\n",
- temp_p.width, temp_p.height, temp_p.pixclock,
- temp_p.stride);
-
- temp_p.base =
- pm3fb_Shiftbpp(l_fb_info, temp_p.depth,
- (var->yoffset * xres) + var->xoffset);
-
- temp_p.video = 0;
-
- if (var->sync & FB_SYNC_HOR_HIGH_ACT)
- temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;
- else
- temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_LOW;
-
- if (var->sync & FB_SYNC_VERT_HIGH_ACT)
- temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;
- else
- temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_LOW;
-
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
- DPRINTK(1, "Interlaced mode not supported\n\n");
- return (-EINVAL);
- }
-
- if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
- temp_p.video |= PM3VideoControl_LINE_DOUBLE_ON;
- else
- temp_p.video |= PM3VideoControl_LINE_DOUBLE_OFF;
-
- if (var->activate == FB_ACTIVATE_NOW)
- temp_p.video |= PM3VideoControl_ENABLE;
- else {
- temp_p.video |= PM3VideoControl_DISABLE;
- DPRINTK(2, "PM3Video disabled\n");
- }
-
- switch (temp_p.depth) {
- case 8:
- temp_p.video |= PM3VideoControl_PIXELSIZE_8BIT;
- break;
- case 12:
- case 15:
- case 16:
- temp_p.video |= PM3VideoControl_PIXELSIZE_16BIT;
- break;
- case 32:
- temp_p.video |= PM3VideoControl_PIXELSIZE_32BIT;
- break;
- default:
- DPRINTK(1, "Unsupported depth\n");
- break;
- }
- }
- (*p) = temp_p;
-
-#ifdef PM3FB_USE_ACCEL
- if (var->accel_flags & FB_ACCELF_TEXT)
- noaccel[l_fb_info->board_num] = 0;
- else
- noaccel[l_fb_info->board_num] = 1;
-#endif /* PM3FB_USE_ACCEL */
-
- return (0);
-}
-
-static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d)
-{
- switch (d) {
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ switch(var->bits_per_pixel) {
case 8:
var->red.length = var->green.length = var->blue.length = 8;
var->red.offset = var->green.offset = var->blue.offset = 0;
- var->transp.offset = var->transp.length = 0;
break;
-
case 12:
- var->red.offset = 8;
- var->red.length = 4;
+ var->red.offset = 8;
+ var->red.length = 4;
var->green.offset = 4;
var->green.length = 4;
- var->blue.offset = 0;
- var->blue.length = 4;
+ var->blue.offset = 0;
+ var->blue.length = 4;
var->transp.offset = 12;
var->transp.length = 4;
- break;
-
case 15:
- var->red.offset = 10;
- var->red.length = 5;
+ var->red.offset = 10;
+ var->red.length = 5;
var->green.offset = 5;
var->green.length = 5;
- var->blue.offset = 0;
- var->blue.length = 5;
+ var->blue.offset = 0;
+ var->blue.length = 5;
var->transp.offset = 15;
var->transp.length = 1;
break;
-
case 16:
- var->red.offset = 11;
- var->red.length = 5;
+ var->red.offset = 11;
+ var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = var->transp.length = 0;
+ var->blue.offset = 0;
+ var->blue.length = 5;
break;
-
case 32:
var->transp.offset = 24;
- var->red.offset = 16;
+ var->transp.length = 8;
+ var->red.offset = 16;
var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = var->green.length =
- var->blue.length = var->transp.length = 8;
+ var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
break;
-
default:
- DPRINTK(1, "Unsupported depth %ld\n", d);
- break;
+ DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+ return -EINVAL;
}
-}
-
-static int pm3fb_encode_var(struct fb_var_screeninfo *var,
- const void *par, struct fb_info_gen *info)
-{
- struct pm3fb_par *p = (struct pm3fb_par *) par;
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
- u32 base;
-
- DTRACE;
-
- DASSERT((var != NULL), "fb_var_screeninfo* not NULL");
- DASSERT((p != NULL), "pm3fb_par* not NULL");
- DASSERT((info != NULL), "fb_info_gen* not NULL");
-
- memset(var, 0, sizeof(struct fb_var_screeninfo));
-
-#ifdef PM3FB_USE_ACCEL
- if (!(noaccel[l_fb_info->board_num]))
- var->accel_flags |= FB_ACCELF_TEXT;
-#endif /* PM3FB_USE_ACCEL */
-
- var->xres_virtual = p->width;
- var->yres_virtual = p->height;
- var->xres = p->htotal - p->hbend;
- var->yres = p->vtotal - p->vbend;
-
- DPRINTK(2, "xres = %d, yres : %d\n", var->xres, var->yres);
-
- var->right_margin = p->hsstart;
- var->hsync_len = p->hsend - p->hsstart;
- var->left_margin = p->hbend - p->hsend;
- var->lower_margin = p->vsstart;
- var->vsync_len = p->vsend - p->vsstart;
- var->upper_margin = p->vbend - p->vsend;
- var->bits_per_pixel = depth2bpp(p->depth);
-
- pm3fb_encode_depth(var, p->depth);
-
- base = pm3fb_Unshiftbpp(l_fb_info, p->depth, p->base);
-
- var->xoffset = base % var->xres;
- var->yoffset = base / var->xres;
-
var->height = var->width = -1;
- var->pixclock = KHZ2PICOS(p->pixclock);
-
- if ((p->video & PM3VideoControl_HSYNC_MASK) ==
- PM3VideoControl_HSYNC_ACTIVE_HIGH)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if ((p->video & PM3VideoControl_VSYNC_MASK) ==
- PM3VideoControl_VSYNC_ACTIVE_HIGH)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
- if (p->video & PM3VideoControl_LINE_DOUBLE_ON)
- var->vmode = FB_VMODE_DOUBLE;
-
- return (0);
-}
-
-static void pm3fb_get_par(void *par, struct fb_info_gen *info)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
- DTRACE;
-
- if (!current_par_valid[l_fb_info->board_num]) {
- if (l_fb_info->use_current)
- pm3fb_read_mode(l_fb_info, l_fb_info->current_par);
- else
- memcpy(l_fb_info->current_par,
- &(mode_base[0].user_mode),
- sizeof(struct pm3fb_par));
- current_par_valid[l_fb_info->board_num] = 1;
+ if (var->xres != var->xres_virtual) {
+ DPRINTK("virtual x resolution != physical x resolution not supported\n");
+ return -EINVAL;
}
- *((struct pm3fb_par *) par) = *(l_fb_info->current_par);
-}
-static void pm3fb_set_par(const void *par, struct fb_info_gen *info)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
- DTRACE;
-
- *(l_fb_info->current_par) = *((struct pm3fb_par *) par);
- current_par_valid[l_fb_info->board_num] = 1;
-
- pm3fb_write_mode(l_fb_info);
-
-#ifdef PM3FB_USE_ACCEL
- pm3fb_init_engine(l_fb_info);
-#endif /* PM3FB_USE_ACCEL */
-}
-
-static void pm3fb_set_color(struct pm3fb_info *l_fb_info,
- unsigned char regno, unsigned char r,
- unsigned char g, unsigned char b)
-{
- DTRACE;
-
- PM3_SLOW_WRITE_REG(PM3RD_PaletteWriteAddress, regno);
- PM3_SLOW_WRITE_REG(PM3RD_PaletteData, r);
- PM3_SLOW_WRITE_REG(PM3RD_PaletteData, g);
- PM3_SLOW_WRITE_REG(PM3RD_PaletteData, b);
-}
-
-static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
- unsigned *blue, unsigned *transp,
- struct fb_info *info)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
- DTRACE;
-
- if (regno < 256) {
- *red =
- l_fb_info->palette[regno].red << 8 | l_fb_info->
- palette[regno].red;
- *green =
- l_fb_info->palette[regno].green << 8 | l_fb_info->
- palette[regno].green;
- *blue =
- l_fb_info->palette[regno].blue << 8 | l_fb_info->
- palette[regno].blue;
- *transp =
- l_fb_info->palette[regno].transp << 8 | l_fb_info->
- palette[regno].transp;
+ if (var->yres > var->yres_virtual) {
+ DPRINTK("virtual y resolution < physical y resolution not possible\n");
+ return -EINVAL;
}
- return (regno > 255);
+
+ if (var->xoffset) {
+ DPRINTK("xoffset not supported\n");
+ return -EINVAL;
+ }
+
+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ DPRINTK("interlace not supported\n");
+ return -EINVAL;
+ }
+
+ var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */
+ lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
+
+ if (var->xres < 200 || var->xres > 2048) {
+ DPRINTK("width not supported: %u\n", var->xres);
+ return -EINVAL;
+ }
+
+ if (var->yres < 200 || var->yres > 4095) {
+ DPRINTK("height not supported: %u\n", var->yres);
+ return -EINVAL;
+ }
+
+ if (lpitch * var->yres_virtual > info->fix.smem_len) {
+ DPRINTK("no memory for screen (%ux%ux%u)\n",
+ var->xres, var->yres_virtual, var->bits_per_pixel);
+ return -EINVAL;
+ }
+
+ if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) {
+ DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
+ return -EINVAL;
+ }
+
+ var->accel_flags = 0; /* Can't mmap if this is on */
+
+ DPRINTK("Checking graphics mode at %dx%d depth %d\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ return 0;
+}
+
+static int pm3fb_set_par(struct fb_info *info)
+{
+ struct pm3_par *par = info->par;
+ const u32 xres = (info->var.xres + 31) & ~31;
+ const int depth = (info->var.bits_per_pixel + 7) & ~7;
+
+ par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
+ (info->var.yoffset * xres)
+ + info->var.xoffset);
+ par->video = 0;
+
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;
+ else
+ par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW;
+
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;
+ else
+ par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW;
+
+ if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+ par->video |= PM3VideoControl_LINE_DOUBLE_ON;
+ else
+ par->video |= PM3VideoControl_LINE_DOUBLE_OFF;
+
+ if (info->var.activate == FB_ACTIVATE_NOW)
+ par->video |= PM3VideoControl_ENABLE;
+ else {
+ par->video |= PM3VideoControl_DISABLE;
+ DPRINTK("PM3Video disabled\n");
+ }
+ switch (depth) {
+ case 8:
+ par->video |= PM3VideoControl_PIXELSIZE_8BIT;
+ break;
+ case 12:
+ case 15:
+ case 16:
+ par->video |= PM3VideoControl_PIXELSIZE_16BIT;
+ break;
+ case 32:
+ par->video |= PM3VideoControl_PIXELSIZE_32BIT;
+ break;
+ default:
+ DPRINTK("Unsupported depth\n");
+ break;
+ }
+
+ info->fix.visual =
+ (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+ info->fix.line_length = ((info->var.xres_virtual + 7) & ~7)
+ * depth / 8;
+
+/* pm3fb_clear_memory(info, 0);*/
+ pm3fb_clear_colormap(par, 0, 0, 0);
+ PM3_WRITE_DAC_REG(par, PM3RD_CursorMode,
+ PM3RD_CursorMode_CURSOR_DISABLE);
+ pm3fb_write_mode(info);
+ return 0;
}
static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
+ struct pm3_par *par = info->par;
- DTRACE;
+ if (regno >= 256) /* no. of hw registers */
+ return -EINVAL;
- if (regno < 16) {
- switch (l_fb_info->current_par->depth) {
-#ifdef FBCON_HAS_CFB8
+ /* grayscale works only partially under directcolor */
+ if (info->var.grayscale) {
+ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ /* Directcolor:
+ * var->{color}.offset contains start of bitfield
+ * var->{color}.length contains length of bitfield
+ * {hardwarespecific} contains width of DAC
+ * pseudo_palette[X] is programmed to (X << red.offset) |
+ * (X << green.offset) |
+ * (X << blue.offset)
+ * RAMDAC[X] is programmed to (red, green, blue)
+ * color depth = SUM(var->{color}.length)
+ *
+ * Pseudocolor:
+ * var->{color}.offset is 0
+ * var->{color}.length contains width of DAC or the number of unique
+ * colors available (color depth)
+ * pseudo_palette is not used
+ * RAMDAC[X] is programmed to (red, green, blue)
+ * color depth = var->{color}.length
+ */
+
+ /*
+ * This is the point where the color is converted to something that
+ * is acceptable by the hardware.
+ */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
+#undef CNVT_TOHW
+
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ u32 v;
+
+ if (regno >= 16)
+ return -EINVAL;
+
+ v = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ switch (info->var.bits_per_pixel) {
case 8:
break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 12:
- l_fb_info->cmap.cmap12[regno] =
- (((u32) red & 0xf000) >> 4) |
- (((u32) green & 0xf000) >> 8) |
- (((u32) blue & 0xf000) >> 12);
- break;
-
- case 15:
- l_fb_info->cmap.cmap15[regno] =
- (((u32) red & 0xf800) >> 1) |
- (((u32) green & 0xf800) >> 6) |
- (((u32) blue & 0xf800) >> 11);
- break;
-
case 16:
- l_fb_info->cmap.cmap16[regno] =
- ((u32) red & 0xf800) |
- (((u32) green & 0xfc00) >> 5) |
- (((u32) blue & 0xf800) >> 11);
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
+ case 24:
case 32:
- l_fb_info->cmap.cmap32[regno] =
- (((u32) transp & 0xff00) << 16) |
- (((u32) red & 0xff00) << 8) |
- (((u32) green & 0xff00)) |
- (((u32) blue & 0xff00) >> 8);
- break;
-#endif
- default:
- DPRINTK(1, "bad depth %u\n",
- l_fb_info->current_par->depth);
+ ((u32*)(info->pseudo_palette))[regno] = v;
break;
}
+ return 0;
}
- if (regno < 256) {
- l_fb_info->palette[regno].red = red >> 8;
- l_fb_info->palette[regno].green = green >> 8;
- l_fb_info->palette[regno].blue = blue >> 8;
- l_fb_info->palette[regno].transp = transp >> 8;
- if (l_fb_info->current_par->depth == 8)
- pm3fb_set_color(l_fb_info, regno, red >> 8,
- green >> 8, blue >> 8);
- }
- return (regno > 255);
+ else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+ pm3fb_set_color(par, regno, red, green, blue);
+
+ return 0;
}
-static int pm3fb_blank(int blank_mode, struct fb_info_gen *info)
+static int pm3fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
- u32 video;
+ struct pm3_par *par = info->par;
+ const u32 xres = (var->xres + 31) & ~31;
- DTRACE;
+ par->base = pm3fb_shift_bpp(var->bits_per_pixel,
+ (var->yoffset * xres)
+ + var->xoffset);
+ PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
+ return 0;
+}
- if (!current_par_valid[l_fb_info->board_num])
- return (1);
-
- video = l_fb_info->current_par->video;
+static int pm3fb_blank(int blank_mode, struct fb_info *info)
+{
+ struct pm3_par *par = info->par;
+ u32 video = par->video;
/*
* Oxygen VX1 - it appears that setting PM3VideoControl and
@@ -3181,454 +663,345 @@
video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
PM3VideoControl_VSYNC_ACTIVE_HIGH;
- if (blank_mode > 0) {
- switch (blank_mode - 1) {
-
- case VESA_NO_BLANKING: /* FIXME */
- video = video & ~(PM3VideoControl_ENABLE);
- break;
-
- case VESA_HSYNC_SUSPEND:
- video = video & ~(PM3VideoControl_HSYNC_MASK |
- PM3VideoControl_BLANK_ACTIVE_LOW);
- break;
- case VESA_VSYNC_SUSPEND:
- video = video & ~(PM3VideoControl_VSYNC_MASK |
- PM3VideoControl_BLANK_ACTIVE_LOW);
- break;
- case VESA_POWERDOWN:
- video = video & ~(PM3VideoControl_HSYNC_MASK |
- PM3VideoControl_VSYNC_MASK |
- PM3VideoControl_BLANK_ACTIVE_LOW);
- break;
- default:
- DPRINTK(1, "Unsupported blanking %d\n",
- blank_mode);
- return (1);
- break;
- }
- }
-
- PM3_SLOW_WRITE_REG(PM3VideoControl, video);
-
- return (0);
-}
-
-static void pm3fb_set_disp(const void *par, struct display *disp,
- struct fb_info_gen *info)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
- struct pm3fb_par *p = (struct pm3fb_par *) par;
- u32 flags;
-
- DTRACE;
-
- local_irq_save(flags);
- info->info.screen_base = l_fb_info->v_fb;
- switch (p->depth) {
-#ifdef FBCON_HAS_CFB8
- case 8:
-#ifdef PM3FB_USE_ACCEL
- if (!(noaccel[l_fb_info->board_num]))
- disp->dispsw = &pm3fb_cfb8;
- else
-#endif /* PM3FB_USE_ACCEL */
- disp->dispsw = &fbcon_cfb8;
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ video = video | PM3VideoControl_ENABLE;
break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 12:
-#ifdef PM3FB_USE_ACCEL
- if (!(noaccel[l_fb_info->board_num]))
- disp->dispsw = &pm3fb_cfb16;
- else
-#endif /* PM3FB_USE_ACCEL */
- disp->dispsw = &fbcon_cfb16;
- disp->dispsw_data = l_fb_info->cmap.cmap12;
+ case FB_BLANK_NORMAL: /* FIXME */
+ video = video & ~(PM3VideoControl_ENABLE);
break;
- case 15:
-#ifdef PM3FB_USE_ACCEL
- if (!(noaccel[l_fb_info->board_num]))
- disp->dispsw = &pm3fb_cfb16;
- else
-#endif /* PM3FB_USE_ACCEL */
- disp->dispsw = &fbcon_cfb16;
- disp->dispsw_data = l_fb_info->cmap.cmap15;
+ case FB_BLANK_HSYNC_SUSPEND:
+ video = video & ~(PM3VideoControl_HSYNC_MASK |
+ PM3VideoControl_BLANK_ACTIVE_LOW);
break;
- case 16:
-#ifdef PM3FB_USE_ACCEL
- if (!(noaccel[l_fb_info->board_num]))
- disp->dispsw = &pm3fb_cfb16;
- else
-#endif /* PM3FB_USE_ACCEL */
- disp->dispsw = &fbcon_cfb16;
- disp->dispsw_data = l_fb_info->cmap.cmap16;
+ case FB_BLANK_VSYNC_SUSPEND:
+ video = video & ~(PM3VideoControl_VSYNC_MASK |
+ PM3VideoControl_BLANK_ACTIVE_LOW);
break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
-#ifdef PM3FB_USE_ACCEL
- if (!(noaccel[l_fb_info->board_num]))
- disp->dispsw = &pm3fb_cfb32;
- else
-#endif /* PM3FB_USE_ACCEL */
- disp->dispsw = &fbcon_cfb32;
- disp->dispsw_data = l_fb_info->cmap.cmap32;
+ case FB_BLANK_POWERDOWN:
+ video = video & ~(PM3VideoControl_HSYNC_MASK |
+ PM3VideoControl_VSYNC_MASK |
+ PM3VideoControl_BLANK_ACTIVE_LOW);
break;
-#endif /* FBCON_HAS_CFB32 */
default:
- disp->dispsw = &fbcon_dummy;
- DPRINTK(1, "Invalid depth, using fbcon_dummy\n");
- break;
- }
- local_irq_restore(flags);
-}
-
-/* */
-static void pm3fb_detect(void)
-{
- struct pci_dev *dev_array[PM3_MAX_BOARD];
- struct pci_dev *dev = NULL;
- struct pm3fb_info *l_fb_info = &(fb_info[0]);
- unsigned long i, j, done;
-
- DTRACE;
-
- for (i = 0; i < PM3_MAX_BOARD; i++) {
- dev_array[i] = NULL;
- fb_info[i].dev = NULL;
+ DPRINTK("Unsupported blanking %d\n", blank_mode);
+ return 1;
}
- dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
- PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
+ PM3_SLOW_WRITE_REG(par,PM3VideoControl, video);
- for (i = 0; ((i < PM3_MAX_BOARD) && dev); i++) {
- dev_array[i] = dev;
- dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
- PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
- }
-
- if (dev) { /* more than PM3_MAX_BOARD */
- printk(KERN_WARNING "pm3fb: Warning: more than %d boards found\n",
- PM3_MAX_BOARD);
- }
-
- if (!dev_array[0]) { /* not a single board, abort */
- return;
- }
-
- /* allocate user-defined boards */
- for (i = 0; i < PM3_MAX_BOARD; i++) {
- if ((bus[i] >= 0) && (slot[i] >= 0) && (func[i] >= 0)) {
- for (j = 0; j < PM3_MAX_BOARD; j++) {
- if ((dev_array[j] != NULL) &&
- (dev_array[j]->bus->number == bus[i])
- && (PCI_SLOT(dev_array[j]->devfn) ==
- slot[i])
- && (PCI_FUNC(dev_array[j]->devfn) ==
- func[i])) {
- fb_info[i].dev = dev_array[j];
- dev_array[j] = NULL;
- }
- }
- }
- }
- /* allocate remaining boards */
- for (i = 0; i < PM3_MAX_BOARD; i++) {
- if (fb_info[i].dev == NULL) {
- done = 0;
- for (j = 0; ((j < PM3_MAX_BOARD) && (!done)); j++) {
- if (dev_array[j] != NULL) {
- fb_info[i].dev = dev_array[j];
- dev_array[j] = NULL;
- done = 1;
- }
- }
- }
- }
-
- /* at that point, all PCI Permedia3 are detected and allocated */
- /* now, initialize... or not */
- for (i = 0; i < PM3_MAX_BOARD; i++) {
- l_fb_info = &(fb_info[i]);
- if (l_fb_info->dev && !disable[i]) { /* PCI device was found and not disabled by user */
- DPRINTK(2,
- "found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n",
- (unsigned long) l_fb_info->dev,
- (unsigned long) l_fb_info->dev->vendor,
- (unsigned long) l_fb_info->dev->device,
- (unsigned long)
- pci_resource_start(l_fb_info->dev, 0),
- (unsigned long)
- pci_resource_start(l_fb_info->dev, 1),
- (unsigned long)
- pci_resource_start(l_fb_info->dev, 2),
- (unsigned long)
- pci_resource_start(l_fb_info->dev, 3),
- (unsigned long)
- pci_resource_start(l_fb_info->dev, 4),
- (unsigned long)
- pci_resource_start(l_fb_info->dev, 5),
- (unsigned long) l_fb_info->dev->irq);
-
- l_fb_info->pIOBase =
- (unsigned char *)
- pci_resource_start(l_fb_info->dev, 0);
-#ifdef __BIG_ENDIAN
- l_fb_info->pIOBase += PM3_REGS_SIZE;
-#endif
- l_fb_info->vIOBase = (unsigned char *) -1;
- l_fb_info->p_fb =
- (unsigned char *)
- pci_resource_start(l_fb_info->dev, 1);
- l_fb_info->v_fb = (unsigned char *) -1;
-
- if (!request_mem_region
- ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
- "pm3fb")) {
- printk
- (KERN_ERR "pm3fb: Error: couldn't request framebuffer memory, board #%ld\n",
- l_fb_info->board_num);
- continue;
- }
- if (!request_mem_region
- ((unsigned long)l_fb_info->pIOBase, PM3_REGS_SIZE,
- "pm3fb I/O regs")) {
- printk
- (KERN_ERR "pm3fb: Error: couldn't request IObase memory, board #%ld\n",
- l_fb_info->board_num);
- continue;
- }
- if (forcesize[l_fb_info->board_num])
- l_fb_info->fb_size = forcesize[l_fb_info->board_num];
-
- l_fb_info->fb_size =
- pm3fb_size_memory(l_fb_info);
- if (l_fb_info->fb_size) {
- (void) pci_enable_device(l_fb_info->dev);
- pm3fb_common_init(l_fb_info);
- } else
- printk(KERN_ERR "pm3fb: memory problem, not enabling board #%ld\n", l_fb_info->board_num);
- }
- }
-}
-
-static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
- struct fb_info_gen *info)
-{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
- DTRACE;
-
- if (!current_par_valid[l_fb_info->board_num])
- return -EINVAL;
-
- l_fb_info->current_par->base = /* in 128 bits chunk - i.e. AFTER Shiftbpp */
- pm3fb_Shiftbpp(l_fb_info,
- l_fb_info->current_par->depth,
- (var->yoffset * l_fb_info->current_par->width) +
- var->xoffset);
- PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base);
return 0;
}
-static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+ /*
+ * Frame buffer operations
+ */
+
+static struct fb_ops pm3fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = pm3fb_check_var,
+ .fb_set_par = pm3fb_set_par,
+ .fb_setcolreg = pm3fb_setcolreg,
+ .fb_pan_display = pm3fb_pan_display,
+ .fb_fillrect = cfb_fillrect, /* Needed !!! */
+ .fb_copyarea = cfb_copyarea, /* Needed !!! */
+ .fb_imageblit = cfb_imageblit, /* Needed !!! */
+ .fb_blank = pm3fb_blank,
+};
+
+/* ------------------------------------------------------------------------- */
+
+ /*
+ * Initialization
+ */
+
+/* mmio register are already mapped when this function is called */
+/* the pm3fb_fix.smem_start is also set */
+static unsigned long pm3fb_size_memory(struct pm3_par *par)
{
- struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
- u32 cm, i;
-#ifdef PM3FB_MASTER_DEBUG
- char cc[3];
-#endif /* PM3FB_MASTER_DEBUG */
+ unsigned long memsize = 0, tempBypass, i, temp1, temp2;
+ unsigned char __iomem *screen_mem;
- switch(cmd)
+ pm3fb_fix.smem_len = 64 * 1024 * 1024; /* request full aperture size */
+ /* Linear frame buffer - request region and map it. */
+ if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
+ "pm3fb smem")) {
+ printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
+ return 0;
+ }
+ screen_mem =
+ ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ if (!screen_mem) {
+ printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
+ release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ return 0;
+ }
+
+ /* TODO: card-specific stuff, *before* accessing *any* FB memory */
+ /* For Appian Jeronimo 2000 board second head */
+
+ tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask);
+
+ DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
+
+ PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
+
+ /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
+ for (i = 0; i < 32; i++) {
+ fb_writel(i * 0x00345678,
+ (screen_mem + (i * 1048576)));
+ mb();
+ temp1 = fb_readl((screen_mem + (i * 1048576)));
+
+ /* Let's check for wrapover, write will fail at 16MB boundary */
+ if (temp1 == (i * 0x00345678))
+ memsize = i;
+ else
+ break;
+ }
+
+ DPRINTK("First detect pass already got %ld MB\n", memsize + 1);
+
+ if (memsize + 1 == i) {
+ for (i = 0; i < 32; i++) {
+ /* Clear first 32MB ; 0 is 0, no need to byteswap */
+ writel(0x0000000,
+ (screen_mem + (i * 1048576)));
+ mb();
+ }
+
+ for (i = 32; i < 64; i++) {
+ fb_writel(i * 0x00345678,
+ (screen_mem + (i * 1048576)));
+ mb();
+ temp1 =
+ fb_readl((screen_mem + (i * 1048576)));
+ temp2 =
+ fb_readl((screen_mem + ((i - 32) * 1048576)));
+ /* different value, different RAM... */
+ if ((temp1 == (i * 0x00345678)) && (temp2 == 0))
+ memsize = i;
+ else
+ break;
+ }
+ }
+ DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
+
+ PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
+
+ iounmap(screen_mem);
+ release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ memsize = 1048576 * (memsize + 1);
+
+ DPRINTK("Returning 0x%08lx bytes\n", memsize);
+
+ return memsize;
+}
+
+static int __devinit pm3fb_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ struct fb_info *info;
+ struct pm3_par *par;
+ struct device* device = &dev->dev; /* for pci drivers */
+ int err, retval = -ENXIO;
+
+ err = pci_enable_device(dev);
+ if (err) {
+ printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err);
+ return err;
+ }
+ /*
+ * Dynamically allocate info and par
+ */
+ info = framebuffer_alloc(sizeof(struct pm3_par), device);
+
+ if (!info)
+ return -ENOMEM;
+ par = info->par;
+
+ /*
+ * Here we set the screen_base to the virtual memory address
+ * for the framebuffer.
+ */
+ pm3fb_fix.mmio_start = pci_resource_start(dev, 0);
+ pm3fb_fix.mmio_len = PM3_REGS_SIZE;
+
+ /* Registers - request region and map it. */
+ if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len,
+ "pm3fb regbase")) {
+ printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n");
+ goto err_exit_neither;
+ }
+ par->v_regs =
+ ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+ if (!par->v_regs) {
+ printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n",
+ pm3fb_fix.id);
+ release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+ goto err_exit_neither;
+ }
+
+#if defined(__BIG_ENDIAN)
+ pm3fb_fix.mmio_start += PM3_REGS_SIZE;
+ DPRINTK("Adjusting register base for big-endian.\n");
+#endif
+ /* Linear frame buffer - request region and map it. */
+ pm3fb_fix.smem_start = pci_resource_start(dev, 1);
+ pm3fb_fix.smem_len = pm3fb_size_memory(par);
+ if (!pm3fb_fix.smem_len)
{
-#ifdef PM3FB_MASTER_DEBUG
- case PM3FBIO_CLEARMEMORY:
- if (copy_from_user(&cm, (void *)arg, sizeof(u32)))
- return(-EFAULT);
- pm3fb_clear_memory(l_fb_info, cm);
- return(0);
- break;
+ printk(KERN_WARNING "pm3fb: Can't find memory on board.\n");
+ goto err_exit_mmio;
+ }
+ if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
+ "pm3fb smem")) {
+ printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
+ goto err_exit_mmio;
+ }
+ info->screen_base =
+ ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ if (!info->screen_base) {
+ printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
+ release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ goto err_exit_mmio;
+ }
+ info->screen_size = pm3fb_fix.smem_len;
- case PM3FBIO_CLEARCMAP:
- if (copy_from_user(cc, (void*)arg, 3 * sizeof(char)))
- return(-EFAULT);
- pm3fb_clear_colormap(l_fb_info, cc[0], cc[1], cc[2]);
- return(0);
- break;
-#endif /* PM3FB_MASTER_DEBUG */
+ info->fbops = &pm3fb_ops;
- case PM3FBIO_RESETCHIP:
- cm = 1;
- PM3_SLOW_WRITE_REG(PM3ResetStatus, 1);
- for (i = 0 ; (i < 10000) && cm ; i++)
- {
- PM3_DELAY(10);
- cm = PM3_READ_REG(PM3ResetStatus);
- }
- if (cm)
- {
- printk(KERN_ERR "pm3fb: chip reset failed with status 0x%x\n", cm);
- return(-EIO);
- }
- /* first thing first, reload memory timings */
- pm3fb_write_memory_timings(l_fb_info);
-#ifdef PM3FB_USE_ACCEL
- pm3fb_init_engine(l_fb_info);
-#endif /* PM3FB_USE_ACCEL */
- pm3fb_write_mode(l_fb_info);
- return(0);
- break;
+ par->video = PM3_READ_REG(par, PM3VideoControl);
- default:
- DPRINTK(2, "unknown ioctl: %d (%x)\n", cmd, cmd);
- return(-EINVAL);
+ info->fix = pm3fb_fix;
+ info->pseudo_palette = par->palette;
+ info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/
+
+ /*
+ * This should give a reasonable default video mode. The following is
+ * done when we can set a video mode.
+ */
+ if (!mode_option)
+ mode_option = "640x480@60";
+
+ retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+
+ if (!retval || retval == 4) {
+ retval = -EINVAL;
+ goto err_exit_both;
+ }
+
+ /* This has to been done !!! */
+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+ retval = -ENOMEM;
+ goto err_exit_both;
+ }
+
+ /*
+ * For drivers that can...
+ */
+ pm3fb_check_var(&info->var, info);
+
+ if (register_framebuffer(info) < 0) {
+ retval = -EINVAL;
+ goto err_exit_all;
+ }
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+ info->fix.id);
+ pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+ return 0;
+
+ err_exit_all:
+ fb_dealloc_cmap(&info->cmap);
+ err_exit_both:
+ iounmap(info->screen_base);
+ release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ err_exit_mmio:
+ iounmap(par->v_regs);
+ release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+ err_exit_neither:
+ framebuffer_release(info);
+ return retval;
+}
+
+ /*
+ * Cleanup
+ */
+static void __devexit pm3fb_remove(struct pci_dev *dev)
+{
+ struct fb_info *info = pci_get_drvdata(dev);
+
+ if (info) {
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct pm3_par *par = info->par;
+
+ unregister_framebuffer(info);
+ fb_dealloc_cmap(&info->cmap);
+
+ iounmap(info->screen_base);
+ release_mem_region(fix->smem_start, fix->smem_len);
+ iounmap(par->v_regs);
+ release_mem_region(fix->mmio_start, fix->mmio_len);
+
+ pci_set_drvdata(dev, NULL);
+ framebuffer_release(info);
}
}
-/* ****************************************** */
-/* ***** standard FB API init functions ***** */
-/* ****************************************** */
+static struct pci_device_id pm3fb_id_table[] = {
+ { PCI_VENDOR_ID_3DLABS, 0x0a,
+ PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+ 0xff0000, 0 },
+ { 0, }
+};
-int __init pm3fb_setup(char *options)
-{
- long opsi = strlen(options);
+/* For PCI drivers */
+static struct pci_driver pm3fb_driver = {
+ .name = "pm3fb",
+ .id_table = pm3fb_id_table,
+ .probe = pm3fb_probe,
+ .remove = __devexit_p(pm3fb_remove),
+};
- DTRACE;
-
- memcpy(g_options, options,
- ((opsi + 1) >
- PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1));
- g_options[PM3_OPTIONS_SIZE - 1] = 0;
-
- return (0);
-}
+MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
int __init pm3fb_init(void)
{
- DTRACE;
+ /*
+ * For kernel boot options (in 'video=pm3fb:<options>' format)
+ */
+#ifndef MODULE
+ char *option = NULL;
- DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $");
+ if (fb_get_options("pm3fb", &option))
+ return -ENODEV;
+ pm3fb_setup(option);
+#endif
- pm3fb_real_setup(g_options);
-
- pm3fb_detect();
-
- if (!fb_info[0].dev) { /* not even one board ??? */
- DPRINTK(1, "No PCI Permedia3 board detected\n");
- }
- return (0);
+ return pci_register_driver(&pm3fb_driver);
}
-/* ************************* */
-/* **** Module support ***** */
-/* ************************* */
+static void __exit pm3fb_exit(void)
+{
+ pci_unregister_driver(&pm3fb_driver);
+}
#ifdef MODULE
-MODULE_AUTHOR("Romain Dolbeau");
-MODULE_DESCRIPTION("Permedia3 framebuffer device driver");
-static char *mode[PM3_MAX_BOARD];
-module_param_array(mode, charp, NULL, 0);
-MODULE_PARM_DESC(mode,"video mode");
-module_param_array(disable, short, NULL, 0);
-MODULE_PARM_DESC(disable,"disable board");
-static short off[PM3_MAX_BOARD];
-module_param_array(off, short, NULL, 0);
-MODULE_PARM_DESC(off,"disable board");
-static char *pciid[PM3_MAX_BOARD];
-module_param_array(pciid, charp, NULL, 0);
-MODULE_PARM_DESC(pciid,"board PCI Id");
-module_param_array(noaccel, short, NULL, 0);
-MODULE_PARM_DESC(noaccel,"disable accel");
-static char *font[PM3_MAX_BOARD];
-module_param_array(font, charp, NULL, 0);
-MODULE_PARM_DESC(font,"choose font");
-module_param(depth, short, NULL, 0);
-MODULE_PARM_DESC(depth,"boot-time depth");
-module_param(printtimings, short, NULL, 0);
-MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
-module_param(forcesize, short, NULL, 0);
-MODULE_PARM_DESC(forcesize, "force specified memory size");
+ /*
+ * Setup
+ */
+
/*
-MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
-MODULE_GENERIC_TABLE(gtype,name)
-MODULE_DEVICE_TABLE(type,name)
-*/
-
-void pm3fb_build_options(void)
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+int __init pm3fb_setup(char *options)
{
- int i;
- char ts[128];
-
- strcpy(g_options, "pm3fb");
- for (i = 0; i < PM3_MAX_BOARD ; i++)
- {
- if (mode[i])
- {
- sprintf(ts, ",mode:%d:%s", i, mode[i]);
- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
- }
- if (disable[i] || off[i])
- {
- sprintf(ts, ",disable:%d:", i);
- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
- }
- if (pciid[i])
- {
- sprintf(ts, ",pciid:%d:%s", i, pciid[i]);
- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
- }
- if (noaccel[i])
- {
- sprintf(ts, ",noaccel:%d:", i);
- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
- }
- if (font[i])
- {
- sprintf(ts, ",font:%d:%s", i, font[i]);
- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
- }
- if (depth[i])
- {
- sprintf(ts, ",depth:%d:%d", i, depth[i]);
- strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
- }
- }
- g_options[PM3_OPTIONS_SIZE - 1] = '\0';
- DPRINTK(1, "pm3fb use options: %s\n", g_options);
-}
-
-int init_module(void)
-{
- DTRACE;
-
- pm3fb_build_options();
-
- pm3fb_init();
-
+ /* Parse user speficied options (`video=pm3fb:') */
return 0;
}
-
-void cleanup_module(void)
-{
- DTRACE;
- {
- unsigned long i;
- struct pm3fb_info *l_fb_info;
- for (i = 0; i < PM3_MAX_BOARD; i++) {
- l_fb_info = &(fb_info[i]);
- pci_dev_put(l_fb_info->dev);
- if (l_fb_info->dev != NULL && !(disable[l_fb_info->board_num])) {
- if (l_fb_info->vIOBase != (unsigned char *) -1) {
- pm3fb_unmapIO(l_fb_info);
- release_mem_region(l_fb_info->p_fb,
- l_fb_info->fb_size);
- release_mem_region(l_fb_info->pIOBase,
- PM3_REGS_SIZE);
- }
- unregister_framebuffer(&l_fb_info->gen.info);
- }
- }
- }
-}
#endif /* MODULE */
+
+module_init(pm3fb_init);
+module_exit(pm3fb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index 76e6ce3..a0e22ac 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -70,8 +70,6 @@
if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04)
val = 1;
- val = VGA_RD08(par->riva.PCIO, 0x3d5);
-
return val;
}
diff --git a/fs/Makefile b/fs/Makefile
index 9edf411..720c29d 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -22,6 +22,10 @@
obj-$(CONFIG_INOTIFY) += inotify.o
obj-$(CONFIG_INOTIFY_USER) += inotify_user.o
obj-$(CONFIG_EPOLL) += eventpoll.o
+obj-$(CONFIG_ANON_INODES) += anon_inodes.o
+obj-$(CONFIG_SIGNALFD) += signalfd.o
+obj-$(CONFIG_TIMERFD) += timerfd.o
+obj-$(CONFIG_EVENTFD) += eventfd.o
obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
nfsd-$(CONFIG_NFSD) := nfsctl.o
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index 52d0752..2452579 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -16,6 +16,9 @@
#define AFS_MAXCELLNAME 64 /* maximum length of a cell name */
#define AFS_MAXVOLNAME 64 /* maximum length of a volume name */
+#define AFSNAMEMAX 256 /* maximum length of a filename plus NUL */
+#define AFSPATHMAX 1024 /* maximum length of a pathname plus NUL */
+#define AFSOPAQUEMAX 1024 /* maximum length of an opaque field */
typedef unsigned afs_volid_t;
typedef unsigned afs_vnodeid_t;
@@ -143,4 +146,24 @@
time_t creation; /* volume creation time */
};
+/*
+ * AFS volume status record
+ */
+struct afs_volume_status {
+ u32 vid; /* volume ID */
+ u32 parent_id; /* parent volume ID */
+ u8 online; /* true if volume currently online and available */
+ u8 in_service; /* true if volume currently in service */
+ u8 blessed; /* same as in_service */
+ u8 needs_salvage; /* true if consistency checking required */
+ u32 type; /* volume type (afs_voltype_t) */
+ u32 min_quota; /* minimum space set aside (blocks) */
+ u32 max_quota; /* maximum space this volume may occupy (blocks) */
+ u32 blocks_in_use; /* space this volume currently occupies (blocks) */
+ u32 part_blocks_avail; /* space available in volume's partition */
+ u32 part_max_blocks; /* size of volume's partition */
+};
+
+#define AFS_BLOCK_SIZE 1024
+
#endif /* AFS_H */
diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h
index d963ef4..a18c374 100644
--- a/fs/afs/afs_fs.h
+++ b/fs/afs/afs_fs.h
@@ -28,7 +28,8 @@
FSMAKEDIR = 141, /* AFS Create a directory */
FSREMOVEDIR = 142, /* AFS Remove a directory */
FSGIVEUPCALLBACKS = 147, /* AFS Discard callback promises */
- FSGETVOLUMEINFO = 148, /* AFS Get root volume information */
+ FSGETVOLUMEINFO = 148, /* AFS Get information about a volume */
+ FSGETVOLUMESTATUS = 149, /* AFS Get volume status information */
FSGETROOTVOLUME = 151, /* AFS Get root volume name */
FSLOOKUP = 161, /* AFS lookup file in directory */
FSFETCHDATA64 = 65537, /* AFS Fetch file data */
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 2fb3127..719af4f 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -497,7 +497,7 @@
ASSERTCMP(dentry->d_inode, ==, NULL);
- if (dentry->d_name.len > 255) {
+ if (dentry->d_name.len >= AFSNAMEMAX) {
_leave(" = -ENAMETOOLONG");
return ERR_PTR(-ENAMETOOLONG);
}
@@ -736,7 +736,7 @@
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
ret = -ENAMETOOLONG;
- if (dentry->d_name.len > 255)
+ if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell);
@@ -801,7 +801,7 @@
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
ret = -ENAMETOOLONG;
- if (dentry->d_name.len > 255)
+ if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell);
@@ -847,7 +847,7 @@
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
ret = -ENAMETOOLONG;
- if (dentry->d_name.len > 255)
+ if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell);
@@ -921,7 +921,7 @@
dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
ret = -ENAMETOOLONG;
- if (dentry->d_name.len > 255)
+ if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell);
@@ -990,7 +990,7 @@
dentry->d_name.name);
ret = -ENAMETOOLONG;
- if (dentry->d_name.len > 255)
+ if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(dvnode->volume->cell);
@@ -1038,11 +1038,11 @@
content);
ret = -ENAMETOOLONG;
- if (dentry->d_name.len > 255)
+ if (dentry->d_name.len >= AFSNAMEMAX)
goto error;
ret = -EINVAL;
- if (strlen(content) > 1023)
+ if (strlen(content) >= AFSPATHMAX)
goto error;
key = afs_request_key(dvnode->volume->cell);
@@ -1112,7 +1112,7 @@
new_dentry->d_name.name);
ret = -ENAMETOOLONG;
- if (new_dentry->d_name.len > 255)
+ if (new_dentry->d_name.len >= AFSNAMEMAX)
goto error;
key = afs_request_key(orig_dvnode->volume->cell);
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 3e25795..9c0e721 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -236,7 +236,7 @@
{
int ret = 1;
- kenter("{%lu},%lu", page->index, offset);
+ _enter("{%lu},%lu", page->index, offset);
BUG_ON(!PageLocked(page));
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 56cc0ef..5dff130 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -202,6 +202,29 @@
}
/*
+ * decode an AFSFetchVolumeStatus block
+ */
+static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
+ struct afs_volume_status *vs)
+{
+ const __be32 *bp = *_bp;
+
+ vs->vid = ntohl(*bp++);
+ vs->parent_id = ntohl(*bp++);
+ vs->online = ntohl(*bp++);
+ vs->in_service = ntohl(*bp++);
+ vs->blessed = ntohl(*bp++);
+ vs->needs_salvage = ntohl(*bp++);
+ vs->type = ntohl(*bp++);
+ vs->min_quota = ntohl(*bp++);
+ vs->max_quota = ntohl(*bp++);
+ vs->blocks_in_use = ntohl(*bp++);
+ vs->part_blocks_avail = ntohl(*bp++);
+ vs->part_max_blocks = ntohl(*bp++);
+ *_bp = bp;
+}
+
+/*
* deliver reply data to an FS.FetchStatus
*/
static int afs_deliver_fs_fetch_status(struct afs_call *call,
@@ -1450,3 +1473,278 @@
return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
}
+
+/*
+ * deliver reply data to an FS.GetVolumeStatus
+ */
+static int afs_deliver_fs_get_volume_status(struct afs_call *call,
+ struct sk_buff *skb, bool last)
+{
+ const __be32 *bp;
+ char *p;
+ int ret;
+
+ _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+
+ switch (call->unmarshall) {
+ case 0:
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the returned status record */
+ case 1:
+ _debug("extract status");
+ ret = afs_extract_data(call, skb, last, call->buffer,
+ 12 * 4);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ bp = call->buffer;
+ xdr_decode_AFSFetchVolumeStatus(&bp, call->reply2);
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the volume name length */
+ case 2:
+ ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ call->count = ntohl(call->tmp);
+ _debug("volname length: %u", call->count);
+ if (call->count >= AFSNAMEMAX)
+ return -EBADMSG;
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the volume name */
+ case 3:
+ _debug("extract volname");
+ if (call->count > 0) {
+ ret = afs_extract_data(call, skb, last, call->reply3,
+ call->count);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+ }
+
+ p = call->reply3;
+ p[call->count] = 0;
+ _debug("volname '%s'", p);
+
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the volume name padding */
+ if ((call->count & 3) == 0) {
+ call->unmarshall++;
+ goto no_volname_padding;
+ }
+ call->count = 4 - (call->count & 3);
+
+ case 4:
+ ret = afs_extract_data(call, skb, last, call->buffer,
+ call->count);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ call->offset = 0;
+ call->unmarshall++;
+ no_volname_padding:
+
+ /* extract the offline message length */
+ case 5:
+ ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ call->count = ntohl(call->tmp);
+ _debug("offline msg length: %u", call->count);
+ if (call->count >= AFSNAMEMAX)
+ return -EBADMSG;
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the offline message */
+ case 6:
+ _debug("extract offline");
+ if (call->count > 0) {
+ ret = afs_extract_data(call, skb, last, call->reply3,
+ call->count);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+ }
+
+ p = call->reply3;
+ p[call->count] = 0;
+ _debug("offline '%s'", p);
+
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the offline message padding */
+ if ((call->count & 3) == 0) {
+ call->unmarshall++;
+ goto no_offline_padding;
+ }
+ call->count = 4 - (call->count & 3);
+
+ case 7:
+ ret = afs_extract_data(call, skb, last, call->buffer,
+ call->count);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ call->offset = 0;
+ call->unmarshall++;
+ no_offline_padding:
+
+ /* extract the message of the day length */
+ case 8:
+ ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ call->count = ntohl(call->tmp);
+ _debug("motd length: %u", call->count);
+ if (call->count >= AFSNAMEMAX)
+ return -EBADMSG;
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the message of the day */
+ case 9:
+ _debug("extract motd");
+ if (call->count > 0) {
+ ret = afs_extract_data(call, skb, last, call->reply3,
+ call->count);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+ }
+
+ p = call->reply3;
+ p[call->count] = 0;
+ _debug("motd '%s'", p);
+
+ call->offset = 0;
+ call->unmarshall++;
+
+ /* extract the message of the day padding */
+ if ((call->count & 3) == 0) {
+ call->unmarshall++;
+ goto no_motd_padding;
+ }
+ call->count = 4 - (call->count & 3);
+
+ case 10:
+ ret = afs_extract_data(call, skb, last, call->buffer,
+ call->count);
+ switch (ret) {
+ case 0: break;
+ case -EAGAIN: return 0;
+ default: return ret;
+ }
+
+ call->offset = 0;
+ call->unmarshall++;
+ no_motd_padding:
+
+ case 11:
+ _debug("trailer %d", skb->len);
+ if (skb->len != 0)
+ return -EBADMSG;
+ break;
+ }
+
+ if (!last)
+ return 0;
+
+ _leave(" = 0 [done]");
+ return 0;
+}
+
+/*
+ * destroy an FS.GetVolumeStatus call
+ */
+static void afs_get_volume_status_call_destructor(struct afs_call *call)
+{
+ kfree(call->reply3);
+ call->reply3 = NULL;
+ afs_flat_call_destructor(call);
+}
+
+/*
+ * FS.GetVolumeStatus operation type
+ */
+static const struct afs_call_type afs_RXFSGetVolumeStatus = {
+ .name = "FS.GetVolumeStatus",
+ .deliver = afs_deliver_fs_get_volume_status,
+ .abort_to_error = afs_abort_to_error,
+ .destructor = afs_get_volume_status_call_destructor,
+};
+
+/*
+ * fetch the status of a volume
+ */
+int afs_fs_get_volume_status(struct afs_server *server,
+ struct key *key,
+ struct afs_vnode *vnode,
+ struct afs_volume_status *vs,
+ const struct afs_wait_mode *wait_mode)
+{
+ struct afs_call *call;
+ __be32 *bp;
+ void *tmpbuf;
+
+ _enter("");
+
+ tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
+ if (!tmpbuf)
+ return -ENOMEM;
+
+ call = afs_alloc_flat_call(&afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
+ if (!call) {
+ kfree(tmpbuf);
+ return -ENOMEM;
+ }
+
+ call->key = key;
+ call->reply = vnode;
+ call->reply2 = vs;
+ call->reply3 = tmpbuf;
+ call->service_id = FS_SERVICE;
+ call->port = htons(AFS_FS_PORT);
+
+ /* marshall the parameters */
+ bp = call->request;
+ bp[0] = htonl(FSGETVOLUMESTATUS);
+ bp[1] = htonl(vnode->fid.vid);
+
+ return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 515a5d1..47f5fed 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -209,11 +209,15 @@
*/
void afs_zap_data(struct afs_vnode *vnode)
{
- _enter("zap data {%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+ _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
/* nuke all the non-dirty pages that aren't locked, mapped or being
- * written back */
- invalidate_remote_inode(&vnode->vfs_inode);
+ * written back in a regular file and completely discard the pages in a
+ * directory or symlink */
+ if (S_ISREG(vnode->vfs_inode.i_mode))
+ invalidate_remote_inode(&vnode->vfs_inode);
+ else
+ invalidate_inode_pages2(vnode->vfs_inode.i_mapping);
}
/*
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index a30d4fa..4953ba5 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -506,6 +506,10 @@
extern int afs_fs_setattr(struct afs_server *, struct key *,
struct afs_vnode *, struct iattr *,
const struct afs_wait_mode *);
+extern int afs_fs_get_volume_status(struct afs_server *, struct key *,
+ struct afs_vnode *,
+ struct afs_volume_status *,
+ const struct afs_wait_mode *);
/*
* inode.c
@@ -672,6 +676,8 @@
extern int afs_vnode_store_data(struct afs_writeback *, pgoff_t, pgoff_t,
unsigned, unsigned);
extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *);
+extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *,
+ struct afs_volume_status *);
/*
* volume.c
diff --git a/fs/afs/super.c b/fs/afs/super.c
index d24be33..579af63 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -21,22 +21,20 @@
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/parser.h>
+#include <linux/statfs.h>
#include "internal.h"
#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
unsigned long flags);
-
static int afs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data, struct vfsmount *mnt);
-
static struct inode *afs_alloc_inode(struct super_block *sb);
-
static void afs_put_super(struct super_block *sb);
-
static void afs_destroy_inode(struct inode *inode);
+static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
struct file_system_type afs_fs_type = {
.owner = THIS_MODULE,
@@ -47,7 +45,7 @@
};
static const struct super_operations afs_super_ops = {
- .statfs = simple_statfs,
+ .statfs = afs_statfs,
.alloc_inode = afs_alloc_inode,
.drop_inode = generic_delete_inode,
.write_inode = afs_write_inode,
@@ -488,6 +486,7 @@
vnode->flags = 1 << AFS_VNODE_UNSET;
vnode->cb_promised = false;
+ _leave(" = %p", &vnode->vfs_inode);
return &vnode->vfs_inode;
}
@@ -498,7 +497,7 @@
{
struct afs_vnode *vnode = AFS_FS_I(inode);
- _enter("{%lu}", inode->i_ino);
+ _enter("%p{%x:%u}", inode, vnode->fid.vid, vnode->fid.vnode);
_debug("DESTROY INODE %p", inode);
@@ -507,3 +506,36 @@
kmem_cache_free(afs_inode_cachep, vnode);
atomic_dec(&afs_count_active_inodes);
}
+
+/*
+ * return information about an AFS volume
+ */
+static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+ struct afs_volume_status vs;
+ struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+ struct key *key;
+ int ret;
+
+ key = afs_request_key(vnode->volume->cell);
+ if (IS_ERR(key))
+ return PTR_ERR(key);
+
+ ret = afs_vnode_get_volume_status(vnode, key, &vs);
+ key_put(key);
+ if (ret < 0) {
+ _leave(" = %d", ret);
+ return ret;
+ }
+
+ buf->f_type = dentry->d_sb->s_magic;
+ buf->f_bsize = AFS_BLOCK_SIZE;
+ buf->f_namelen = AFSNAMEMAX - 1;
+
+ if (vs.max_quota == 0)
+ buf->f_blocks = vs.part_max_blocks;
+ else
+ buf->f_blocks = vs.max_quota;
+ buf->f_bavail = buf->f_bfree = buf->f_blocks - vs.blocks_in_use;
+ return 0;
+}
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index ec81466..c36c98c 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -175,24 +175,33 @@
{
struct afs_server *server;
+ _enter("{%p}", vnode->server);
+
set_bit(AFS_VNODE_DELETED, &vnode->flags);
server = vnode->server;
- if (vnode->cb_promised) {
- spin_lock(&server->cb_lock);
+ if (server) {
if (vnode->cb_promised) {
- rb_erase(&vnode->cb_promise, &server->cb_promises);
- vnode->cb_promised = false;
+ spin_lock(&server->cb_lock);
+ if (vnode->cb_promised) {
+ rb_erase(&vnode->cb_promise,
+ &server->cb_promises);
+ vnode->cb_promised = false;
+ }
+ spin_unlock(&server->cb_lock);
}
- spin_unlock(&server->cb_lock);
+
+ spin_lock(&server->fs_lock);
+ rb_erase(&vnode->server_rb, &server->fs_vnodes);
+ spin_unlock(&server->fs_lock);
+
+ vnode->server = NULL;
+ afs_put_server(server);
+ } else {
+ ASSERT(!vnode->cb_promised);
}
- spin_lock(&vnode->server->fs_lock);
- rb_erase(&vnode->server_rb, &vnode->server->fs_vnodes);
- spin_unlock(&vnode->server->fs_lock);
-
- vnode->server = NULL;
- afs_put_server(server);
+ _leave("");
}
/*
@@ -225,7 +234,7 @@
*/
static void afs_vnode_status_update_failed(struct afs_vnode *vnode, int ret)
{
- _enter("%p,%d", vnode, ret);
+ _enter("{%x:%u},%d", vnode->fid.vid, vnode->fid.vnode, ret);
spin_lock(&vnode->lock);
@@ -860,3 +869,55 @@
spin_unlock(&vnode->lock);
return PTR_ERR(server);
}
+
+/*
+ * get the status of a volume
+ */
+int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key,
+ struct afs_volume_status *vs)
+{
+ struct afs_server *server;
+ int ret;
+
+ _enter("%s{%x:%u.%u},%x,",
+ vnode->volume->vlocation->vldb.name,
+ vnode->fid.vid,
+ vnode->fid.vnode,
+ vnode->fid.unique,
+ key_serial(key));
+
+ /* this op will fetch the status */
+ spin_lock(&vnode->lock);
+ vnode->update_cnt++;
+ spin_unlock(&vnode->lock);
+
+ do {
+ /* pick a server to query */
+ server = afs_volume_pick_fileserver(vnode);
+ if (IS_ERR(server))
+ goto no_server;
+
+ _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+ ret = afs_fs_get_volume_status(server, key, vnode, vs, &afs_sync_call);
+
+ } while (!afs_volume_release_fileserver(vnode, server, ret));
+
+ /* adjust the flags */
+ if (ret == 0) {
+ afs_vnode_finalise_status_update(vnode, server);
+ afs_put_server(server);
+ } else {
+ afs_vnode_status_update_failed(vnode, ret);
+ }
+
+ _leave(" = %d", ret);
+ return ret;
+
+no_server:
+ spin_lock(&vnode->lock);
+ vnode->update_cnt--;
+ ASSERTCMP(vnode->update_cnt, >=, 0);
+ spin_unlock(&vnode->lock);
+ return PTR_ERR(server);
+}
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 67ae4db..28f3751 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -395,8 +395,9 @@
if (n == 0)
goto no_more;
if (pages[0]->index != start) {
- for (n--; n >= 0; n--)
- put_page(pages[n]);
+ do {
+ put_page(pages[--n]);
+ } while (n > 0);
goto no_more;
}
diff --git a/fs/aio.c b/fs/aio.c
index ac1c158..dbe699e 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -30,6 +30,7 @@
#include <linux/highmem.h>
#include <linux/workqueue.h>
#include <linux/security.h>
+#include <linux/eventfd.h>
#include <asm/kmap_types.h>
#include <asm/uaccess.h>
@@ -417,6 +418,7 @@
req->private = NULL;
req->ki_iovec = NULL;
INIT_LIST_HEAD(&req->ki_run_list);
+ req->ki_eventfd = ERR_PTR(-EINVAL);
/* Check if the completion queue has enough free space to
* accept an event from this io.
@@ -458,6 +460,8 @@
{
assert_spin_locked(&ctx->ctx_lock);
+ if (!IS_ERR(req->ki_eventfd))
+ fput(req->ki_eventfd);
if (req->ki_dtor)
req->ki_dtor(req);
if (req->ki_iovec != &req->ki_inline_vec)
@@ -942,6 +946,14 @@
return 1;
}
+ /*
+ * Check if the user asked us to deliver the result through an
+ * eventfd. The eventfd_signal() function is safe to be called
+ * from IRQ context.
+ */
+ if (!IS_ERR(iocb->ki_eventfd))
+ eventfd_signal(iocb->ki_eventfd, 1);
+
info = &ctx->ring_info;
/* add a completion event to the ring buffer.
@@ -1526,8 +1538,7 @@
ssize_t ret;
/* enforce forwards compatibility on users */
- if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
- iocb->aio_reserved3)) {
+ if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) {
pr_debug("EINVAL: io_submit: reserve field set\n");
return -EINVAL;
}
@@ -1551,6 +1562,19 @@
fput(file);
return -EAGAIN;
}
+ if (iocb->aio_flags & IOCB_FLAG_RESFD) {
+ /*
+ * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
+ * instance of the file* now. The file descriptor must be
+ * an eventfd() fd, and will be signaled for each completed
+ * event using the eventfd_signal() function.
+ */
+ req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
+ if (unlikely(IS_ERR(req->ki_eventfd))) {
+ ret = PTR_ERR(req->ki_eventfd);
+ goto out_put_req;
+ }
+ }
req->ki_filp = file;
ret = put_user(req->ki_key, &user_iocb->aio_key);
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
new file mode 100644
index 0000000..40fe3a3
--- /dev/null
+++ b/fs/anon_inodes.c
@@ -0,0 +1,200 @@
+/*
+ * fs/anon_inodes.c
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ * Thanks to Arnd Bergmann for code review and suggestions.
+ * More changes for Thomas Gleixner suggestions.
+ *
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/magic.h>
+#include <linux/anon_inodes.h>
+
+#include <asm/uaccess.h>
+
+static struct vfsmount *anon_inode_mnt __read_mostly;
+static struct inode *anon_inode_inode;
+static const struct file_operations anon_inode_fops;
+
+static int anon_inodefs_get_sb(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data,
+ struct vfsmount *mnt)
+{
+ return get_sb_pseudo(fs_type, "anon_inode:", NULL, ANON_INODE_FS_MAGIC,
+ mnt);
+}
+
+static int anon_inodefs_delete_dentry(struct dentry *dentry)
+{
+ /*
+ * We faked vfs to believe the dentry was hashed when we created it.
+ * Now we restore the flag so that dput() will work correctly.
+ */
+ dentry->d_flags |= DCACHE_UNHASHED;
+ return 1;
+}
+
+static struct file_system_type anon_inode_fs_type = {
+ .name = "anon_inodefs",
+ .get_sb = anon_inodefs_get_sb,
+ .kill_sb = kill_anon_super,
+};
+static struct dentry_operations anon_inodefs_dentry_operations = {
+ .d_delete = anon_inodefs_delete_dentry,
+};
+
+/**
+ * anon_inode_getfd - creates a new file instance by hooking it up to and
+ * anonymous inode, and a dentry that describe the "class"
+ * of the file
+ *
+ * @pfd: [out] pointer to the file descriptor
+ * @dpinode: [out] pointer to the inode
+ * @pfile: [out] pointer to the file struct
+ * @name: [in] name of the "class" of the new file
+ * @fops [in] file operations for the new file
+ * @priv [in] private data for the new file (will be file's private_data)
+ *
+ * Creates a new file by hooking it on a single inode. This is useful for files
+ * that do not need to have a full-fledged inode in order to operate correctly.
+ * All the files created with anon_inode_getfd() will share a single inode, by
+ * hence saving memory and avoiding code duplication for the file/inode/dentry
+ * setup.
+ */
+int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
+ const char *name, const struct file_operations *fops,
+ void *priv)
+{
+ struct qstr this;
+ struct dentry *dentry;
+ struct inode *inode;
+ struct file *file;
+ int error, fd;
+
+ if (IS_ERR(anon_inode_inode))
+ return -ENODEV;
+ file = get_empty_filp();
+ if (!file)
+ return -ENFILE;
+
+ inode = igrab(anon_inode_inode);
+ if (IS_ERR(inode)) {
+ error = PTR_ERR(inode);
+ goto err_put_filp;
+ }
+
+ error = get_unused_fd();
+ if (error < 0)
+ goto err_iput;
+ fd = error;
+
+ /*
+ * Link the inode to a directory entry by creating a unique name
+ * using the inode sequence number.
+ */
+ error = -ENOMEM;
+ this.name = name;
+ this.len = strlen(name);
+ this.hash = 0;
+ dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
+ if (!dentry)
+ goto err_put_unused_fd;
+ dentry->d_op = &anon_inodefs_dentry_operations;
+ /* Do not publish this dentry inside the global dentry hash table */
+ dentry->d_flags &= ~DCACHE_UNHASHED;
+ d_instantiate(dentry, inode);
+
+ file->f_path.mnt = mntget(anon_inode_mnt);
+ file->f_path.dentry = dentry;
+ file->f_mapping = inode->i_mapping;
+
+ file->f_pos = 0;
+ file->f_flags = O_RDWR;
+ file->f_op = fops;
+ file->f_mode = FMODE_READ | FMODE_WRITE;
+ file->f_version = 0;
+ file->private_data = priv;
+
+ fd_install(fd, file);
+
+ *pfd = fd;
+ *pinode = inode;
+ *pfile = file;
+ return 0;
+
+err_put_unused_fd:
+ put_unused_fd(fd);
+err_iput:
+ iput(inode);
+err_put_filp:
+ put_filp(file);
+ return error;
+}
+
+/*
+ * A single inode exist for all anon_inode files. Contrary to pipes,
+ * anon_inode inodes has no per-instance data associated, so we can avoid
+ * the allocation of multiple of them.
+ */
+static struct inode *anon_inode_mkinode(void)
+{
+ struct inode *inode = new_inode(anon_inode_mnt->mnt_sb);
+
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+
+ inode->i_fop = &anon_inode_fops;
+
+ /*
+ * Mark the inode dirty from the very beginning,
+ * that way it will never be moved to the dirty
+ * list because mark_inode_dirty() will think
+ * that it already _is_ on the dirty list.
+ */
+ inode->i_state = I_DIRTY;
+ inode->i_mode = S_IRUSR | S_IWUSR;
+ inode->i_uid = current->fsuid;
+ inode->i_gid = current->fsgid;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+ return inode;
+}
+
+static int __init anon_inode_init(void)
+{
+ int error;
+
+ error = register_filesystem(&anon_inode_fs_type);
+ if (error)
+ goto err_exit;
+ anon_inode_mnt = kern_mount(&anon_inode_fs_type);
+ if (IS_ERR(anon_inode_mnt)) {
+ error = PTR_ERR(anon_inode_mnt);
+ goto err_unregister_filesystem;
+ }
+ anon_inode_inode = anon_inode_mkinode();
+ if (IS_ERR(anon_inode_inode)) {
+ error = PTR_ERR(anon_inode_inode);
+ goto err_mntput;
+ }
+
+ return 0;
+
+err_mntput:
+ mntput(anon_inode_mnt);
+err_unregister_filesystem:
+ unregister_filesystem(&anon_inode_fs_type);
+err_exit:
+ panic(KERN_ERR "anon_inode_init() failed (%d)\n", error);
+}
+
+fs_initcall(anon_inode_init);
+
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 4ef5444..8b4cca3 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -101,7 +101,7 @@
struct autofs_sb_info {
u32 magic;
struct file *pipe;
- pid_t oz_pgrp;
+ struct pid *oz_pgrp;
int catatonic;
struct super_block *sb;
unsigned long exp_timeout;
@@ -122,7 +122,7 @@
filesystem without "magic".) */
static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
- return sbi->catatonic || process_group(current) == sbi->oz_pgrp;
+ return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
}
/* Hash operations */
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index aa0b61f..e7204d7 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -34,12 +34,14 @@
if (!sbi)
goto out_kill_sb;
- if ( !sbi->catatonic )
+ if (!sbi->catatonic)
autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
+ put_pid(sbi->oz_pgrp);
+
autofs_hash_nuke(sbi);
- for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
- if ( test_bit(n, sbi->symlink_bitmap) )
+ for (n = 0; n < AUTOFS_MAX_SYMLINKS; n++) {
+ if (test_bit(n, sbi->symlink_bitmap))
kfree(sbi->symlink[n].data);
}
@@ -69,7 +71,8 @@
{Opt_err, NULL}
};
-static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid_t *pgrp, int *minproto, int *maxproto)
+static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
+ pid_t *pgrp, int *minproto, int *maxproto)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -138,9 +141,10 @@
int pipefd;
struct autofs_sb_info *sbi;
int minproto, maxproto;
+ pid_t pgid;
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
- if ( !sbi )
+ if (!sbi)
goto fail_unlock;
DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
@@ -149,7 +153,6 @@
sbi->pipe = NULL;
sbi->catatonic = 1;
sbi->exp_timeout = 0;
- sbi->oz_pgrp = process_group(current);
autofs_initialize_hash(&sbi->dirhash);
sbi->queues = NULL;
memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN);
@@ -169,26 +172,36 @@
goto fail_iput;
/* Can this call block? - WTF cares? s is locked. */
- if ( parse_options(data,&pipefd,&root_inode->i_uid,&root_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
+ if (parse_options(data, &pipefd, &root_inode->i_uid,
+ &root_inode->i_gid, &pgid, &minproto,
+ &maxproto)) {
printk("autofs: called with bogus options\n");
goto fail_dput;
}
/* Couldn't this be tested earlier? */
- if ( minproto > AUTOFS_PROTO_VERSION ||
- maxproto < AUTOFS_PROTO_VERSION ) {
+ if (minproto > AUTOFS_PROTO_VERSION ||
+ maxproto < AUTOFS_PROTO_VERSION) {
printk("autofs: kernel does not match daemon version\n");
goto fail_dput;
}
- DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp));
- pipe = fget(pipefd);
-
- if ( !pipe ) {
- printk("autofs: could not open pipe file descriptor\n");
+ DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, pgid));
+ sbi->oz_pgrp = find_get_pid(pgid);
+
+ if (!sbi->oz_pgrp) {
+ printk("autofs: could not find process group %d\n", pgid);
goto fail_dput;
}
- if ( !pipe->f_op || !pipe->f_op->write )
+
+ pipe = fget(pipefd);
+
+ if (!pipe) {
+ printk("autofs: could not open pipe file descriptor\n");
+ goto fail_put_pid;
+ }
+
+ if (!pipe->f_op || !pipe->f_op->write)
goto fail_fput;
sbi->pipe = pipe;
sbi->catatonic = 0;
@@ -202,6 +215,8 @@
fail_fput:
printk("autofs: pipe file descriptor does not contain proper ops\n");
fput(pipe);
+fail_put_pid:
+ put_pid(sbi->oz_pgrp);
fail_dput:
dput(root);
goto fail_free;
@@ -230,7 +245,7 @@
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0;
- if ( ino == AUTOFS_ROOT_INO ) {
+ if (ino == AUTOFS_ROOT_INO) {
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &autofs_root_inode_operations;
inode->i_fop = &autofs_root_operations;
@@ -241,12 +256,12 @@
inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
- if ( ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO ) {
+ if (ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO) {
/* Symlink inode - should be in symlink list */
struct autofs_symlink *sl;
n = ino - AUTOFS_FIRST_SYMLINK;
- if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
+ if (n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino);
return;
}
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index f259720..c148953 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -67,8 +67,8 @@
filp->f_pos = ++nr;
/* fall through */
default:
- while ( onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent) ) {
- if ( !ent->dentry || d_mountpoint(ent->dentry) ) {
+ while (onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent)) {
+ if (!ent->dentry || d_mountpoint(ent->dentry)) {
if (filldir(dirent,ent->name,ent->len,onr,ent->ino,DT_UNKNOWN) < 0)
goto out;
filp->f_pos = nr;
@@ -88,10 +88,10 @@
struct autofs_dir_ent *ent;
int status = 0;
- if ( !(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) ) {
+ if (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))) {
do {
- if ( status && dentry->d_inode ) {
- if ( status != -ENOENT )
+ if (status && dentry->d_inode) {
+ if (status != -ENOENT)
printk("autofs warning: lookup failure on positive dentry, status = %d, name = %s\n", status, dentry->d_name.name);
return 0; /* Try to get the kernel to invalidate this dentry */
}
@@ -106,7 +106,7 @@
return 1;
}
status = autofs_wait(sbi, &dentry->d_name);
- } while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) );
+ } while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)));
}
/* Abuse this field as a pointer to the directory entry, used to
@@ -124,13 +124,13 @@
/* If this is a directory that isn't a mount point, bitch at the
daemon and fix it in user space */
- if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) {
+ if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
return !autofs_wait(sbi, &dentry->d_name);
}
/* We don't update the usages for the autofs daemon itself, this
is necessary for recursive autofs mounts */
- if ( !autofs_oz_mode(sbi) ) {
+ if (!autofs_oz_mode(sbi)) {
autofs_update_usage(&sbi->dirhash,ent);
}
@@ -157,7 +157,7 @@
sbi = autofs_sbi(dir->i_sb);
/* Pending dentry */
- if ( dentry->d_flags & DCACHE_AUTOFS_PENDING ) {
+ if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
if (autofs_oz_mode(sbi))
res = 1;
else
@@ -173,7 +173,7 @@
}
/* Check for a non-mountpoint directory */
- if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) {
+ if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
if (autofs_oz_mode(sbi))
res = 1;
else
@@ -183,9 +183,9 @@
}
/* Update the usage list */
- if ( !autofs_oz_mode(sbi) ) {
+ if (!autofs_oz_mode(sbi)) {
ent = (struct autofs_dir_ent *) dentry->d_time;
- if ( ent )
+ if (ent)
autofs_update_usage(&sbi->dirhash,ent);
}
unlock_kernel();
@@ -213,8 +213,10 @@
sbi = autofs_sbi(dir->i_sb);
oz_mode = autofs_oz_mode(sbi);
- DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n",
- current->pid, process_group(current), sbi->catatonic, oz_mode));
+ DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, "
+ "oz_mode = %d\n", pid_nr(task_pid(current)),
+ process_group(current), sbi->catatonic,
+ oz_mode));
/*
* Mark the dentry incomplete, but add it. This is needed so
@@ -258,7 +260,7 @@
* doesn't do the right thing for all system calls, but it should
* be OK for the operations we permit from an autofs.
*/
- if ( dentry->d_inode && d_unhashed(dentry) )
+ if (dentry->d_inode && d_unhashed(dentry))
return ERR_PTR(-ENOENT);
return NULL;
@@ -277,18 +279,18 @@
autofs_say(dentry->d_name.name,dentry->d_name.len);
lock_kernel();
- if ( !autofs_oz_mode(sbi) ) {
+ if (!autofs_oz_mode(sbi)) {
unlock_kernel();
return -EACCES;
}
- if ( autofs_hash_lookup(dh, &dentry->d_name) ) {
+ if (autofs_hash_lookup(dh, &dentry->d_name)) {
unlock_kernel();
return -EEXIST;
}
n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
- if ( n >= AUTOFS_MAX_SYMLINKS ) {
+ if (n >= AUTOFS_MAX_SYMLINKS) {
unlock_kernel();
return -ENOSPC;
}
@@ -297,14 +299,14 @@
sl = &sbi->symlink[n];
sl->len = strlen(symname);
sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
- if ( !sl->data ) {
+ if (!sl->data) {
clear_bit(n,sbi->symlink_bitmap);
unlock_kernel();
return -ENOSPC;
}
ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
- if ( !ent ) {
+ if (!ent) {
kfree(sl->data);
clear_bit(n,sbi->symlink_bitmap);
unlock_kernel();
@@ -312,7 +314,7 @@
}
ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
- if ( !ent->name ) {
+ if (!ent->name) {
kfree(sl->data);
kfree(ent);
clear_bit(n,sbi->symlink_bitmap);
@@ -354,23 +356,23 @@
/* This allows root to remove symlinks */
lock_kernel();
- if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) {
+ if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) {
unlock_kernel();
return -EACCES;
}
ent = autofs_hash_lookup(dh, &dentry->d_name);
- if ( !ent ) {
+ if (!ent) {
unlock_kernel();
return -ENOENT;
}
n = ent->ino - AUTOFS_FIRST_SYMLINK;
- if ( n >= AUTOFS_MAX_SYMLINKS ) {
+ if (n >= AUTOFS_MAX_SYMLINKS) {
unlock_kernel();
return -EISDIR; /* It's a directory, dummy */
}
- if ( !test_bit(n,sbi->symlink_bitmap) ) {
+ if (!test_bit(n,sbi->symlink_bitmap)) {
unlock_kernel();
return -EINVAL; /* Nonexistent symlink? Shouldn't happen */
}
@@ -392,23 +394,23 @@
struct autofs_dir_ent *ent;
lock_kernel();
- if ( !autofs_oz_mode(sbi) ) {
+ if (!autofs_oz_mode(sbi)) {
unlock_kernel();
return -EACCES;
}
ent = autofs_hash_lookup(dh, &dentry->d_name);
- if ( !ent ) {
+ if (!ent) {
unlock_kernel();
return -ENOENT;
}
- if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO ) {
+ if ((unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO) {
unlock_kernel();
return -ENOTDIR; /* Not a directory */
}
- if ( ent->dentry != dentry ) {
+ if (ent->dentry != dentry) {
printk("autofs_rmdir: odentry != dentry for entry %s\n", dentry->d_name.name);
}
@@ -429,18 +431,18 @@
ino_t ino;
lock_kernel();
- if ( !autofs_oz_mode(sbi) ) {
+ if (!autofs_oz_mode(sbi)) {
unlock_kernel();
return -EACCES;
}
ent = autofs_hash_lookup(dh, &dentry->d_name);
- if ( ent ) {
+ if (ent) {
unlock_kernel();
return -EEXIST;
}
- if ( sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO ) {
+ if (sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO) {
printk("autofs: Out of inode numbers -- what the heck did you do??\n");
unlock_kernel();
return -ENOSPC;
@@ -448,13 +450,13 @@
ino = sbi->next_dir_ino++;
ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
- if ( !ent ) {
+ if (!ent) {
unlock_kernel();
return -ENOSPC;
}
ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
- if ( !ent->name ) {
+ if (!ent->name) {
kfree(ent);
unlock_kernel();
return -ENOSPC;
@@ -483,7 +485,7 @@
put_user(sbi->exp_timeout / HZ, p))
return -EFAULT;
- if ( ntimeout > ULONG_MAX/HZ )
+ if (ntimeout > ULONG_MAX/HZ)
sbi->exp_timeout = 0;
else
sbi->exp_timeout = ntimeout * HZ;
@@ -511,15 +513,14 @@
pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
pkt.hdr.type = autofs_ptype_expire;
- if ( !sbi->exp_timeout ||
- !(ent = autofs_expire(sb,sbi,mnt)) )
+ if (!sbi->exp_timeout || !(ent = autofs_expire(sb,sbi,mnt)))
return -EAGAIN;
pkt.len = ent->len;
memcpy(pkt.name, ent->name, pkt.len);
pkt.name[pkt.len] = '\0';
- if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
+ if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
return -EFAULT;
return 0;
@@ -537,11 +538,11 @@
DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current)));
- if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
- _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
+ if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
+ _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
return -ENOTTY;
- if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
+ if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
return -EPERM;
switch(cmd) {
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 5769a2f..692364e8 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -218,8 +218,7 @@
};
static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
- pid_t *pgrp, unsigned int *type,
- int *minproto, int *maxproto)
+ pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto)
{
char *p;
substring_t args[MAX_OPT_ARGS];
@@ -314,7 +313,7 @@
struct autofs_info *ino;
sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
- if ( !sbi )
+ if (!sbi)
goto fail_unlock;
DPRINTK("starting up, sbi = %p",sbi);
@@ -363,10 +362,9 @@
root->d_fsdata = ino;
/* Can this call block? */
- if (parse_options(data, &pipefd,
- &root_inode->i_uid, &root_inode->i_gid,
- &sbi->oz_pgrp, &sbi->type,
- &sbi->min_proto, &sbi->max_proto)) {
+ if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid,
+ &sbi->oz_pgrp, &sbi->type, &sbi->min_proto,
+ &sbi->max_proto)) {
printk("autofs: called with bogus options\n");
goto fail_dput;
}
@@ -396,11 +394,11 @@
DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp);
pipe = fget(pipefd);
- if ( !pipe ) {
+ if (!pipe) {
printk("autofs: could not open pipe file descriptor\n");
goto fail_dput;
}
- if ( !pipe->f_op || !pipe->f_op->write )
+ if (!pipe->f_op || !pipe->f_op->write)
goto fail_fput;
sbi->pipe = pipe;
sbi->pipefd = pipefd;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 15170f4..2d4c8a3 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -759,7 +759,7 @@
struct autofs_info *p_ino;
/* This allows root to remove symlinks */
- if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
+ if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
return -EACCES;
if (atomic_dec_and_test(&ino->count)) {
@@ -833,7 +833,7 @@
struct autofs_info *p_ino;
struct inode *inode;
- if ( !autofs4_oz_mode(sbi) )
+ if (!autofs4_oz_mode(sbi))
return -EACCES;
DPRINTK("dentry %p, creating %.*s",
@@ -871,11 +871,11 @@
int rv;
unsigned long ntimeout;
- if ( (rv = get_user(ntimeout, p)) ||
- (rv = put_user(sbi->exp_timeout/HZ, p)) )
+ if ((rv = get_user(ntimeout, p)) ||
+ (rv = put_user(sbi->exp_timeout/HZ, p)))
return rv;
- if ( ntimeout > ULONG_MAX/HZ )
+ if (ntimeout > ULONG_MAX/HZ)
sbi->exp_timeout = 0;
else
sbi->exp_timeout = ntimeout * HZ;
@@ -906,7 +906,7 @@
DPRINTK("returning %d", sbi->needs_reghost);
status = put_user(sbi->needs_reghost, p);
- if ( status )
+ if (status)
return status;
sbi->needs_reghost = 0;
@@ -975,11 +975,11 @@
DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u",
cmd,arg,sbi,process_group(current));
- if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
- _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
+ if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
+ _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
return -ENOTTY;
- if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
+ if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
return -EPERM;
switch(cmd) {
diff --git a/fs/compat.c b/fs/compat.c
index 9cf75df..7b21b0a 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -46,6 +46,7 @@
#include <linux/tsacct_kern.h>
#include <linux/security.h>
#include <linux/highmem.h>
+#include <linux/signal.h>
#include <linux/poll.h>
#include <linux/mm.h>
#include <linux/eventpoll.h>
@@ -2199,3 +2200,51 @@
#endif /* TIF_RESTORE_SIGMASK */
#endif /* CONFIG_EPOLL */
+
+#ifdef CONFIG_SIGNALFD
+
+asmlinkage long compat_sys_signalfd(int ufd,
+ const compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize)
+{
+ compat_sigset_t ss32;
+ sigset_t tmp;
+ sigset_t __user *ksigmask;
+
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+ return -EFAULT;
+ sigset_from_compat(&tmp, &ss32);
+ ksigmask = compat_alloc_user_space(sizeof(sigset_t));
+ if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
+ return -EFAULT;
+
+ return sys_signalfd(ufd, ksigmask, sizeof(sigset_t));
+}
+
+#endif /* CONFIG_SIGNALFD */
+
+#ifdef CONFIG_TIMERFD
+
+asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags,
+ const struct compat_itimerspec __user *utmr)
+{
+ long res;
+ struct itimerspec t;
+ struct itimerspec __user *ut;
+
+ res = -EFAULT;
+ if (get_compat_itimerspec(&t, utmr))
+ goto err_exit;
+ ut = compat_alloc_user_space(sizeof(*ut));
+ if (copy_to_user(ut, &t, sizeof(t)) )
+ goto err_exit;
+
+ res = sys_timerfd(ufd, clockid, flags, ut);
+err_exit:
+ return res;
+}
+
+#endif /* CONFIG_TIMERFD */
+
diff --git a/fs/eventfd.c b/fs/eventfd.c
new file mode 100644
index 0000000..480e2b3
--- /dev/null
+++ b/fs/eventfd.c
@@ -0,0 +1,228 @@
+/*
+ * fs/eventfd.c
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/anon_inodes.h>
+#include <linux/eventfd.h>
+
+struct eventfd_ctx {
+ spinlock_t lock;
+ wait_queue_head_t wqh;
+ /*
+ * Every time that a write(2) is performed on an eventfd, the
+ * value of the __u64 being written is added to "count" and a
+ * wakeup is performed on "wqh". A read(2) will return the "count"
+ * value to userspace, and will reset "count" to zero. The kernel
+ * size eventfd_signal() also, adds to the "count" counter and
+ * issue a wakeup.
+ */
+ __u64 count;
+};
+
+/*
+ * Adds "n" to the eventfd counter "count". Returns "n" in case of
+ * success, or a value lower then "n" in case of coutner overflow.
+ * This function is supposed to be called by the kernel in paths
+ * that do not allow sleeping. In this function we allow the counter
+ * to reach the ULLONG_MAX value, and we signal this as overflow
+ * condition by returining a POLLERR to poll(2).
+ */
+int eventfd_signal(struct file *file, int n)
+{
+ struct eventfd_ctx *ctx = file->private_data;
+ unsigned long flags;
+
+ if (n < 0)
+ return -EINVAL;
+ spin_lock_irqsave(&ctx->lock, flags);
+ if (ULLONG_MAX - ctx->count < n)
+ n = (int) (ULLONG_MAX - ctx->count);
+ ctx->count += n;
+ if (waitqueue_active(&ctx->wqh))
+ wake_up_locked(&ctx->wqh);
+ spin_unlock_irqrestore(&ctx->lock, flags);
+
+ return n;
+}
+
+static int eventfd_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ return 0;
+}
+
+static unsigned int eventfd_poll(struct file *file, poll_table *wait)
+{
+ struct eventfd_ctx *ctx = file->private_data;
+ unsigned int events = 0;
+ unsigned long flags;
+
+ poll_wait(file, &ctx->wqh, wait);
+
+ spin_lock_irqsave(&ctx->lock, flags);
+ if (ctx->count > 0)
+ events |= POLLIN;
+ if (ctx->count == ULLONG_MAX)
+ events |= POLLERR;
+ if (ULLONG_MAX - 1 > ctx->count)
+ events |= POLLOUT;
+ spin_unlock_irqrestore(&ctx->lock, flags);
+
+ return events;
+}
+
+static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct eventfd_ctx *ctx = file->private_data;
+ ssize_t res;
+ __u64 ucnt;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (count < sizeof(ucnt))
+ return -EINVAL;
+ spin_lock_irq(&ctx->lock);
+ res = -EAGAIN;
+ ucnt = ctx->count;
+ if (ucnt > 0)
+ res = sizeof(ucnt);
+ else if (!(file->f_flags & O_NONBLOCK)) {
+ __add_wait_queue(&ctx->wqh, &wait);
+ for (res = 0;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (ctx->count > 0) {
+ ucnt = ctx->count;
+ res = sizeof(ucnt);
+ break;
+ }
+ if (signal_pending(current)) {
+ res = -ERESTARTSYS;
+ break;
+ }
+ spin_unlock_irq(&ctx->lock);
+ schedule();
+ spin_lock_irq(&ctx->lock);
+ }
+ __remove_wait_queue(&ctx->wqh, &wait);
+ __set_current_state(TASK_RUNNING);
+ }
+ if (res > 0) {
+ ctx->count = 0;
+ if (waitqueue_active(&ctx->wqh))
+ wake_up_locked(&ctx->wqh);
+ }
+ spin_unlock_irq(&ctx->lock);
+ if (res > 0 && put_user(ucnt, (__u64 __user *) buf))
+ return -EFAULT;
+
+ return res;
+}
+
+static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct eventfd_ctx *ctx = file->private_data;
+ ssize_t res;
+ __u64 ucnt;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (count < sizeof(ucnt))
+ return -EINVAL;
+ if (copy_from_user(&ucnt, buf, sizeof(ucnt)))
+ return -EFAULT;
+ if (ucnt == ULLONG_MAX)
+ return -EINVAL;
+ spin_lock_irq(&ctx->lock);
+ res = -EAGAIN;
+ if (ULLONG_MAX - ctx->count > ucnt)
+ res = sizeof(ucnt);
+ else if (!(file->f_flags & O_NONBLOCK)) {
+ __add_wait_queue(&ctx->wqh, &wait);
+ for (res = 0;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (ULLONG_MAX - ctx->count > ucnt) {
+ res = sizeof(ucnt);
+ break;
+ }
+ if (signal_pending(current)) {
+ res = -ERESTARTSYS;
+ break;
+ }
+ spin_unlock_irq(&ctx->lock);
+ schedule();
+ spin_lock_irq(&ctx->lock);
+ }
+ __remove_wait_queue(&ctx->wqh, &wait);
+ __set_current_state(TASK_RUNNING);
+ }
+ if (res > 0) {
+ ctx->count += ucnt;
+ if (waitqueue_active(&ctx->wqh))
+ wake_up_locked(&ctx->wqh);
+ }
+ spin_unlock_irq(&ctx->lock);
+
+ return res;
+}
+
+static const struct file_operations eventfd_fops = {
+ .release = eventfd_release,
+ .poll = eventfd_poll,
+ .read = eventfd_read,
+ .write = eventfd_write,
+};
+
+struct file *eventfd_fget(int fd)
+{
+ struct file *file;
+
+ file = fget(fd);
+ if (!file)
+ return ERR_PTR(-EBADF);
+ if (file->f_op != &eventfd_fops) {
+ fput(file);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return file;
+}
+
+asmlinkage long sys_eventfd(unsigned int count)
+{
+ int error, fd;
+ struct eventfd_ctx *ctx;
+ struct file *file;
+ struct inode *inode;
+
+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ init_waitqueue_head(&ctx->wqh);
+ spin_lock_init(&ctx->lock);
+ ctx->count = count;
+
+ /*
+ * When we call this, the initialization must be complete, since
+ * anon_inode_getfd() will install the fd.
+ */
+ error = anon_inode_getfd(&fd, &inode, &file, "[eventfd]",
+ &eventfd_fops, ctx);
+ if (!error)
+ return fd;
+
+ kfree(ctx);
+ return error;
+}
+
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index b5c7ca5..1aad34e 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -11,7 +11,6 @@
*
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -34,6 +33,7 @@
#include <linux/mount.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <linux/anon_inodes.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -41,7 +41,6 @@
#include <asm/atomic.h>
#include <asm/semaphore.h>
-
/*
* LOCKING:
* There are three level of locking required by epoll :
@@ -74,9 +73,6 @@
* a greater scalability.
*/
-
-#define EVENTPOLLFS_MAGIC 0x03111965 /* My birthday should work for this :) */
-
#define DEBUG_EPOLL 0
#if DEBUG_EPOLL > 0
@@ -106,7 +102,6 @@
#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
-
struct epoll_filefd {
struct file *file;
int fd;
@@ -224,43 +219,6 @@
struct epitem *epi;
};
-
-
-static void ep_poll_safewake_init(struct poll_safewake *psw);
-static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
- struct eventpoll *ep);
-static int ep_alloc(struct eventpoll **pep);
-static void ep_free(struct eventpoll *ep);
-static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
-static void ep_use_epitem(struct epitem *epi);
-static void ep_release_epitem(struct epitem *epi);
-static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
- poll_table *pt);
-static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi);
-static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
- struct file *tfile, int fd);
-static int ep_modify(struct eventpoll *ep, struct epitem *epi,
- struct epoll_event *event);
-static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi);
-static int ep_unlink(struct eventpoll *ep, struct epitem *epi);
-static int ep_remove(struct eventpoll *ep, struct epitem *epi);
-static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key);
-static int ep_eventpoll_close(struct inode *inode, struct file *file);
-static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait);
-static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
- struct epoll_event __user *events, int maxevents);
-static int ep_events_transfer(struct eventpoll *ep,
- struct epoll_event __user *events,
- int maxevents);
-static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
- int maxevents, long timeout);
-static int eventpollfs_delete_dentry(struct dentry *dentry);
-static struct inode *ep_eventpoll_inode(void);
-static int eventpollfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name,
- void *data, struct vfsmount *mnt);
-
/*
* This semaphore is used to serialize ep_free() and eventpoll_release_file().
*/
@@ -275,37 +233,6 @@
/* Slab cache used to allocate "struct eppoll_entry" */
static struct kmem_cache *pwq_cache __read_mostly;
-/* Virtual fs used to allocate inodes for eventpoll files */
-static struct vfsmount *eventpoll_mnt __read_mostly;
-
-/* File callbacks that implement the eventpoll file behaviour */
-static const struct file_operations eventpoll_fops = {
- .release = ep_eventpoll_close,
- .poll = ep_eventpoll_poll
-};
-
-/*
- * This is used to register the virtual file system from where
- * eventpoll inodes are allocated.
- */
-static struct file_system_type eventpoll_fs_type = {
- .name = "eventpollfs",
- .get_sb = eventpollfs_get_sb,
- .kill_sb = kill_anon_super,
-};
-
-/* Very basic directory entry operations for the eventpoll virtual file system */
-static struct dentry_operations eventpollfs_dentry_operations = {
- .d_delete = eventpollfs_delete_dentry,
-};
-
-
-
-/* Fast test to see if the file is an evenpoll file */
-static inline int is_file_epoll(struct file *f)
-{
- return f->f_op == &eventpoll_fops;
-}
/* Setup the structure that is used as key for the rb-tree */
static inline void ep_set_ffd(struct epoll_filefd *ffd,
@@ -374,7 +301,6 @@
spin_lock_init(&psw->lock);
}
-
/*
* Perform a safe wake up of the poll wait list. The problem is that
* with the new callback'd wake up system, it is possible that the
@@ -429,400 +355,145 @@
spin_unlock_irqrestore(&psw->lock, flags);
}
+/*
+ * This function unregister poll callbacks from the associated file descriptor.
+ * Since this must be called without holding "ep->lock" the atomic exchange trick
+ * will protect us from multiple unregister.
+ */
+static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
+{
+ int nwait;
+ struct list_head *lsthead = &epi->pwqlist;
+ struct eppoll_entry *pwq;
+
+ /* This is called without locks, so we need the atomic exchange */
+ nwait = xchg(&epi->nwait, 0);
+
+ if (nwait) {
+ while (!list_empty(lsthead)) {
+ pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
+
+ list_del_init(&pwq->llink);
+ remove_wait_queue(pwq->whead, &pwq->wait);
+ kmem_cache_free(pwq_cache, pwq);
+ }
+ }
+}
/*
- * This is called from eventpoll_release() to unlink files from the eventpoll
- * interface. We need to have this facility to cleanup correctly files that are
- * closed without being removed from the eventpoll interface.
+ * Unlink the "struct epitem" from all places it might have been hooked up.
+ * This function must be called with write IRQ lock on "ep->lock".
*/
-void eventpoll_release_file(struct file *file)
+static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
{
- struct list_head *lsthead = &file->f_ep_links;
- struct eventpoll *ep;
- struct epitem *epi;
+ int error;
/*
- * We don't want to get "file->f_ep_lock" because it is not
- * necessary. It is not necessary because we're in the "struct file"
- * cleanup path, and this means that noone is using this file anymore.
- * The only hit might come from ep_free() but by holding the semaphore
- * will correctly serialize the operation. We do need to acquire
- * "ep->sem" after "epmutex" because ep_remove() requires it when called
- * from anywhere but ep_free().
+ * It can happen that this one is called for an item already unlinked.
+ * The check protect us from doing a double unlink ( crash ).
*/
- mutex_lock(&epmutex);
+ error = -ENOENT;
+ if (!ep_rb_linked(&epi->rbn))
+ goto error_return;
- while (!list_empty(lsthead)) {
- epi = list_first_entry(lsthead, struct epitem, fllink);
+ /*
+ * Clear the event mask for the unlinked item. This will avoid item
+ * notifications to be sent after the unlink operation from inside
+ * the kernel->userspace event transfer loop.
+ */
+ epi->event.events = 0;
- ep = epi->ep;
+ /*
+ * At this point is safe to do the job, unlink the item from our rb-tree.
+ * This operation togheter with the above check closes the door to
+ * double unlinks.
+ */
+ ep_rb_erase(&epi->rbn, &ep->rbr);
+
+ /*
+ * If the item we are going to remove is inside the ready file descriptors
+ * we want to remove it from this list to avoid stale events.
+ */
+ if (ep_is_linked(&epi->rdllink))
+ list_del_init(&epi->rdllink);
+
+ error = 0;
+error_return:
+
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n",
+ current, ep, epi->ffd.file, error));
+
+ return error;
+}
+
+/*
+ * Increment the usage count of the "struct epitem" making it sure
+ * that the user will have a valid pointer to reference.
+ */
+static void ep_use_epitem(struct epitem *epi)
+{
+ atomic_inc(&epi->usecnt);
+}
+
+/*
+ * Decrement ( release ) the usage count by signaling that the user
+ * has finished using the structure. It might lead to freeing the
+ * structure itself if the count goes to zero.
+ */
+static void ep_release_epitem(struct epitem *epi)
+{
+ if (atomic_dec_and_test(&epi->usecnt))
+ kmem_cache_free(epi_cache, epi);
+}
+
+/*
+ * Removes a "struct epitem" from the eventpoll RB tree and deallocates
+ * all the associated resources.
+ */
+static int ep_remove(struct eventpoll *ep, struct epitem *epi)
+{
+ int error;
+ unsigned long flags;
+ struct file *file = epi->ffd.file;
+
+ /*
+ * Removes poll wait queue hooks. We _have_ to do this without holding
+ * the "ep->lock" otherwise a deadlock might occur. This because of the
+ * sequence of the lock acquisition. Here we do "ep->lock" then the wait
+ * queue head lock when unregistering the wait queue. The wakeup callback
+ * will run by holding the wait queue head lock and will call our callback
+ * that will try to get "ep->lock".
+ */
+ ep_unregister_pollwait(ep, epi);
+
+ /* Remove the current item from the list of epoll hooks */
+ spin_lock(&file->f_ep_lock);
+ if (ep_is_linked(&epi->fllink))
list_del_init(&epi->fllink);
- down_write(&ep->sem);
- ep_remove(ep, epi);
- up_write(&ep->sem);
- }
+ spin_unlock(&file->f_ep_lock);
- mutex_unlock(&epmutex);
-}
+ /* We need to acquire the write IRQ lock before calling ep_unlink() */
+ write_lock_irqsave(&ep->lock, flags);
+ /* Really unlink the item from the RB tree */
+ error = ep_unlink(ep, epi);
-/*
- * It opens an eventpoll file descriptor by suggesting a storage of "size"
- * file descriptors. The size parameter is just an hint about how to size
- * data structures. It won't prevent the user to store more than "size"
- * file descriptors inside the epoll interface. It is the kernel part of
- * the userspace epoll_create(2).
- */
-asmlinkage long sys_epoll_create(int size)
-{
- int error, fd = -1;
- struct eventpoll *ep;
- struct inode *inode;
- struct file *file;
+ write_unlock_irqrestore(&ep->lock, flags);
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
- current, size));
-
- /*
- * Sanity check on the size parameter, and create the internal data
- * structure ( "struct eventpoll" ).
- */
- error = -EINVAL;
- if (size <= 0 || (error = ep_alloc(&ep)) != 0)
- goto eexit_1;
-
- /*
- * Creates all the items needed to setup an eventpoll file. That is,
- * a file structure, and inode and a free file descriptor.
- */
- error = ep_getfd(&fd, &inode, &file, ep);
if (error)
- goto eexit_2;
+ goto error_return;
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
- current, size, fd));
+ /* At this point it is safe to free the eventpoll item */
+ ep_release_epitem(epi);
- return fd;
-
-eexit_2:
- ep_free(ep);
- kfree(ep);
-eexit_1:
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
- current, size, error));
- return error;
-}
-
-
-/*
- * The following function implements the controller interface for
- * the eventpoll file that enables the insertion/removal/change of
- * file descriptors inside the interest set. It represents
- * the kernel part of the user space epoll_ctl(2).
- */
-asmlinkage long
-sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
-{
- int error;
- struct file *file, *tfile;
- struct eventpoll *ep;
- struct epitem *epi;
- struct epoll_event epds;
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n",
- current, epfd, op, fd, event));
-
- error = -EFAULT;
- if (ep_op_has_event(op) &&
- copy_from_user(&epds, event, sizeof(struct epoll_event)))
- goto eexit_1;
-
- /* Get the "struct file *" for the eventpoll file */
- error = -EBADF;
- file = fget(epfd);
- if (!file)
- goto eexit_1;
-
- /* Get the "struct file *" for the target file */
- tfile = fget(fd);
- if (!tfile)
- goto eexit_2;
-
- /* The target file descriptor must support poll */
- error = -EPERM;
- if (!tfile->f_op || !tfile->f_op->poll)
- goto eexit_3;
-
- /*
- * We have to check that the file structure underneath the file descriptor
- * the user passed to us _is_ an eventpoll file. And also we do not permit
- * adding an epoll file descriptor inside itself.
- */
- error = -EINVAL;
- if (file == tfile || !is_file_epoll(file))
- goto eexit_3;
-
- /*
- * At this point it is safe to assume that the "private_data" contains
- * our own data structure.
- */
- ep = file->private_data;
-
- down_write(&ep->sem);
-
- /* Try to lookup the file inside our RB tree */
- epi = ep_find(ep, tfile, fd);
-
- error = -EINVAL;
- switch (op) {
- case EPOLL_CTL_ADD:
- if (!epi) {
- epds.events |= POLLERR | POLLHUP;
-
- error = ep_insert(ep, &epds, tfile, fd);
- } else
- error = -EEXIST;
- break;
- case EPOLL_CTL_DEL:
- if (epi)
- error = ep_remove(ep, epi);
- else
- error = -ENOENT;
- break;
- case EPOLL_CTL_MOD:
- if (epi) {
- epds.events |= POLLERR | POLLHUP;
- error = ep_modify(ep, epi, &epds);
- } else
- error = -ENOENT;
- break;
- }
-
- /*
- * The function ep_find() increments the usage count of the structure
- * so, if this is not NULL, we need to release it.
- */
- if (epi)
- ep_release_epitem(epi);
-
- up_write(&ep->sem);
-
-eexit_3:
- fput(tfile);
-eexit_2:
- fput(file);
-eexit_1:
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n",
- current, epfd, op, fd, event, error));
+ error = 0;
+error_return:
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p) = %d\n",
+ current, ep, file, error));
return error;
}
-
-/*
- * Implement the event wait interface for the eventpoll file. It is the kernel
- * part of the user space epoll_wait(2).
- */
-asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
- int maxevents, int timeout)
-{
- int error;
- struct file *file;
- struct eventpoll *ep;
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d)\n",
- current, epfd, events, maxevents, timeout));
-
- /* The maximum number of event must be greater than zero */
- if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
- return -EINVAL;
-
- /* Verify that the area passed by the user is writeable */
- if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) {
- error = -EFAULT;
- goto eexit_1;
- }
-
- /* Get the "struct file *" for the eventpoll file */
- error = -EBADF;
- file = fget(epfd);
- if (!file)
- goto eexit_1;
-
- /*
- * We have to check that the file structure underneath the fd
- * the user passed to us _is_ an eventpoll file.
- */
- error = -EINVAL;
- if (!is_file_epoll(file))
- goto eexit_2;
-
- /*
- * At this point it is safe to assume that the "private_data" contains
- * our own data structure.
- */
- ep = file->private_data;
-
- /* Time to fish for events ... */
- error = ep_poll(ep, events, maxevents, timeout);
-
-eexit_2:
- fput(file);
-eexit_1:
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n",
- current, epfd, events, maxevents, timeout, error));
-
- return error;
-}
-
-
-#ifdef TIF_RESTORE_SIGMASK
-
-/*
- * Implement the event wait interface for the eventpoll file. It is the kernel
- * part of the user space epoll_pwait(2).
- */
-asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
- int maxevents, int timeout, const sigset_t __user *sigmask,
- size_t sigsetsize)
-{
- int error;
- sigset_t ksigmask, sigsaved;
-
- /*
- * If the caller wants a certain signal mask to be set during the wait,
- * we apply it here.
- */
- if (sigmask) {
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
- if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
- return -EFAULT;
- sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
-
- error = sys_epoll_wait(epfd, events, maxevents, timeout);
-
- /*
- * If we changed the signal mask, we need to restore the original one.
- * In case we've got a signal while waiting, we do not restore the
- * signal mask yet, and we allow do_signal() to deliver the signal on
- * the way back to userspace, before the signal mask is restored.
- */
- if (sigmask) {
- if (error == -EINTR) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_thread_flag(TIF_RESTORE_SIGMASK);
- } else
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
- }
-
- return error;
-}
-
-#endif /* #ifdef TIF_RESTORE_SIGMASK */
-
-
-/*
- * Creates the file descriptor to be used by the epoll interface.
- */
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
- struct eventpoll *ep)
-{
- struct qstr this;
- char name[32];
- struct dentry *dentry;
- struct inode *inode;
- struct file *file;
- int error, fd;
-
- /* Get an ready to use file */
- error = -ENFILE;
- file = get_empty_filp();
- if (!file)
- goto eexit_1;
-
- /* Allocates an inode from the eventpoll file system */
- inode = ep_eventpoll_inode();
- if (IS_ERR(inode)) {
- error = PTR_ERR(inode);
- goto eexit_2;
- }
-
- /* Allocates a free descriptor to plug the file onto */
- error = get_unused_fd();
- if (error < 0)
- goto eexit_3;
- fd = error;
-
- /*
- * Link the inode to a directory entry by creating a unique name
- * using the inode number.
- */
- error = -ENOMEM;
- sprintf(name, "[%lu]", inode->i_ino);
- this.name = name;
- this.len = strlen(name);
- this.hash = inode->i_ino;
- dentry = d_alloc(eventpoll_mnt->mnt_sb->s_root, &this);
- if (!dentry)
- goto eexit_4;
- dentry->d_op = &eventpollfs_dentry_operations;
- d_add(dentry, inode);
- file->f_path.mnt = mntget(eventpoll_mnt);
- file->f_path.dentry = dentry;
- file->f_mapping = inode->i_mapping;
-
- file->f_pos = 0;
- file->f_flags = O_RDONLY;
- file->f_op = &eventpoll_fops;
- file->f_mode = FMODE_READ;
- file->f_version = 0;
- file->private_data = ep;
-
- /* Install the new setup file into the allocated fd. */
- fd_install(fd, file);
-
- *efd = fd;
- *einode = inode;
- *efile = file;
- return 0;
-
-eexit_4:
- put_unused_fd(fd);
-eexit_3:
- iput(inode);
-eexit_2:
- put_filp(file);
-eexit_1:
- return error;
-}
-
-
-static int ep_alloc(struct eventpoll **pep)
-{
- struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL);
-
- if (!ep)
- return -ENOMEM;
-
- rwlock_init(&ep->lock);
- init_rwsem(&ep->sem);
- init_waitqueue_head(&ep->wq);
- init_waitqueue_head(&ep->poll_wait);
- INIT_LIST_HEAD(&ep->rdllist);
- ep->rbr = RB_ROOT;
-
- *pep = ep;
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n",
- current, ep));
- return 0;
-}
-
-
static void ep_free(struct eventpoll *ep)
{
struct rb_node *rbp;
@@ -865,6 +536,104 @@
mutex_unlock(&epmutex);
}
+static int ep_eventpoll_release(struct inode *inode, struct file *file)
+{
+ struct eventpoll *ep = file->private_data;
+
+ if (ep) {
+ ep_free(ep);
+ kfree(ep);
+ }
+
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep));
+ return 0;
+}
+
+static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
+{
+ unsigned int pollflags = 0;
+ unsigned long flags;
+ struct eventpoll *ep = file->private_data;
+
+ /* Insert inside our poll wait queue */
+ poll_wait(file, &ep->poll_wait, wait);
+
+ /* Check our condition */
+ read_lock_irqsave(&ep->lock, flags);
+ if (!list_empty(&ep->rdllist))
+ pollflags = POLLIN | POLLRDNORM;
+ read_unlock_irqrestore(&ep->lock, flags);
+
+ return pollflags;
+}
+
+/* File callbacks that implement the eventpoll file behaviour */
+static const struct file_operations eventpoll_fops = {
+ .release = ep_eventpoll_release,
+ .poll = ep_eventpoll_poll
+};
+
+/* Fast test to see if the file is an evenpoll file */
+static inline int is_file_epoll(struct file *f)
+{
+ return f->f_op == &eventpoll_fops;
+}
+
+/*
+ * This is called from eventpoll_release() to unlink files from the eventpoll
+ * interface. We need to have this facility to cleanup correctly files that are
+ * closed without being removed from the eventpoll interface.
+ */
+void eventpoll_release_file(struct file *file)
+{
+ struct list_head *lsthead = &file->f_ep_links;
+ struct eventpoll *ep;
+ struct epitem *epi;
+
+ /*
+ * We don't want to get "file->f_ep_lock" because it is not
+ * necessary. It is not necessary because we're in the "struct file"
+ * cleanup path, and this means that noone is using this file anymore.
+ * The only hit might come from ep_free() but by holding the semaphore
+ * will correctly serialize the operation. We do need to acquire
+ * "ep->sem" after "epmutex" because ep_remove() requires it when called
+ * from anywhere but ep_free().
+ */
+ mutex_lock(&epmutex);
+
+ while (!list_empty(lsthead)) {
+ epi = list_first_entry(lsthead, struct epitem, fllink);
+
+ ep = epi->ep;
+ list_del_init(&epi->fllink);
+ down_write(&ep->sem);
+ ep_remove(ep, epi);
+ up_write(&ep->sem);
+ }
+
+ mutex_unlock(&epmutex);
+}
+
+static int ep_alloc(struct eventpoll **pep)
+{
+ struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL);
+
+ if (!ep)
+ return -ENOMEM;
+
+ rwlock_init(&ep->lock);
+ init_rwsem(&ep->sem);
+ init_waitqueue_head(&ep->wq);
+ init_waitqueue_head(&ep->poll_wait);
+ INIT_LIST_HEAD(&ep->rdllist);
+ ep->rbr = RB_ROOT;
+
+ *pep = ep;
+
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n",
+ current, ep));
+ return 0;
+}
/*
* Search the file inside the eventpoll tree. It add usage count to
@@ -902,31 +671,59 @@
return epir;
}
-
/*
- * Increment the usage count of the "struct epitem" making it sure
- * that the user will have a valid pointer to reference.
+ * This is the callback that is passed to the wait queue wakeup
+ * machanism. It is called by the stored file descriptors when they
+ * have events to report.
*/
-static void ep_use_epitem(struct epitem *epi)
+static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
+ int pwake = 0;
+ unsigned long flags;
+ struct epitem *epi = ep_item_from_wait(wait);
+ struct eventpoll *ep = epi->ep;
- atomic_inc(&epi->usecnt);
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
+ current, epi->ffd.file, epi, ep));
+
+ write_lock_irqsave(&ep->lock, flags);
+
+ /*
+ * If the event mask does not contain any poll(2) event, we consider the
+ * descriptor to be disabled. This condition is likely the effect of the
+ * EPOLLONESHOT bit that disables the descriptor when an event is received,
+ * until the next EPOLL_CTL_MOD will be issued.
+ */
+ if (!(epi->event.events & ~EP_PRIVATE_BITS))
+ goto is_disabled;
+
+ /* If this file is already in the ready list we exit soon */
+ if (ep_is_linked(&epi->rdllink))
+ goto is_linked;
+
+ list_add_tail(&epi->rdllink, &ep->rdllist);
+
+is_linked:
+ /*
+ * Wake up ( if active ) both the eventpoll wait list and the ->poll()
+ * wait list.
+ */
+ if (waitqueue_active(&ep->wq))
+ __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+ TASK_INTERRUPTIBLE);
+ if (waitqueue_active(&ep->poll_wait))
+ pwake++;
+
+is_disabled:
+ write_unlock_irqrestore(&ep->lock, flags);
+
+ /* We have to call this outside the lock */
+ if (pwake)
+ ep_poll_safewake(&psw, &ep->poll_wait);
+
+ return 1;
}
-
-/*
- * Decrement ( release ) the usage count by signaling that the user
- * has finished using the structure. It might lead to freeing the
- * structure itself if the count goes to zero.
- */
-static void ep_release_epitem(struct epitem *epi)
-{
-
- if (atomic_dec_and_test(&epi->usecnt))
- kmem_cache_free(epi_cache, epi);
-}
-
-
/*
* This is the callback that is used to add our wait queue to the
* target file wakeup lists.
@@ -950,7 +747,6 @@
}
}
-
static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
{
int kcmp;
@@ -970,7 +766,6 @@
rb_insert_color(&epi->rbn, &ep->rbr);
}
-
static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
struct file *tfile, int fd)
{
@@ -981,7 +776,7 @@
error = -ENOMEM;
if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL)))
- goto eexit_1;
+ goto error_return;
/* Item initialization follow here ... */
ep_rb_initnode(&epi->rbn);
@@ -1011,7 +806,7 @@
* high memory pressure.
*/
if (epi->nwait < 0)
- goto eexit_2;
+ goto error_unregister;
/* Add the current item to the list of active epoll hook for this file */
spin_lock(&tfile->f_ep_lock);
@@ -1046,7 +841,7 @@
return 0;
-eexit_2:
+error_unregister:
ep_unregister_pollwait(ep, epi);
/*
@@ -1059,11 +854,10 @@
write_unlock_irqrestore(&ep->lock, flags);
kmem_cache_free(epi_cache, epi);
-eexit_1:
+error_return:
return error;
}
-
/*
* Modify the interest event mask by dropping an event if the new mask
* has a match in the current file status.
@@ -1126,216 +920,6 @@
return 0;
}
-
-/*
- * This function unregister poll callbacks from the associated file descriptor.
- * Since this must be called without holding "ep->lock" the atomic exchange trick
- * will protect us from multiple unregister.
- */
-static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
-{
- int nwait;
- struct list_head *lsthead = &epi->pwqlist;
- struct eppoll_entry *pwq;
-
- /* This is called without locks, so we need the atomic exchange */
- nwait = xchg(&epi->nwait, 0);
-
- if (nwait) {
- while (!list_empty(lsthead)) {
- pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
-
- list_del_init(&pwq->llink);
- remove_wait_queue(pwq->whead, &pwq->wait);
- kmem_cache_free(pwq_cache, pwq);
- }
- }
-}
-
-
-/*
- * Unlink the "struct epitem" from all places it might have been hooked up.
- * This function must be called with write IRQ lock on "ep->lock".
- */
-static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
-{
- int error;
-
- /*
- * It can happen that this one is called for an item already unlinked.
- * The check protect us from doing a double unlink ( crash ).
- */
- error = -ENOENT;
- if (!ep_rb_linked(&epi->rbn))
- goto eexit_1;
-
- /*
- * Clear the event mask for the unlinked item. This will avoid item
- * notifications to be sent after the unlink operation from inside
- * the kernel->userspace event transfer loop.
- */
- epi->event.events = 0;
-
- /*
- * At this point is safe to do the job, unlink the item from our rb-tree.
- * This operation togheter with the above check closes the door to
- * double unlinks.
- */
- ep_rb_erase(&epi->rbn, &ep->rbr);
-
- /*
- * If the item we are going to remove is inside the ready file descriptors
- * we want to remove it from this list to avoid stale events.
- */
- if (ep_is_linked(&epi->rdllink))
- list_del_init(&epi->rdllink);
-
- error = 0;
-eexit_1:
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n",
- current, ep, epi->ffd.file, error));
-
- return error;
-}
-
-
-/*
- * Removes a "struct epitem" from the eventpoll RB tree and deallocates
- * all the associated resources.
- */
-static int ep_remove(struct eventpoll *ep, struct epitem *epi)
-{
- int error;
- unsigned long flags;
- struct file *file = epi->ffd.file;
-
- /*
- * Removes poll wait queue hooks. We _have_ to do this without holding
- * the "ep->lock" otherwise a deadlock might occur. This because of the
- * sequence of the lock acquisition. Here we do "ep->lock" then the wait
- * queue head lock when unregistering the wait queue. The wakeup callback
- * will run by holding the wait queue head lock and will call our callback
- * that will try to get "ep->lock".
- */
- ep_unregister_pollwait(ep, epi);
-
- /* Remove the current item from the list of epoll hooks */
- spin_lock(&file->f_ep_lock);
- if (ep_is_linked(&epi->fllink))
- list_del_init(&epi->fllink);
- spin_unlock(&file->f_ep_lock);
-
- /* We need to acquire the write IRQ lock before calling ep_unlink() */
- write_lock_irqsave(&ep->lock, flags);
-
- /* Really unlink the item from the RB tree */
- error = ep_unlink(ep, epi);
-
- write_unlock_irqrestore(&ep->lock, flags);
-
- if (error)
- goto eexit_1;
-
- /* At this point it is safe to free the eventpoll item */
- ep_release_epitem(epi);
-
- error = 0;
-eexit_1:
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p) = %d\n",
- current, ep, file, error));
-
- return error;
-}
-
-
-/*
- * This is the callback that is passed to the wait queue wakeup
- * machanism. It is called by the stored file descriptors when they
- * have events to report.
- */
-static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
- int pwake = 0;
- unsigned long flags;
- struct epitem *epi = ep_item_from_wait(wait);
- struct eventpoll *ep = epi->ep;
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
- current, epi->ffd.file, epi, ep));
-
- write_lock_irqsave(&ep->lock, flags);
-
- /*
- * If the event mask does not contain any poll(2) event, we consider the
- * descriptor to be disabled. This condition is likely the effect of the
- * EPOLLONESHOT bit that disables the descriptor when an event is received,
- * until the next EPOLL_CTL_MOD will be issued.
- */
- if (!(epi->event.events & ~EP_PRIVATE_BITS))
- goto is_disabled;
-
- /* If this file is already in the ready list we exit soon */
- if (ep_is_linked(&epi->rdllink))
- goto is_linked;
-
- list_add_tail(&epi->rdllink, &ep->rdllist);
-
-is_linked:
- /*
- * Wake up ( if active ) both the eventpoll wait list and the ->poll()
- * wait list.
- */
- if (waitqueue_active(&ep->wq))
- __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
- TASK_INTERRUPTIBLE);
- if (waitqueue_active(&ep->poll_wait))
- pwake++;
-
-is_disabled:
- write_unlock_irqrestore(&ep->lock, flags);
-
- /* We have to call this outside the lock */
- if (pwake)
- ep_poll_safewake(&psw, &ep->poll_wait);
-
- return 1;
-}
-
-
-static int ep_eventpoll_close(struct inode *inode, struct file *file)
-{
- struct eventpoll *ep = file->private_data;
-
- if (ep) {
- ep_free(ep);
- kfree(ep);
- }
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep));
- return 0;
-}
-
-
-static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
-{
- unsigned int pollflags = 0;
- unsigned long flags;
- struct eventpoll *ep = file->private_data;
-
- /* Insert inside our poll wait queue */
- poll_wait(file, &ep->poll_wait, wait);
-
- /* Check our condition */
- read_lock_irqsave(&ep->lock, flags);
- if (!list_empty(&ep->rdllist))
- pollflags = POLLIN | POLLRDNORM;
- read_unlock_irqrestore(&ep->lock, flags);
-
- return pollflags;
-}
-
-
/*
* This function is called without holding the "ep->lock" since the call to
* __copy_to_user() might sleep, and also f_op->poll() might reenable the IRQ
@@ -1447,7 +1031,6 @@
return eventcnt == 0 ? error: eventcnt;
}
-
/*
* Perform the transfer of events to user space.
*/
@@ -1483,7 +1066,6 @@
return eventcnt;
}
-
static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
int maxevents, long timeout)
{
@@ -1553,52 +1135,262 @@
return res;
}
-static int eventpollfs_delete_dentry(struct dentry *dentry)
+/*
+ * It opens an eventpoll file descriptor by suggesting a storage of "size"
+ * file descriptors. The size parameter is just an hint about how to size
+ * data structures. It won't prevent the user to store more than "size"
+ * file descriptors inside the epoll interface. It is the kernel part of
+ * the userspace epoll_create(2).
+ */
+asmlinkage long sys_epoll_create(int size)
{
+ int error, fd = -1;
+ struct eventpoll *ep;
+ struct inode *inode;
+ struct file *file;
- return 1;
-}
-
-static struct inode *ep_eventpoll_inode(void)
-{
- int error = -ENOMEM;
- struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
-
- if (!inode)
- goto eexit_1;
-
- inode->i_fop = &eventpoll_fops;
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
+ current, size));
/*
- * Mark the inode dirty from the very beginning,
- * that way it will never be moved to the dirty
- * list because mark_inode_dirty() will think
- * that it already _is_ on the dirty list.
+ * Sanity check on the size parameter, and create the internal data
+ * structure ( "struct eventpoll" ).
*/
- inode->i_state = I_DIRTY;
- inode->i_mode = S_IRUSR | S_IWUSR;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- return inode;
+ error = -EINVAL;
+ if (size <= 0 || (error = ep_alloc(&ep)) != 0)
+ goto error_return;
-eexit_1:
- return ERR_PTR(error);
+ /*
+ * Creates all the items needed to setup an eventpoll file. That is,
+ * a file structure, and inode and a free file descriptor.
+ */
+ error = anon_inode_getfd(&fd, &inode, &file, "[eventpoll]",
+ &eventpoll_fops, ep);
+ if (error)
+ goto error_free;
+
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
+ current, size, fd));
+
+ return fd;
+
+error_free:
+ ep_free(ep);
+ kfree(ep);
+error_return:
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
+ current, size, error));
+ return error;
}
-static int
-eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
- const char *dev_name, void *data, struct vfsmount *mnt)
+/*
+ * The following function implements the controller interface for
+ * the eventpoll file that enables the insertion/removal/change of
+ * file descriptors inside the interest set. It represents
+ * the kernel part of the user space epoll_ctl(2).
+ */
+asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
+ struct epoll_event __user *event)
{
- return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC,
- mnt);
+ int error;
+ struct file *file, *tfile;
+ struct eventpoll *ep;
+ struct epitem *epi;
+ struct epoll_event epds;
+
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n",
+ current, epfd, op, fd, event));
+
+ error = -EFAULT;
+ if (ep_op_has_event(op) &&
+ copy_from_user(&epds, event, sizeof(struct epoll_event)))
+ goto error_return;
+
+ /* Get the "struct file *" for the eventpoll file */
+ error = -EBADF;
+ file = fget(epfd);
+ if (!file)
+ goto error_return;
+
+ /* Get the "struct file *" for the target file */
+ tfile = fget(fd);
+ if (!tfile)
+ goto error_fput;
+
+ /* The target file descriptor must support poll */
+ error = -EPERM;
+ if (!tfile->f_op || !tfile->f_op->poll)
+ goto error_tgt_fput;
+
+ /*
+ * We have to check that the file structure underneath the file descriptor
+ * the user passed to us _is_ an eventpoll file. And also we do not permit
+ * adding an epoll file descriptor inside itself.
+ */
+ error = -EINVAL;
+ if (file == tfile || !is_file_epoll(file))
+ goto error_tgt_fput;
+
+ /*
+ * At this point it is safe to assume that the "private_data" contains
+ * our own data structure.
+ */
+ ep = file->private_data;
+
+ down_write(&ep->sem);
+
+ /* Try to lookup the file inside our RB tree */
+ epi = ep_find(ep, tfile, fd);
+
+ error = -EINVAL;
+ switch (op) {
+ case EPOLL_CTL_ADD:
+ if (!epi) {
+ epds.events |= POLLERR | POLLHUP;
+
+ error = ep_insert(ep, &epds, tfile, fd);
+ } else
+ error = -EEXIST;
+ break;
+ case EPOLL_CTL_DEL:
+ if (epi)
+ error = ep_remove(ep, epi);
+ else
+ error = -ENOENT;
+ break;
+ case EPOLL_CTL_MOD:
+ if (epi) {
+ epds.events |= POLLERR | POLLHUP;
+ error = ep_modify(ep, epi, &epds);
+ } else
+ error = -ENOENT;
+ break;
+ }
+ /*
+ * The function ep_find() increments the usage count of the structure
+ * so, if this is not NULL, we need to release it.
+ */
+ if (epi)
+ ep_release_epitem(epi);
+ up_write(&ep->sem);
+
+error_tgt_fput:
+ fput(tfile);
+error_fput:
+ fput(file);
+error_return:
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n",
+ current, epfd, op, fd, event, error));
+
+ return error;
}
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_wait(2).
+ */
+asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
+ int maxevents, int timeout)
+{
+ int error;
+ struct file *file;
+ struct eventpoll *ep;
+
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d)\n",
+ current, epfd, events, maxevents, timeout));
+
+ /* The maximum number of event must be greater than zero */
+ if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
+ return -EINVAL;
+
+ /* Verify that the area passed by the user is writeable */
+ if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) {
+ error = -EFAULT;
+ goto error_return;
+ }
+
+ /* Get the "struct file *" for the eventpoll file */
+ error = -EBADF;
+ file = fget(epfd);
+ if (!file)
+ goto error_return;
+
+ /*
+ * We have to check that the file structure underneath the fd
+ * the user passed to us _is_ an eventpoll file.
+ */
+ error = -EINVAL;
+ if (!is_file_epoll(file))
+ goto error_fput;
+
+ /*
+ * At this point it is safe to assume that the "private_data" contains
+ * our own data structure.
+ */
+ ep = file->private_data;
+
+ /* Time to fish for events ... */
+ error = ep_poll(ep, events, maxevents, timeout);
+
+error_fput:
+ fput(file);
+error_return:
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n",
+ current, epfd, events, maxevents, timeout, error));
+
+ return error;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_pwait(2).
+ */
+asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
+ int maxevents, int timeout, const sigset_t __user *sigmask,
+ size_t sigsetsize)
+{
+ int error;
+ sigset_t ksigmask, sigsaved;
+
+ /*
+ * If the caller wants a certain signal mask to be set during the wait,
+ * we apply it here.
+ */
+ if (sigmask) {
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+ return -EFAULT;
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+ }
+
+ error = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+ /*
+ * If we changed the signal mask, we need to restore the original one.
+ * In case we've got a signal while waiting, we do not restore the
+ * signal mask yet, and we allow do_signal() to deliver the signal on
+ * the way back to userspace, before the signal mask is restored.
+ */
+ if (sigmask) {
+ if (error == -EINTR) {
+ memcpy(¤t->saved_sigmask, &sigsaved,
+ sizeof(sigsaved));
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ } else
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ }
+
+ return error;
+}
+
+#endif /* #ifdef TIF_RESTORE_SIGMASK */
static int __init eventpoll_init(void)
{
- int error;
-
mutex_init(&epmutex);
/* Initialize the structure used to perform safe poll wait head wake ups */
@@ -1614,39 +1406,7 @@
sizeof(struct eppoll_entry), 0,
EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL);
- /*
- * Register the virtual file system that will be the source of inodes
- * for the eventpoll files
- */
- error = register_filesystem(&eventpoll_fs_type);
- if (error)
- goto epanic;
-
- /* Mount the above commented virtual file system */
- eventpoll_mnt = kern_mount(&eventpoll_fs_type);
- error = PTR_ERR(eventpoll_mnt);
- if (IS_ERR(eventpoll_mnt))
- goto epanic;
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: successfully initialized.\n",
- current));
return 0;
-
-epanic:
- panic("eventpoll_init() failed\n");
}
+fs_initcall(eventpoll_init);
-
-static void __exit eventpoll_exit(void)
-{
- /* Undo all operations done inside eventpoll_init() */
- unregister_filesystem(&eventpoll_fs_type);
- mntput(eventpoll_mnt);
- kmem_cache_destroy(pwq_cache);
- kmem_cache_destroy(epi_cache);
-}
-
-module_init(eventpoll_init);
-module_exit(eventpoll_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/fs/exec.c b/fs/exec.c
index 1ba85c7..70fa365 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -50,6 +50,7 @@
#include <linux/tsacct_kern.h>
#include <linux/cn_proc.h>
#include <linux/audit.h>
+#include <linux/signalfd.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -582,6 +583,13 @@
int count;
/*
+ * Tell all the sighand listeners that this sighand has
+ * been detached. The signalfd_detach() function grabs the
+ * sighand lock, if signal listeners are present on the sighand.
+ */
+ signalfd_detach(tsk);
+
+ /*
* If we don't share sighandlers, then we aren't sharing anything
* and we can just re-use it all.
*/
@@ -702,7 +710,7 @@
*/
detach_pid(tsk, PIDTYPE_PID);
tsk->pid = leader->pid;
- attach_pid(tsk, PIDTYPE_PID, tsk->pid);
+ attach_pid(tsk, PIDTYPE_PID, find_pid(tsk->pid));
transfer_pid(leader, tsk, PIDTYPE_PGID);
transfer_pid(leader, tsk, PIDTYPE_SID);
list_replace_rcu(&leader->tasks, &tsk->tasks);
@@ -757,8 +765,7 @@
spin_unlock(&oldsighand->siglock);
write_unlock_irq(&tasklist_lock);
- if (atomic_dec_and_test(&oldsighand->count))
- kmem_cache_free(sighand_cachep, oldsighand);
+ __cleanup_sighand(oldsighand);
}
BUG_ON(!thread_group_leader(tsk));
@@ -1488,6 +1495,8 @@
int flag = 0;
int ispipe = 0;
+ audit_core_dumps(signr);
+
binfmt = current->binfmt;
if (!binfmt || !binfmt->core_dump)
goto fail;
diff --git a/fs/mpage.c b/fs/mpage.c
index 0fb914f..c1698f2 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -454,11 +454,18 @@
* written, so it can intelligently allocate a suitably-sized BIO. For now,
* just allocate full-size (16-page) BIOs.
*/
-static struct bio *
-__mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
- sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc,
- writepage_t writepage_fn)
+struct mpage_data {
+ struct bio *bio;
+ sector_t last_block_in_bio;
+ get_block_t *get_block;
+ unsigned use_writepage;
+};
+
+static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
+ void *data)
{
+ struct mpage_data *mpd = data;
+ struct bio *bio = mpd->bio;
struct address_space *mapping = page->mapping;
struct inode *inode = page->mapping->host;
const unsigned blkbits = inode->i_blkbits;
@@ -476,6 +483,7 @@
int length;
struct buffer_head map_bh;
loff_t i_size = i_size_read(inode);
+ int ret = 0;
if (page_has_buffers(page)) {
struct buffer_head *head = page_buffers(page);
@@ -538,7 +546,7 @@
map_bh.b_state = 0;
map_bh.b_size = 1 << blkbits;
- if (get_block(inode, block_in_file, &map_bh, 1))
+ if (mpd->get_block(inode, block_in_file, &map_bh, 1))
goto confused;
if (buffer_new(&map_bh))
unmap_underlying_metadata(map_bh.b_bdev,
@@ -584,7 +592,7 @@
/*
* This page will go to BIO. Do we need to send this BIO off first?
*/
- if (bio && *last_block_in_bio != blocks[0] - 1)
+ if (bio && mpd->last_block_in_bio != blocks[0] - 1)
bio = mpage_bio_submit(WRITE, bio);
alloc_new:
@@ -641,7 +649,7 @@
boundary_block, 1 << blkbits);
}
} else {
- *last_block_in_bio = blocks[blocks_per_page - 1];
+ mpd->last_block_in_bio = blocks[blocks_per_page - 1];
}
goto out;
@@ -649,18 +657,19 @@
if (bio)
bio = mpage_bio_submit(WRITE, bio);
- if (writepage_fn) {
- *ret = (*writepage_fn)(page, wbc);
+ if (mpd->use_writepage) {
+ ret = mapping->a_ops->writepage(page, wbc);
} else {
- *ret = -EAGAIN;
+ ret = -EAGAIN;
goto out;
}
/*
* The caller has a ref on the inode, so *mapping is stable
*/
- mapping_set_error(mapping, *ret);
+ mapping_set_error(mapping, ret);
out:
- return bio;
+ mpd->bio = bio;
+ return ret;
}
/**
@@ -683,120 +692,27 @@
* the call was made get new I/O started against them. If wbc->sync_mode is
* WB_SYNC_ALL then we were called for data integrity and we must wait for
* existing IO to complete.
- *
- * If you fix this you should check generic_writepages() also!
*/
int
mpage_writepages(struct address_space *mapping,
struct writeback_control *wbc, get_block_t get_block)
{
- struct backing_dev_info *bdi = mapping->backing_dev_info;
- struct bio *bio = NULL;
- sector_t last_block_in_bio = 0;
- int ret = 0;
- int done = 0;
- int (*writepage)(struct page *page, struct writeback_control *wbc);
- struct pagevec pvec;
- int nr_pages;
- pgoff_t index;
- pgoff_t end; /* Inclusive */
- int scanned = 0;
- int range_whole = 0;
+ int ret;
- if (wbc->nonblocking && bdi_write_congested(bdi)) {
- wbc->encountered_congestion = 1;
- return 0;
+ if (!get_block)
+ ret = generic_writepages(mapping, wbc);
+ else {
+ struct mpage_data mpd = {
+ .bio = NULL,
+ .last_block_in_bio = 0,
+ .get_block = get_block,
+ .use_writepage = 1,
+ };
+
+ ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd);
+ if (mpd.bio)
+ mpage_bio_submit(WRITE, mpd.bio);
}
-
- writepage = NULL;
- if (get_block == NULL)
- writepage = mapping->a_ops->writepage;
-
- pagevec_init(&pvec, 0);
- if (wbc->range_cyclic) {
- index = mapping->writeback_index; /* Start from prev offset */
- end = -1;
- } else {
- index = wbc->range_start >> PAGE_CACHE_SHIFT;
- end = wbc->range_end >> PAGE_CACHE_SHIFT;
- if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
- range_whole = 1;
- scanned = 1;
- }
-retry:
- while (!done && (index <= end) &&
- (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
- PAGECACHE_TAG_DIRTY,
- min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
- unsigned i;
-
- scanned = 1;
- for (i = 0; i < nr_pages; i++) {
- struct page *page = pvec.pages[i];
-
- /*
- * At this point we hold neither mapping->tree_lock nor
- * lock on the page itself: the page may be truncated or
- * invalidated (changing page->mapping to NULL), or even
- * swizzled back from swapper_space to tmpfs file
- * mapping
- */
-
- lock_page(page);
-
- if (unlikely(page->mapping != mapping)) {
- unlock_page(page);
- continue;
- }
-
- if (!wbc->range_cyclic && page->index > end) {
- done = 1;
- unlock_page(page);
- continue;
- }
-
- if (wbc->sync_mode != WB_SYNC_NONE)
- wait_on_page_writeback(page);
-
- if (PageWriteback(page) ||
- !clear_page_dirty_for_io(page)) {
- unlock_page(page);
- continue;
- }
-
- if (writepage) {
- ret = (*writepage)(page, wbc);
- mapping_set_error(mapping, ret);
- } else {
- bio = __mpage_writepage(bio, page, get_block,
- &last_block_in_bio, &ret, wbc,
- page->mapping->a_ops->writepage);
- }
- if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
- unlock_page(page);
- if (ret || (--(wbc->nr_to_write) <= 0))
- done = 1;
- if (wbc->nonblocking && bdi_write_congested(bdi)) {
- wbc->encountered_congestion = 1;
- done = 1;
- }
- }
- pagevec_release(&pvec);
- cond_resched();
- }
- if (!scanned && !done) {
- /*
- * We hit the last page and there is more work to be done: wrap
- * back to the start of the file
- */
- scanned = 1;
- index = 0;
- goto retry;
- }
- if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
- mapping->writeback_index = index;
- if (bio)
- mpage_bio_submit(WRITE, bio);
return ret;
}
EXPORT_SYMBOL(mpage_writepages);
@@ -804,15 +720,15 @@
int mpage_writepage(struct page *page, get_block_t get_block,
struct writeback_control *wbc)
{
- int ret = 0;
- struct bio *bio;
- sector_t last_block_in_bio = 0;
-
- bio = __mpage_writepage(NULL, page, get_block,
- &last_block_in_bio, &ret, wbc, NULL);
- if (bio)
- mpage_bio_submit(WRITE, bio);
-
+ struct mpage_data mpd = {
+ .bio = NULL,
+ .last_block_in_bio = 0,
+ .get_block = get_block,
+ .use_writepage = 0,
+ };
+ int ret = __mpage_writepage(page, wbc, &mpd);
+ if (mpd.bio)
+ mpage_bio_submit(WRITE, mpd.bio);
return ret;
}
EXPORT_SYMBOL(mpage_writepage);
diff --git a/fs/namei.c b/fs/namei.c
index b3780e3..5e2d98d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1719,7 +1719,7 @@
* It already exists.
*/
mutex_unlock(&dir->d_inode->i_mutex);
- audit_inode_update(path.dentry->d_inode);
+ audit_inode(pathname, path.dentry->d_inode);
error = -EEXIST;
if (flag & O_EXCL)
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index 0120704..7638a1c 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -239,7 +239,7 @@
config SYSV68_PARTITION
bool "SYSV68 partition table support" if PARTITION_ADVANCED
- default y if M68K
+ default y if VME
help
Say Y here if you would like to be able to read the hard disk
partition table format used by Motorola Delta machines (using
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
index 1bea610..e7b0700 100644
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -152,7 +152,7 @@
}
static inline int
-pmbr_part_valid(struct partition *part, u64 lastlba)
+pmbr_part_valid(struct partition *part)
{
if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
le32_to_cpu(part->start_sect) == 1UL)
@@ -163,7 +163,6 @@
/**
* is_pmbr_valid(): test Protective MBR for validity
* @mbr: pointer to a legacy mbr structure
- * @lastlba: last_lba for the whole device
*
* Description: Returns 1 if PMBR is valid, 0 otherwise.
* Validity depends on two things:
@@ -171,13 +170,13 @@
* 2) One partition of type 0xEE is found
*/
static int
-is_pmbr_valid(legacy_mbr *mbr, u64 lastlba)
+is_pmbr_valid(legacy_mbr *mbr)
{
int i;
if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
return 0;
for (i = 0; i < 4; i++)
- if (pmbr_part_valid(&mbr->partition_record[i], lastlba))
+ if (pmbr_part_valid(&mbr->partition_record[i]))
return 1;
return 0;
}
@@ -516,7 +515,7 @@
int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
gpt_header *pgpt = NULL, *agpt = NULL;
gpt_entry *pptes = NULL, *aptes = NULL;
- legacy_mbr *legacymbr = NULL;
+ legacy_mbr *legacymbr;
u64 lastlba;
if (!bdev || !gpt || !ptes)
return 0;
@@ -528,9 +527,8 @@
if (legacymbr) {
read_lba(bdev, 0, (u8 *) legacymbr,
sizeof (*legacymbr));
- good_pmbr = is_pmbr_valid(legacymbr, lastlba);
+ good_pmbr = is_pmbr_valid(legacymbr);
kfree(legacymbr);
- legacymbr=NULL;
}
if (!good_pmbr)
goto fail;
diff --git a/fs/signalfd.c b/fs/signalfd.c
new file mode 100644
index 0000000..7cfeab4
--- /dev/null
+++ b/fs/signalfd.c
@@ -0,0 +1,349 @@
+/*
+ * fs/signalfd.c
+ *
+ * Copyright (C) 2003 Linus Torvalds
+ *
+ * Mon Mar 5, 2007: Davide Libenzi <davidel@xmailserver.org>
+ * Changed ->read() to return a siginfo strcture instead of signal number.
+ * Fixed locking in ->poll().
+ * Added sighand-detach notification.
+ * Added fd re-use in sys_signalfd() syscall.
+ * Now using anonymous inode source.
+ * Thanks to Oleg Nesterov for useful code review and suggestions.
+ * More comments and suggestions from Arnd Bergmann.
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/list.h>
+#include <linux/anon_inodes.h>
+#include <linux/signalfd.h>
+
+struct signalfd_ctx {
+ struct list_head lnk;
+ wait_queue_head_t wqh;
+ sigset_t sigmask;
+ struct task_struct *tsk;
+};
+
+struct signalfd_lockctx {
+ struct task_struct *tsk;
+ unsigned long flags;
+};
+
+/*
+ * Tries to acquire the sighand lock. We do not increment the sighand
+ * use count, and we do not even pin the task struct, so we need to
+ * do it inside an RCU read lock, and we must be prepared for the
+ * ctx->tsk going to NULL (in signalfd_deliver()), and for the sighand
+ * being detached. We return 0 if the sighand has been detached, or
+ * 1 if we were able to pin the sighand lock.
+ */
+static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk)
+{
+ struct sighand_struct *sighand = NULL;
+
+ rcu_read_lock();
+ lk->tsk = rcu_dereference(ctx->tsk);
+ if (likely(lk->tsk != NULL))
+ sighand = lock_task_sighand(lk->tsk, &lk->flags);
+ rcu_read_unlock();
+
+ if (sighand && !ctx->tsk) {
+ unlock_task_sighand(lk->tsk, &lk->flags);
+ sighand = NULL;
+ }
+
+ return sighand != NULL;
+}
+
+static void signalfd_unlock(struct signalfd_lockctx *lk)
+{
+ unlock_task_sighand(lk->tsk, &lk->flags);
+}
+
+/*
+ * This must be called with the sighand lock held.
+ */
+void signalfd_deliver(struct task_struct *tsk, int sig)
+{
+ struct sighand_struct *sighand = tsk->sighand;
+ struct signalfd_ctx *ctx, *tmp;
+
+ BUG_ON(!sig);
+ list_for_each_entry_safe(ctx, tmp, &sighand->signalfd_list, lnk) {
+ /*
+ * We use a negative signal value as a way to broadcast that the
+ * sighand has been orphaned, so that we can notify all the
+ * listeners about this. Remember the ctx->sigmask is inverted,
+ * so if the user is interested in a signal, that corresponding
+ * bit will be zero.
+ */
+ if (sig < 0) {
+ if (ctx->tsk == tsk) {
+ ctx->tsk = NULL;
+ list_del_init(&ctx->lnk);
+ wake_up(&ctx->wqh);
+ }
+ } else {
+ if (!sigismember(&ctx->sigmask, sig))
+ wake_up(&ctx->wqh);
+ }
+ }
+}
+
+static void signalfd_cleanup(struct signalfd_ctx *ctx)
+{
+ struct signalfd_lockctx lk;
+
+ /*
+ * This is tricky. If the sighand is gone, we do not need to remove
+ * context from the list, the list itself won't be there anymore.
+ */
+ if (signalfd_lock(ctx, &lk)) {
+ list_del(&ctx->lnk);
+ signalfd_unlock(&lk);
+ }
+ kfree(ctx);
+}
+
+static int signalfd_release(struct inode *inode, struct file *file)
+{
+ signalfd_cleanup(file->private_data);
+ return 0;
+}
+
+static unsigned int signalfd_poll(struct file *file, poll_table *wait)
+{
+ struct signalfd_ctx *ctx = file->private_data;
+ unsigned int events = 0;
+ struct signalfd_lockctx lk;
+
+ poll_wait(file, &ctx->wqh, wait);
+
+ /*
+ * Let the caller get a POLLIN in this case, ala socket recv() when
+ * the peer disconnects.
+ */
+ if (signalfd_lock(ctx, &lk)) {
+ if (next_signal(&lk.tsk->pending, &ctx->sigmask) > 0 ||
+ next_signal(&lk.tsk->signal->shared_pending,
+ &ctx->sigmask) > 0)
+ events |= POLLIN;
+ signalfd_unlock(&lk);
+ } else
+ events |= POLLIN;
+
+ return events;
+}
+
+/*
+ * Copied from copy_siginfo_to_user() in kernel/signal.c
+ */
+static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
+ siginfo_t const *kinfo)
+{
+ long err;
+
+ BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
+
+ /*
+ * Unused memebers should be zero ...
+ */
+ err = __clear_user(uinfo, sizeof(*uinfo));
+
+ /*
+ * If you change siginfo_t structure, please be sure
+ * this code is fixed accordingly.
+ */
+ err |= __put_user(kinfo->si_signo, &uinfo->signo);
+ err |= __put_user(kinfo->si_errno, &uinfo->err);
+ err |= __put_user((short)kinfo->si_code, &uinfo->code);
+ switch (kinfo->si_code & __SI_MASK) {
+ case __SI_KILL:
+ err |= __put_user(kinfo->si_pid, &uinfo->pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->uid);
+ break;
+ case __SI_TIMER:
+ err |= __put_user(kinfo->si_tid, &uinfo->tid);
+ err |= __put_user(kinfo->si_overrun, &uinfo->overrun);
+ err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr);
+ break;
+ case __SI_POLL:
+ err |= __put_user(kinfo->si_band, &uinfo->band);
+ err |= __put_user(kinfo->si_fd, &uinfo->fd);
+ break;
+ case __SI_FAULT:
+ err |= __put_user((long)kinfo->si_addr, &uinfo->addr);
+#ifdef __ARCH_SI_TRAPNO
+ err |= __put_user(kinfo->si_trapno, &uinfo->trapno);
+#endif
+ break;
+ case __SI_CHLD:
+ err |= __put_user(kinfo->si_pid, &uinfo->pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->uid);
+ err |= __put_user(kinfo->si_status, &uinfo->status);
+ err |= __put_user(kinfo->si_utime, &uinfo->utime);
+ err |= __put_user(kinfo->si_stime, &uinfo->stime);
+ break;
+ case __SI_RT: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ: /* But this is */
+ err |= __put_user(kinfo->si_pid, &uinfo->pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->uid);
+ err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr);
+ break;
+ default: /* this is just in case for now ... */
+ err |= __put_user(kinfo->si_pid, &uinfo->pid);
+ err |= __put_user(kinfo->si_uid, &uinfo->uid);
+ break;
+ }
+
+ return err ? -EFAULT: sizeof(*uinfo);
+}
+
+/*
+ * Returns either the size of a "struct signalfd_siginfo", or zero if the
+ * sighand we are attached to, has been orphaned. The "count" parameter
+ * must be at least the size of a "struct signalfd_siginfo".
+ */
+static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct signalfd_ctx *ctx = file->private_data;
+ ssize_t res = 0;
+ int locked, signo;
+ siginfo_t info;
+ struct signalfd_lockctx lk;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (count < sizeof(struct signalfd_siginfo))
+ return -EINVAL;
+ locked = signalfd_lock(ctx, &lk);
+ if (!locked)
+ return 0;
+ res = -EAGAIN;
+ signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
+ if (signo == 0 && !(file->f_flags & O_NONBLOCK)) {
+ add_wait_queue(&ctx->wqh, &wait);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
+ if (signo != 0)
+ break;
+ if (signal_pending(current)) {
+ res = -ERESTARTSYS;
+ break;
+ }
+ signalfd_unlock(&lk);
+ schedule();
+ locked = signalfd_lock(ctx, &lk);
+ if (unlikely(!locked)) {
+ /*
+ * Let the caller read zero byte, ala socket
+ * recv() when the peer disconnect. This test
+ * must be done before doing a dequeue_signal(),
+ * because if the sighand has been orphaned,
+ * the dequeue_signal() call is going to crash.
+ */
+ res = 0;
+ break;
+ }
+ }
+ remove_wait_queue(&ctx->wqh, &wait);
+ __set_current_state(TASK_RUNNING);
+ }
+ if (likely(locked))
+ signalfd_unlock(&lk);
+ if (likely(signo))
+ res = signalfd_copyinfo((struct signalfd_siginfo __user *) buf,
+ &info);
+
+ return res;
+}
+
+static const struct file_operations signalfd_fops = {
+ .release = signalfd_release,
+ .poll = signalfd_poll,
+ .read = signalfd_read,
+};
+
+/*
+ * Create a file descriptor that is associated with our signal
+ * state. We can pass it around to others if we want to, but
+ * it will always be _our_ signal state.
+ */
+asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask)
+{
+ int error;
+ sigset_t sigmask;
+ struct signalfd_ctx *ctx;
+ struct sighand_struct *sighand;
+ struct file *file;
+ struct inode *inode;
+ struct signalfd_lockctx lk;
+
+ if (sizemask != sizeof(sigset_t) ||
+ copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
+ return error = -EINVAL;
+ sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ signotset(&sigmask);
+
+ if (ufd == -1) {
+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ init_waitqueue_head(&ctx->wqh);
+ ctx->sigmask = sigmask;
+ ctx->tsk = current;
+
+ sighand = current->sighand;
+ /*
+ * Add this fd to the list of signal listeners.
+ */
+ spin_lock_irq(&sighand->siglock);
+ list_add_tail(&ctx->lnk, &sighand->signalfd_list);
+ spin_unlock_irq(&sighand->siglock);
+
+ /*
+ * When we call this, the initialization must be complete, since
+ * anon_inode_getfd() will install the fd.
+ */
+ error = anon_inode_getfd(&ufd, &inode, &file, "[signalfd]",
+ &signalfd_fops, ctx);
+ if (error)
+ goto err_fdalloc;
+ } else {
+ file = fget(ufd);
+ if (!file)
+ return -EBADF;
+ ctx = file->private_data;
+ if (file->f_op != &signalfd_fops) {
+ fput(file);
+ return -EINVAL;
+ }
+ /*
+ * We need to be prepared of the fact that the sighand this fd
+ * is attached to, has been detched. In that case signalfd_lock()
+ * will return 0, and we'll just skip setting the new mask.
+ */
+ if (signalfd_lock(ctx, &lk)) {
+ ctx->sigmask = sigmask;
+ signalfd_unlock(&lk);
+ }
+ wake_up(&ctx->wqh);
+ fput(file);
+ }
+
+ return ufd;
+
+err_fdalloc:
+ signalfd_cleanup(ctx);
+ return error;
+}
+
diff --git a/fs/timerfd.c b/fs/timerfd.c
new file mode 100644
index 0000000..e329e37
--- /dev/null
+++ b/fs/timerfd.c
@@ -0,0 +1,227 @@
+/*
+ * fs/timerfd.c
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ *
+ * Thanks to Thomas Gleixner for code reviews and useful comments.
+ *
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/anon_inodes.h>
+#include <linux/timerfd.h>
+
+struct timerfd_ctx {
+ struct hrtimer tmr;
+ ktime_t tintv;
+ spinlock_t lock;
+ wait_queue_head_t wqh;
+ int expired;
+};
+
+/*
+ * This gets called when the timer event triggers. We set the "expired"
+ * flag, but we do not re-arm the timer (in case it's necessary,
+ * tintv.tv64 != 0) until the timer is read.
+ */
+static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
+{
+ struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ctx->lock, flags);
+ ctx->expired = 1;
+ wake_up_locked(&ctx->wqh);
+ spin_unlock_irqrestore(&ctx->lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+static void timerfd_setup(struct timerfd_ctx *ctx, int clockid, int flags,
+ const struct itimerspec *ktmr)
+{
+ enum hrtimer_mode htmode;
+ ktime_t texp;
+
+ htmode = (flags & TFD_TIMER_ABSTIME) ?
+ HRTIMER_MODE_ABS: HRTIMER_MODE_REL;
+
+ texp = timespec_to_ktime(ktmr->it_value);
+ ctx->expired = 0;
+ ctx->tintv = timespec_to_ktime(ktmr->it_interval);
+ hrtimer_init(&ctx->tmr, clockid, htmode);
+ ctx->tmr.expires = texp;
+ ctx->tmr.function = timerfd_tmrproc;
+ if (texp.tv64 != 0)
+ hrtimer_start(&ctx->tmr, texp, htmode);
+}
+
+static int timerfd_release(struct inode *inode, struct file *file)
+{
+ struct timerfd_ctx *ctx = file->private_data;
+
+ hrtimer_cancel(&ctx->tmr);
+ kfree(ctx);
+ return 0;
+}
+
+static unsigned int timerfd_poll(struct file *file, poll_table *wait)
+{
+ struct timerfd_ctx *ctx = file->private_data;
+ unsigned int events = 0;
+ unsigned long flags;
+
+ poll_wait(file, &ctx->wqh, wait);
+
+ spin_lock_irqsave(&ctx->lock, flags);
+ if (ctx->expired)
+ events |= POLLIN;
+ spin_unlock_irqrestore(&ctx->lock, flags);
+
+ return events;
+}
+
+static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct timerfd_ctx *ctx = file->private_data;
+ ssize_t res;
+ u32 ticks = 0;
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (count < sizeof(ticks))
+ return -EINVAL;
+ spin_lock_irq(&ctx->lock);
+ res = -EAGAIN;
+ if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) {
+ __add_wait_queue(&ctx->wqh, &wait);
+ for (res = 0;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (ctx->expired) {
+ res = 0;
+ break;
+ }
+ if (signal_pending(current)) {
+ res = -ERESTARTSYS;
+ break;
+ }
+ spin_unlock_irq(&ctx->lock);
+ schedule();
+ spin_lock_irq(&ctx->lock);
+ }
+ __remove_wait_queue(&ctx->wqh, &wait);
+ __set_current_state(TASK_RUNNING);
+ }
+ if (ctx->expired) {
+ ctx->expired = 0;
+ if (ctx->tintv.tv64 != 0) {
+ /*
+ * If tintv.tv64 != 0, this is a periodic timer that
+ * needs to be re-armed. We avoid doing it in the timer
+ * callback to avoid DoS attacks specifying a very
+ * short timer period.
+ */
+ ticks = (u32)
+ hrtimer_forward(&ctx->tmr,
+ hrtimer_cb_get_time(&ctx->tmr),
+ ctx->tintv);
+ hrtimer_restart(&ctx->tmr);
+ } else
+ ticks = 1;
+ }
+ spin_unlock_irq(&ctx->lock);
+ if (ticks)
+ res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks);
+ return res;
+}
+
+static const struct file_operations timerfd_fops = {
+ .release = timerfd_release,
+ .poll = timerfd_poll,
+ .read = timerfd_read,
+};
+
+asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
+ const struct itimerspec __user *utmr)
+{
+ int error;
+ struct timerfd_ctx *ctx;
+ struct file *file;
+ struct inode *inode;
+ struct itimerspec ktmr;
+
+ if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
+ return -EFAULT;
+
+ if (clockid != CLOCK_MONOTONIC &&
+ clockid != CLOCK_REALTIME)
+ return -EINVAL;
+ if (!timespec_valid(&ktmr.it_value) ||
+ !timespec_valid(&ktmr.it_interval))
+ return -EINVAL;
+
+ if (ufd == -1) {
+ ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ init_waitqueue_head(&ctx->wqh);
+ spin_lock_init(&ctx->lock);
+
+ timerfd_setup(ctx, clockid, flags, &ktmr);
+
+ /*
+ * When we call this, the initialization must be complete, since
+ * anon_inode_getfd() will install the fd.
+ */
+ error = anon_inode_getfd(&ufd, &inode, &file, "[timerfd]",
+ &timerfd_fops, ctx);
+ if (error)
+ goto err_tmrcancel;
+ } else {
+ file = fget(ufd);
+ if (!file)
+ return -EBADF;
+ ctx = file->private_data;
+ if (file->f_op != &timerfd_fops) {
+ fput(file);
+ return -EINVAL;
+ }
+ /*
+ * We need to stop the existing timer before reprogramming
+ * it to the new values.
+ */
+ for (;;) {
+ spin_lock_irq(&ctx->lock);
+ if (hrtimer_try_to_cancel(&ctx->tmr) >= 0)
+ break;
+ spin_unlock_irq(&ctx->lock);
+ cpu_relax();
+ }
+ /*
+ * Re-program the timer to the new value ...
+ */
+ timerfd_setup(ctx, clockid, flags, &ktmr);
+
+ spin_unlock_irq(&ctx->lock);
+ fput(file);
+ }
+
+ return ufd;
+
+err_tmrcancel:
+ hrtimer_cancel(&ctx->tmr);
+ kfree(ctx);
+ return error;
+}
+
diff --git a/fs/xattr.c b/fs/xattr.c
index 9f4568b..4523aca 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -350,6 +350,7 @@
f = fget(fd);
if (!f)
return error;
+ audit_inode(NULL, f->f_path.dentry->d_inode);
error = getxattr(f->f_path.dentry, name, value, size);
fput(f);
return error;
@@ -422,6 +423,7 @@
f = fget(fd);
if (!f)
return error;
+ audit_inode(NULL, f->f_path.dentry->d_inode);
error = listxattr(f->f_path.dentry, list, size);
fput(f);
return error;
diff --git a/include/asm-alpha/poll.h b/include/asm-alpha/poll.h
index 76f8935..c98509d 100644
--- a/include/asm-alpha/poll.h
+++ b/include/asm-alpha/poll.h
@@ -1,25 +1 @@
-#ifndef __ALPHA_POLL_H
-#define __ALPHA_POLL_H
-
-#define POLLIN (1 << 0)
-#define POLLPRI (1 << 1)
-#define POLLOUT (1 << 2)
-#define POLLERR (1 << 3)
-#define POLLHUP (1 << 4)
-#define POLLNVAL (1 << 5)
-#define POLLRDNORM (1 << 6)
-#define POLLRDBAND (1 << 7)
-#define POLLWRNORM (1 << 8)
-#define POLLWRBAND (1 << 9)
-#define POLLMSG (1 << 10)
-#define POLLREMOVE (1 << 12)
-#define POLLRDHUP (1 << 13)
-
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-arm/poll.h b/include/asm-arm/poll.h
index 5030b2b..c98509d 100644
--- a/include/asm-arm/poll.h
+++ b/include/asm-arm/poll.h
@@ -1,27 +1 @@
-#ifndef __ASMARM_POLL_H
-#define __ASMARM_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-arm26/poll.h b/include/asm-arm26/poll.h
index 9ccb7f4..1170e70 100644
--- a/include/asm-arm26/poll.h
+++ b/include/asm-arm26/poll.h
@@ -1,26 +1,8 @@
#ifndef __ASMARM_POLL_H
#define __ASMARM_POLL_H
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
+#include <asm-generic/poll.h>
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#undef POLLREMOVE
#endif
diff --git a/include/asm-avr32/poll.h b/include/asm-avr32/poll.h
index 736e297..c98509d 100644
--- a/include/asm-avr32/poll.h
+++ b/include/asm-avr32/poll.h
@@ -1,27 +1 @@
-#ifndef __ASM_AVR32_POLL_H
-#define __ASM_AVR32_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif /* __ASM_AVR32_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-cris/poll.h b/include/asm-cris/poll.h
index 1b25d4c..c98509d 100644
--- a/include/asm-cris/poll.h
+++ b/include/asm-cris/poll.h
@@ -1,26 +1 @@
-#ifndef __ASM_CRIS_POLL_H
-#define __ASM_CRIS_POLL_H
-
-/* taken from asm-alpha */
-
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#define POLLERR 8
-#define POLLHUP 16
-#define POLLNVAL 32
-#define POLLRDNORM 64
-#define POLLRDBAND 128
-#define POLLWRNORM 256
-#define POLLWRBAND 512
-#define POLLMSG 1024
-#define POLLREMOVE 4096
-#define POLLRDHUP 8192
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-frv/poll.h b/include/asm-frv/poll.h
index c8fe880..0d01479 100644
--- a/include/asm-frv/poll.h
+++ b/include/asm-frv/poll.h
@@ -1,24 +1,12 @@
#ifndef _ASM_POLL_H
#define _ASM_POLL_H
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#define POLLERR 8
-#define POLLHUP 16
-#define POLLNVAL 32
-#define POLLRDNORM 64
#define POLLWRNORM POLLOUT
-#define POLLRDBAND 128
#define POLLWRBAND 256
-#define POLLMSG 0x0400
-#define POLLRDHUP 0x2000
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
+
+#undef POLLREMOVE
#endif
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index fa14f8c..5bfeef7 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -4,6 +4,7 @@
header-y += ioctl.h
header-y += ipc.h
header-y += mman.h
+header-y += poll.h
header-y += signal.h
header-y += statfs.h
diff --git a/include/asm-generic/audit_signal.h b/include/asm-generic/audit_signal.h
new file mode 100644
index 0000000..6feab7f
--- /dev/null
+++ b/include/asm-generic/audit_signal.h
@@ -0,0 +1,3 @@
+__NR_kill,
+__NR_tgkill,
+__NR_tkill,
diff --git a/include/asm-generic/poll.h b/include/asm-generic/poll.h
new file mode 100644
index 0000000..44bce83
--- /dev/null
+++ b/include/asm-generic/poll.h
@@ -0,0 +1,37 @@
+#ifndef __ASM_GENERIC_POLL_H
+#define __ASM_GENERIC_POLL_H
+
+/* These are specified by iBCS2 */
+#define POLLIN 0x0001
+#define POLLPRI 0x0002
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+/* The rest seem to be more-or-less nonstandard. Check them! */
+#define POLLRDNORM 0x0040
+#define POLLRDBAND 0x0080
+#ifndef POLLWRNORM
+#define POLLWRNORM 0x0100
+#endif
+#ifndef POLLWRBAND
+#define POLLWRBAND 0x0200
+#endif
+#ifndef POLLMSG
+#define POLLMSG 0x0400
+#endif
+#ifndef POLLREMOVE
+#define POLLREMOVE 0x1000
+#endif
+#ifndef POLLRDHUP
+#define POLLRDHUP 0x2000
+#endif
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+#endif /* __ASM_GENERIC_POLL_H */
diff --git a/include/asm-h8300/poll.h b/include/asm-h8300/poll.h
index fc52103..f61540c 100644
--- a/include/asm-h8300/poll.h
+++ b/include/asm-h8300/poll.h
@@ -1,23 +1,11 @@
#ifndef __H8300_POLL_H
#define __H8300_POLL_H
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#define POLLERR 8
-#define POLLHUP 16
-#define POLLNVAL 32
-#define POLLRDNORM 64
#define POLLWRNORM POLLOUT
-#define POLLRDBAND 128
#define POLLWRBAND 256
-#define POLLMSG 0x0400
-#define POLLRDHUP 0x2000
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
+
+#undef POLLREMOVE
#endif
diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h
index 7ddd414..99f3c35 100644
--- a/include/asm-h8300/unistd.h
+++ b/include/asm-h8300/unistd.h
@@ -21,7 +21,7 @@
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
-#define __NR_chown 16
+#define __NR_lchown 16
#define __NR_break 17
#define __NR_oldstat 18
#define __NR_lseek 19
@@ -115,10 +115,10 @@
#define __NR_lstat 107
#define __NR_fstat 108
#define __NR_olduname 109
-#define __NR_iopl /* 110 */ not supported
+#define __NR_iopl 110
#define __NR_vhangup 111
-#define __NR_idle /* 112 */ Obsolete
-#define __NR_vm86 /* 113 */ not supported
+#define __NR_idle 112
+#define __NR_vm86old 113
#define __NR_wait4 114
#define __NR_swapoff 115
#define __NR_sysinfo 116
@@ -128,7 +128,7 @@
#define __NR_clone 120
#define __NR_setdomainname 121
#define __NR_uname 122
-#define __NR_cacheflush 123
+#define __NR_modify_ldt 123
#define __NR_adjtimex 124
#define __NR_mprotect 125
#define __NR_sigprocmask 126
@@ -171,7 +171,7 @@
#define __NR_mremap 163
#define __NR_setresuid 164
#define __NR_getresuid 165
-#define __NR_getpagesize 166
+#define __NR_vm86 166
#define __NR_query_module 167
#define __NR_poll 168
#define __NR_nfsservctl 169
@@ -187,7 +187,7 @@
#define __NR_rt_sigsuspend 179
#define __NR_pread64 180
#define __NR_pwrite64 181
-#define __NR_lchown 182
+#define __NR_chown 182
#define __NR_getcwd 183
#define __NR_capget 184
#define __NR_capset 185
@@ -203,7 +203,7 @@
#define __NR_stat64 195
#define __NR_lstat64 196
#define __NR_fstat64 197
-#define __NR_chown32 198
+#define __NR_lchown32 198
#define __NR_getuid32 199
#define __NR_getgid32 200
#define __NR_geteuid32 201
@@ -217,15 +217,18 @@
#define __NR_getresuid32 209
#define __NR_setresgid32 210
#define __NR_getresgid32 211
-#define __NR_lchown32 212
+#define __NR_chown32 212
#define __NR_setuid32 213
#define __NR_setgid32 214
#define __NR_setfsuid32 215
#define __NR_setfsgid32 216
#define __NR_pivot_root 217
+#define __NR_mincore 218
+#define __NR_madvise 219
+#define __NR_madvise1 219
#define __NR_getdents64 220
#define __NR_fcntl64 221
-#define __NR_security 223
+/* 223 is unused */
#define __NR_gettid 224
#define __NR_readahead 225
#define __NR_setxattr 226
@@ -252,13 +255,13 @@
#define __NR_io_getevents 247
#define __NR_io_submit 248
#define __NR_io_cancel 249
-#define __NR_alloc_hugepages 250
-#define __NR_free_hugepages 251
+#define __NR_fadvise64 250
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
#define __NR_exit_group 252
#define __NR_lookup_dcookie 253
-#define __NR_sys_epoll_create 254
-#define __NR_sys_epoll_ctl 255
-#define __NR_sys_epoll_wait 256
+#define __NR_epoll_create 254
+#define __NR_epoll_ctl 255
+#define __NR_epoll_wait 256
#define __NR_remap_file_pages 257
#define __NR_set_tid_address 258
#define __NR_timer_create 259
@@ -291,10 +294,41 @@
#define __NR_add_key 286
#define __NR_request_key 287
#define __NR_keyctl 288
+#define __NR_ioprio_set 289
+#define __NR_ioprio_get 290
+#define __NR_inotify_init 291
+#define __NR_inotify_add_watch 292
+#define __NR_inotify_rm_watch 293
+#define __NR_migrate_pages 294
+#define __NR_openat 295
+#define __NR_mkdirat 296
+#define __NR_mknodat 297
+#define __NR_fchownat 298
+#define __NR_futimesat 299
+#define __NR_fstatat64 300
+#define __NR_unlinkat 301
+#define __NR_renameat 302
+#define __NR_linkat 303
+#define __NR_symlinkat 304
+#define __NR_readlinkat 305
+#define __NR_fchmodat 306
+#define __NR_faccessat 307
+#define __NR_pselect6 308
+#define __NR_ppoll 309
+#define __NR_unshare 310
+#define __NR_set_robust_list 311
+#define __NR_get_robust_list 312
+#define __NR_splice 313
+#define __NR_sync_file_range 314
+#define __NR_tee 315
+#define __NR_vmsplice 316
+#define __NR_move_pages 317
+#define __NR_getcpu 318
+#define __NR_epoll_pwait 319
#ifdef __KERNEL__
-#define NR_syscalls 289
+#define NR_syscalls 320
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h
index 0f70b37..eb7da54 100644
--- a/include/asm-i386/alternative.h
+++ b/include/asm-i386/alternative.h
@@ -98,6 +98,12 @@
".previous" : output : [feat] "i" (feature), ##input)
/*
+ * use this macro(s) if you need more than one output parameter
+ * in alternative_io
+ */
+#define ASM_OUTPUT2(a, b) a, b
+
+/*
* Alternative inline assembly for SMP.
*
* The LOCK_PREFIX macro defined here replaces the LOCK and
diff --git a/include/asm-i386/poll.h b/include/asm-i386/poll.h
index 2cd4929..c98509d 100644
--- a/include/asm-i386/poll.h
+++ b/include/asm-i386/poll.h
@@ -1,27 +1 @@
-#ifndef __i386_POLL_H
-#define __i386_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h
index 3f3c1fa..62c091f 100644
--- a/include/asm-i386/tsc.h
+++ b/include/asm-i386/tsc.h
@@ -35,14 +35,16 @@
static __always_inline cycles_t get_cycles_sync(void)
{
unsigned long long ret;
- unsigned eax;
+ unsigned eax, edx;
/*
* Use RDTSCP if possible; it is guaranteed to be synchronous
* and doesn't cause a VMEXIT on Hypervisors
*/
alternative_io(ASM_NOP3, ".byte 0x0f,0x01,0xf9", X86_FEATURE_RDTSCP,
- "=A" (ret), "0" (0ULL) : "ecx", "memory");
+ ASM_OUTPUT2("=a" (eax), "=d" (edx)),
+ "a" (0U), "d" (0U) : "ecx", "memory");
+ ret = (((unsigned long long)edx) << 32) | ((unsigned long long)eax);
if (ret)
return ret;
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index bd21e79..e84ace1 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -326,10 +326,13 @@
#define __NR_getcpu 318
#define __NR_epoll_pwait 319
#define __NR_utimensat 320
+#define __NR_signalfd 321
+#define __NR_timerfd 322
+#define __NR_eventfd 323
#ifdef __KERNEL__
-#define NR_syscalls 321
+#define NR_syscalls 324
#define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-ia64/poll.h b/include/asm-ia64/poll.h
index bcaf9f1..c98509d 100644
--- a/include/asm-ia64/poll.h
+++ b/include/asm-ia64/poll.h
@@ -1,32 +1 @@
-#ifndef _ASM_IA64_POLL_H
-#define _ASM_IA64_POLL_H
-
-/*
- * poll(2) bit definitions. Based on <asm-i386/poll.h>.
- *
- * Modified 1998, 1999, 2002
- * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif /* _ASM_IA64_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
index 7509257..bca3475 100644
--- a/include/asm-m32r/pgtable-2level.h
+++ b/include/asm-m32r/pgtable-2level.h
@@ -71,8 +71,8 @@
#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
#define PTE_FILE_MAX_BITS 29
-#define pte_to_pgoff(pte) (((pte_val(pte) >> 2) & 0xef) | (((pte_val(pte) >> 10)) << 7))
-#define pgoff_to_pte(off) ((pte_t) { (((off) & 0xef) << 2) | (((off) >> 7) << 10) | _PAGE_FILE })
+#define pte_to_pgoff(pte) (((pte_val(pte) >> 2) & 0x7f) | (((pte_val(pte) >> 10)) << 7))
+#define pgoff_to_pte(off) ((pte_t) { (((off) & 0x7f) << 2) | (((off) >> 7) << 10) | _PAGE_FILE })
#endif /* __KERNEL__ */
#endif /* _ASM_M32R_PGTABLE_2LEVEL_H */
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 8b2a2f1..6604303 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -366,7 +366,7 @@
#define pte_unmap_nested(pte) do { } while (0)
/* Encode and de-code a swap entry */
-#define __swp_type(x) (((x).val >> 2) & 0x3f)
+#define __swp_type(x) (((x).val >> 2) & 0x1f)
#define __swp_offset(x) ((x).val >> 10)
#define __swp_entry(type, offset) \
((swp_entry_t) { ((type) << 2) | ((offset) << 10) })
diff --git a/include/asm-m32r/poll.h b/include/asm-m32r/poll.h
index 9e0e700..c98509d 100644
--- a/include/asm-m32r/poll.h
+++ b/include/asm-m32r/poll.h
@@ -1,32 +1 @@
-#ifndef _ASM_M32R_POLL_H
-#define _ASM_M32R_POLL_H
-
-/*
- * poll(2) bit definitions. Based on <asm-i386/poll.h>.
- *
- * Modified 2004
- * Hirokazu Takata <takata at linux-m32r.org>
- */
-
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif /* _ASM_M32R_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index f62f5c9..b291b2f 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -21,12 +21,22 @@
* `next' and `prev' should be struct task_struct, but it isn't always defined
*/
+#if defined(CONFIG_FRAME_POINTER) || \
+ !defined(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER)
+#define M32R_PUSH_FP " push fp\n"
+#define M32R_POP_FP " pop fp\n"
+#else
+#define M32R_PUSH_FP ""
+#define M32R_POP_FP ""
+#endif
+
#define switch_to(prev, next, last) do { \
__asm__ __volatile__ ( \
" seth lr, #high(1f) \n" \
" or3 lr, lr, #low(1f) \n" \
" st lr, @%4 ; store old LR \n" \
" ld lr, @%5 ; load new LR \n" \
+ M32R_PUSH_FP \
" st sp, @%2 ; store old SP \n" \
" ld sp, @%3 ; load new SP \n" \
" push %1 ; store `prev' on new stack \n" \
@@ -34,6 +44,7 @@
" .fillinsn \n" \
"1: \n" \
" pop %0 ; restore `__last' from new stack \n" \
+ M32R_POP_FP \
: "=r" (last) \
: "0" (prev), \
"r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
diff --git a/include/asm-m68k/poll.h b/include/asm-m68k/poll.h
index 0fb8843..f080fcd 100644
--- a/include/asm-m68k/poll.h
+++ b/include/asm-m68k/poll.h
@@ -1,24 +1,9 @@
#ifndef __m68k_POLL_H
#define __m68k_POLL_H
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#define POLLERR 8
-#define POLLHUP 16
-#define POLLNVAL 32
-#define POLLRDNORM 64
#define POLLWRNORM POLLOUT
-#define POLLRDBAND 128
#define POLLWRBAND 256
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
#endif
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index 62daa74..1b60624 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -689,7 +689,7 @@
}
#define atomic64_cmpxchg(v, o, n) \
- (((__typeof__((v)->counter)))cmpxchg(&((v)->counter), (o), (n)))
+ ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new)))
/**
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index dbf834f..b0c3297 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -119,9 +119,9 @@
*/
#define MACH_GROUP_MOMENCO 12 /* Momentum Boards */
#define MACH_MOMENCO_OCELOT 0
-#define MACH_MOMENCO_OCELOT_G 1
+#define MACH_MOMENCO_OCELOT_G 1 /* no more supported (may 2007) */
#define MACH_MOMENCO_OCELOT_C 2
-#define MACH_MOMENCO_JAGUAR_ATX 3
+#define MACH_MOMENCO_JAGUAR_ATX 3 /* no more supported (may 2007) */
#define MACH_MOMENCO_OCELOT_3 4
/*
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index b414a7d..483685b 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -16,6 +16,7 @@
#include <asm/mipsregs.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
+#include <asm/hazards.h>
#include <asm/bitops.h>
#include <asm/processor.h>
#include <asm/current.h>
@@ -38,34 +39,16 @@
extern void _save_fp(struct task_struct *);
extern void _restore_fp(struct task_struct *);
-#if defined(CONFIG_CPU_SB1)
-#define __enable_fpu_hazard() \
-do { \
- asm(".set push \n\t" \
- ".set mips64 \n\t" \
- ".set noreorder \n\t" \
- "ssnop \n\t" \
- "bnezl $0, .+4 \n\t" \
- "ssnop \n\t" \
- ".set pop"); \
-} while (0)
-#else
-#define __enable_fpu_hazard() \
-do { \
- asm("nop;nop;nop;nop"); /* max. hazard */ \
-} while (0)
-#endif
-
#define __enable_fpu() \
do { \
set_c0_status(ST0_CU1); \
- __enable_fpu_hazard(); \
+ enable_fpu_hazard(); \
} while (0)
#define __disable_fpu() \
do { \
clear_c0_status(ST0_CU1); \
- /* We don't care about the c0 hazard here */ \
+ disable_fpu_hazard(); \
} while (0)
#define enable_fpu() \
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index e50c77e..d9119f4 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -178,4 +178,36 @@
#endif
+
+/* FPU hazards */
+
+#if defined(CONFIG_CPU_SB1)
+ASMMACRO(enable_fpu_hazard,
+ .set push;
+ .set mips64;
+ .set noreorder;
+ _ssnop;
+ bnezl $0,.+4;
+ _ssnop;
+ .set pop
+)
+ASMMACRO(disable_fpu_hazard,
+)
+
+#elif defined(CONFIG_CPU_MIPSR2)
+ASMMACRO(enable_fpu_hazard,
+ _ehb
+)
+ASMMACRO(disable_fpu_hazard,
+ _ehb
+)
+#else
+ASMMACRO(enable_fpu_hazard,
+ nop; nop; nop; nop
+)
+ASMMACRO(disable_fpu_hazard,
+ _ehb
+)
+#endif
+
#endif /* _ASM_HAZARDS_H */
diff --git a/include/asm-mips/highmem.h b/include/asm-mips/highmem.h
index f8c8182..4d6bd5c 100644
--- a/include/asm-mips/highmem.h
+++ b/include/asm-mips/highmem.h
@@ -48,46 +48,6 @@
extern void * kmap_high(struct page *page);
extern void kunmap_high(struct page *page);
-/*
- * CONFIG_LIMITED_DMA is for systems with DMA limitations such as Momentum's
- * Jaguar ATX. This option exploits the highmem code in the kernel so is
- * always enabled together with CONFIG_HIGHMEM but at this time doesn't
- * actually add highmem functionality.
- */
-
-#ifdef CONFIG_LIMITED_DMA
-
-/*
- * These are the default functions for the no-highmem case from
- * <linux/highmem.h>
- */
-static inline void *kmap(struct page *page)
-{
- might_sleep();
- return page_address(page);
-}
-
-#define kunmap(page) do { (void) (page); } while (0)
-
-static inline void *kmap_atomic(struct page *page, enum km_type type)
-{
- pagefault_disable();
- return page_address(page);
-}
-
-static inline void kunmap_atomic(void *kvaddr, enum km_type type)
-{
- pagefault_enable();
-}
-
-#define kmap_atomic_pfn(pfn, idx) kmap_atomic(pfn_to_page(pfn), (idx))
-
-#define kmap_atomic_to_page(ptr) virt_to_page(ptr)
-
-#define flush_cache_kmaps() do { } while (0)
-
-#else /* LIMITED_DMA */
-
extern void *__kmap(struct page *page);
extern void __kunmap(struct page *page);
extern void *__kmap_atomic(struct page *page, enum km_type type);
@@ -103,8 +63,6 @@
#define flush_cache_kmaps() flush_cache_all()
-#endif /* LIMITED_DMA */
-
#endif /* __KERNEL__ */
#endif /* _ASM_HIGHMEM_H */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index 24a8d51..684a501 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -69,6 +69,8 @@
#define COBALT_BRD_ID_QUBE2 0x5
#define COBALT_BRD_ID_RAQ2 0x6
+extern int cobalt_board_id;
+
#define PCI_CFG_SET(devfn,where) \
GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) | \
(PCI_FUNC (devfn) << 8) | (where)))
diff --git a/include/asm-mips/mach-ja/cpu-feature-overrides.h b/include/asm-mips/mach-ja/cpu-feature-overrides.h
deleted file mode 100644
index 84b6dea..0000000
--- a/include/asm-mips/mach-ja/cpu-feature-overrides.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2004 Ralf Baechle
- */
-#ifndef __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Momentum Jaguar ATX always has the RM9000 processor.
- */
-#define cpu_has_watch 1
-#define cpu_has_mips16 0
-#define cpu_has_divec 0
-#define cpu_has_vce 0
-#define cpu_has_cache_cdex_p 0
-#define cpu_has_cache_cdex_s 0
-#define cpu_has_prefetch 1
-#define cpu_has_mcheck 0
-#define cpu_has_ejtag 0
-
-#define cpu_has_llsc 1
-#define cpu_has_vtag_icache 0
-#define cpu_has_dc_aliases 0
-#define cpu_has_ic_fills_f_dc 0
-#define cpu_has_dsp 0
-#define cpu_icache_snoops_remote_store 0
-
-#define cpu_has_nofpuex 0
-#define cpu_has_64bits 1
-
-#define cpu_has_inclusive_pcaches 0
-
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#define cpu_scache_line_size() 32
-
-#define cpu_has_mips32r1 0
-#define cpu_has_mips32r2 0
-#define cpu_has_mips64r1 0
-#define cpu_has_mips64r2 0
-
-#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ja/spaces.h b/include/asm-mips/mach-ja/spaces.h
deleted file mode 100644
index 8466a0e..0000000
--- a/include/asm-mips/mach-ja/spaces.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
- * Copyright (C) 2000, 2002 Maciej W. Rozycki
- * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef __ASM_MACH_JA_SPACES_H
-#define __ASM_MACH_JA_SPACES_H
-
-/*
- * Memory above this physical address will be considered highmem.
- */
-#define HIGHMEM_START 0x08000000UL
-
-#include_next <spaces.h>
-
-#endif /* __ASM_MACH_JA_SPACES_H */
diff --git a/include/asm-mips/mips-boards/malta.h b/include/asm-mips/mips-boards/malta.h
index b0ba3c5..eec9100 100644
--- a/include/asm-mips/mips-boards/malta.h
+++ b/include/asm-mips/mips-boards/malta.h
@@ -25,6 +25,10 @@
#include <asm/mips-boards/msc01_pci.h>
#include <asm/gt64120.h>
+/* Mips interrupt controller found in SOCit variations */
+#define MIPS_MSC01_IC_REG_BASE 0x1bc40000
+#define MIPS_SOCITSC_IC_REG_BASE 0x1ffa0000
+
/*
* Malta I/O ports base address for the Galileo GT64120 and Algorithmics
* Bonito system controllers.
diff --git a/include/asm-mips/msc01_ic.h b/include/asm-mips/msc01_ic.h
index aa7ad9a..7989b9f 100644
--- a/include/asm-mips/msc01_ic.h
+++ b/include/asm-mips/msc01_ic.h
@@ -94,10 +94,7 @@
/*
* MIPS System controller interrupt register base.
*
- * FIXME - are these macros specific to Malta and co or to the MSC? If the
- * latter, they should be moved elsewhere.
*/
-#define MIPS_MSC01_IC_REG_BASE 0x1bc40000
/*****************************************************************************
* Absolute register addresses
@@ -144,7 +141,7 @@
#define MSC01_IRQ_LEVEL 0
#define MSC01_IRQ_EDGE 1
-extern void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq);
+extern void __init init_msc_irqs(unsigned long icubase, unsigned int base, msc_irqmap_t *imp, int nirq);
extern void ll_msc_irq(void);
#endif /* __ASM_MIPS_BOARDS_MSC01_IC_H */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index d3fbd83..5c3239d 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -190,10 +190,6 @@
#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
-#ifdef CONFIG_LIMITED_DMA
-#define WANT_PAGE_VIRTUAL
-#endif
-
#include <asm-generic/memory_model.h>
#include <asm-generic/page.h>
diff --git a/include/asm-mips/poll.h b/include/asm-mips/poll.h
index 70881f8..47b9520 100644
--- a/include/asm-mips/poll.h
+++ b/include/asm-mips/poll.h
@@ -1,28 +1,9 @@
#ifndef __ASM_POLL_H
#define __ASM_POLL_H
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
#define POLLWRNORM POLLOUT
#define POLLWRBAND 0x0100
-/* These seem to be more or less nonstandard ... */
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
#endif /* __ASM_POLL_H */
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index d7a6513..ce51213 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -81,25 +81,6 @@
#define STD_SERIAL_PORT_DEFNS
#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-#ifdef CONFIG_MOMENCO_JAGUAR_ATX
-/* Ordinary NS16552 duart with a 20MHz crystal. */
-#define JAGUAR_ATX_UART_CLK 20000000
-#define JAGUAR_ATX_BASE_BAUD (JAGUAR_ATX_UART_CLK / 16)
-
-#define JAGUAR_ATX_SERIAL1_IRQ 6
-#define JAGUAR_ATX_SERIAL1_BASE 0xfd000023L
-
-#define _JAGUAR_ATX_SERIAL_INIT(int, base) \
- { .baud_base = JAGUAR_ATX_BASE_BAUD, irq: int, \
- .flags = (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
- .iomem_base = (u8 *) base, iomem_reg_shift: 2, \
- io_type: SERIAL_IO_MEM }
-#define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS \
- _JAGUAR_ATX_SERIAL_INIT(JAGUAR_ATX_SERIAL1_IRQ, JAGUAR_ATX_SERIAL1_BASE)
-#else
-#define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS
-#endif
-
#ifdef CONFIG_MOMENCO_OCELOT_3
#define OCELOT_3_BASE_BAUD ( 20000000 / 16 )
#define OCELOT_3_SERIAL_IRQ 6
@@ -134,27 +115,6 @@
#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS
#endif
-#ifdef CONFIG_MOMENCO_OCELOT_G
-/* Ordinary NS16552 duart with a 20MHz crystal. */
-#define OCELOT_G_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_G_SERIAL1_IRQ 4
-#if 0
-#define OCELOT_G_SERIAL1_BASE 0xe0001020
-#else
-#define OCELOT_G_SERIAL1_BASE 0xfd000020
-#endif
-
-#define _OCELOT_G_SERIAL_INIT(int, base) \
- { .baud_base = OCELOT_G_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,\
- .iomem_base = (u8 *) base, .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM }
-#define MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \
- _OCELOT_G_SERIAL_INIT(OCELOT_G_SERIAL1_IRQ, OCELOT_G_SERIAL1_BASE)
-#else
-#define MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS
-#endif
-
#ifdef CONFIG_MOMENCO_OCELOT_C
/* Ordinary NS16552 duart with a 20MHz crystal. */
#define OCELOT_C_BASE_BAUD ( 20000000 / 16 )
@@ -210,7 +170,6 @@
IP32_SERIAL_PORT_DEFNS \
JAZZ_SERIAL_PORT_DEFNS \
STD_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
diff --git a/include/asm-mips/sgi/seeq.h b/include/asm-mips/sgi/seeq.h
new file mode 100644
index 0000000..af0ffd7
--- /dev/null
+++ b/include/asm-mips/sgi/seeq.h
@@ -0,0 +1,21 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 by Ralf Baechle
+ */
+#ifndef __ASM_SGI_SEEQ_H
+#define __ASM_SGI_SEEQ_H
+
+#include <linux/if_ether.h>
+
+#include <asm/sgi/hpc3.h>
+
+struct sgiseeq_platform_data {
+ struct hpc3_regs *hpc;
+ unsigned int irq;
+ unsigned char mac[ETH_ALEN];
+};
+
+#endif /* __ASM_SGI_SEEQ_H */
diff --git a/include/asm-mips/sgi/wd.h b/include/asm-mips/sgi/wd.h
new file mode 100644
index 0000000..0d6c3a4
--- /dev/null
+++ b/include/asm-mips/sgi/wd.h
@@ -0,0 +1,20 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 by Ralf Baechle
+ */
+#ifndef __ASM_SGI_WD_H
+#define __ASM_SGI_WD_H
+
+#include <asm/sgi/hpc3.h>
+
+struct sgiwd93_platform_data {
+ unsigned int unit;
+ unsigned int irq;
+ struct hpc3_scsiregs *hregs;
+ unsigned char *wdregs;
+};
+
+#endif /* __ASM_SGI_WD_H */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 3713d25..bb0b289 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -464,7 +464,10 @@
extern void set_handler (unsigned long offset, void *addr, unsigned long len);
extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
-extern void *set_vi_handler (int n, void *addr);
+
+typedef void (*vi_handler_t)(void);
+extern void *set_vi_handler (int n, vi_handler_t addr);
+
extern void *set_except_vector(int n, void *addr);
extern unsigned long ebase;
extern void per_cpu_trap_init(void);
diff --git a/include/asm-parisc/poll.h b/include/asm-parisc/poll.h
index 20e4d03..c98509d 100644
--- a/include/asm-parisc/poll.h
+++ b/include/asm-parisc/poll.h
@@ -1,27 +1 @@
-#ifndef __PARISC_POLL_H
-#define __PARISC_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index 9e4dd98..a7b60bf 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -48,8 +48,15 @@
#define irqs_disabled() (local_get_flags() == 0)
-#define hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1)
-#define hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1)
+#define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1)
+#define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1)
+
+#define hard_irq_disable() \
+ do { \
+ __hard_irq_disable(); \
+ get_paca()->soft_enabled = 0; \
+ get_paca()->hard_enabled = 0; \
+ } while(0)
#else
diff --git a/include/asm-powerpc/poll.h b/include/asm-powerpc/poll.h
index 9c7d126..c98509d 100644
--- a/include/asm-powerpc/poll.h
+++ b/include/asm-powerpc/poll.h
@@ -1,24 +1 @@
-#ifndef _ASM_POWERPC_POLL_H
-#define _ASM_POWERPC_POLL_H
-
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif /* _ASM_POWERPC_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-s390/poll.h b/include/asm-s390/poll.h
index 6f7f65a..c98509d 100644
--- a/include/asm-s390/poll.h
+++ b/include/asm-s390/poll.h
@@ -1,35 +1 @@
-/*
- * include/asm-s390/poll.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/poll.h"
- */
-
-#ifndef __S390_POLL_H
-#define __S390_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-sh/poll.h b/include/asm-sh/poll.h
index dbca9b3..c98509d 100644
--- a/include/asm-sh/poll.h
+++ b/include/asm-sh/poll.h
@@ -1,27 +1 @@
-#ifndef __ASM_SH_POLL_H
-#define __ASM_SH_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif /* __ASM_SH_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-sh64/poll.h b/include/asm-sh64/poll.h
index 3a6cbad..ca29502 100644
--- a/include/asm-sh64/poll.h
+++ b/include/asm-sh64/poll.h
@@ -1,37 +1,8 @@
#ifndef __ASM_SH64_POLL_H
#define __ASM_SH64_POLL_H
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * include/asm-sh64/poll.h
- *
- * Copyright (C) 2000, 2001 Paolo Alberelli
- *
- */
+#include <asm-generic/poll.h>
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#undef POLLREMOVE
#endif /* __ASM_SH64_POLL_H */
diff --git a/include/asm-sparc/poll.h b/include/asm-sparc/poll.h
index 26f13fb..091d3ad 100644
--- a/include/asm-sparc/poll.h
+++ b/include/asm-sparc/poll.h
@@ -1,24 +1,12 @@
#ifndef __SPARC_POLL_H
#define __SPARC_POLL_H
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#define POLLERR 8
-#define POLLHUP 16
-#define POLLNVAL 32
-#define POLLRDNORM 64
#define POLLWRNORM POLLOUT
-#define POLLRDBAND 128
#define POLLWRBAND 256
#define POLLMSG 512
#define POLLREMOVE 1024
#define POLLRDHUP 2048
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
#endif
diff --git a/include/asm-sparc64/poll.h b/include/asm-sparc64/poll.h
index ab6b0d1..ebeeb38 100644
--- a/include/asm-sparc64/poll.h
+++ b/include/asm-sparc64/poll.h
@@ -1,24 +1,12 @@
#ifndef __SPARC64_POLL_H
#define __SPARC64_POLL_H
-#define POLLIN 1
-#define POLLPRI 2
-#define POLLOUT 4
-#define POLLERR 8
-#define POLLHUP 16
-#define POLLNVAL 32
-#define POLLRDNORM 64
#define POLLWRNORM POLLOUT
-#define POLLRDBAND 128
#define POLLWRBAND 256
#define POLLMSG 512
#define POLLREMOVE 1024
#define POLLRDHUP 2048
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
#endif
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 261e2f4..18a13ba 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -22,6 +22,7 @@
0-0xBFFFFFFF for user
0-0xFFFFFFFF for kernel */
struct restart_block restart_block;
+ struct thread_info *real_thread; /* Points to non-IRQ stack */
};
#define INIT_THREAD_INFO(tsk) \
@@ -35,6 +36,7 @@
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
+ .real_thread = NULL, \
}
#define init_thread_info (init_thread_union.thread_info)
diff --git a/include/asm-v850/poll.h b/include/asm-v850/poll.h
index c10176c..803cad0 100644
--- a/include/asm-v850/poll.h
+++ b/include/asm-v850/poll.h
@@ -1,24 +1,9 @@
#ifndef __V850_POLL_H__
#define __V850_POLL_H__
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-#define POLLRDNORM 0x0040
#define POLLWRNORM POLLOUT
-#define POLLRDBAND 0x0080
#define POLLWRBAND 0x0100
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
#endif /* __V850_POLL_H__ */
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
index a09fe85..a094276 100644
--- a/include/asm-x86_64/alternative.h
+++ b/include/asm-x86_64/alternative.h
@@ -103,6 +103,12 @@
".previous" : output : [feat] "i" (feature), ##input)
/*
+ * use this macro(s) if you need more than one output parameter
+ * in alternative_io
+ */
+#define ASM_OUTPUT2(a, b) a, b
+
+/*
* Alternative inline assembly for SMP.
*
* The LOCK_PREFIX macro defined here replaces the LOCK and
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index dee632f..e327c83 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -80,6 +80,15 @@
#define __PHYSICAL_START CONFIG_PHYSICAL_START
#define __KERNEL_ALIGN 0x200000
+/*
+ * Make sure kernel is aligned to 2MB address. Catching it at compile
+ * time is better. Change your config file and compile the kernel
+ * for a 2MB aligned address (CONFIG_PHYSICAL_START)
+ */
+#if (CONFIG_PHYSICAL_START % __KERNEL_ALIGN) != 0
+#error "CONFIG_PHYSICAL_START must be a multiple of 2MB"
+#endif
+
#define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START)
#define __START_KERNEL_map _AC(0xffffffff80000000, UL)
#define __PAGE_OFFSET _AC(0xffff810000000000, UL)
diff --git a/include/asm-x86_64/poll.h b/include/asm-x86_64/poll.h
index c0475a9..c98509d 100644
--- a/include/asm-x86_64/poll.h
+++ b/include/asm-x86_64/poll.h
@@ -1,27 +1 @@
-#ifndef __x86_64_POLL_H
-#define __x86_64_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
-#define POLLWRNORM 0x0100
-#define POLLWRBAND 0x0200
-#define POLLMSG 0x0400
-#define POLLREMOVE 0x1000
-#define POLLRDHUP 0x2000
-
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 5957039..ae1ed05 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -621,6 +621,15 @@
__SYSCALL(__NR_move_pages, sys_move_pages)
#define __NR_utimensat 280
__SYSCALL(__NR_utimensat, sys_utimensat)
+#define __IGNORE_getcpu /* implemented as a vsyscall */
+#define __NR_epoll_pwait 281
+__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
+#define __NR_signalfd 282
+__SYSCALL(__NR_signalfd, sys_signalfd)
+#define __NR_timerfd 282
+__SYSCALL(__NR_timerfd, sys_timerfd)
+#define __NR_eventfd 283
+__SYSCALL(__NR_eventfd, sys_eventfd)
#ifndef __NO_STUBS
#define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-xtensa/poll.h b/include/asm-xtensa/poll.h
index 6fd9477..9d2d599 100644
--- a/include/asm-xtensa/poll.h
+++ b/include/asm-xtensa/poll.h
@@ -11,28 +11,10 @@
#ifndef _XTENSA_POLL_H
#define _XTENSA_POLL_H
-
-#define POLLIN 0x0001
-#define POLLPRI 0x0002
-#define POLLOUT 0x0004
-
-#define POLLERR 0x0008
-#define POLLHUP 0x0010
-#define POLLNVAL 0x0020
-
-#define POLLRDNORM 0x0040
-#define POLLRDBAND 0x0080
#define POLLWRNORM POLLOUT
#define POLLWRBAND 0x0100
-
-#define POLLMSG 0x0400
#define POLLREMOVE 0x0800
-#define POLLRDHUP 0x2000
-struct pollfd {
- int fd;
- short events;
- short revents;
-};
+#include <asm-generic/poll.h>
#endif /* _XTENSA_POLL_H */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 94cc04a..bcd01f2 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -140,7 +140,6 @@
header-y += sockios.h
header-y += som.h
header-y += sound.h
-header-y += synclink.h
header-y += taskstats.h
header-y += telephony.h
header-y += termios.h
@@ -191,6 +190,7 @@
unifdef-y += errqueue.h
unifdef-y += ethtool.h
unifdef-y += eventpoll.h
+unifdef-y += signalfd.h
unifdef-y += ext2_fs.h
unifdef-y += ext3_fs.h
unifdef-y += fb.h
@@ -320,6 +320,7 @@
unifdef-y += soundcard.h
unifdef-y += stat.h
unifdef-y += stddef.h
+unifdef-y += synclink.h
unifdef-y += sysctl.h
unifdef-y += tcp.h
unifdef-y += time.h
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 43dc2eb..b903fc0 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -119,6 +119,12 @@
struct list_head ki_list; /* the aio core uses this
* for cancellation */
+
+ /*
+ * If the aio_resfd field of the userspace iocb is not zero,
+ * this is the underlying file* to deliver event to.
+ */
+ struct file *ki_eventfd;
};
#define is_sync_kiocb(iocb) ((iocb)->ki_key == KIOCB_SYNC_KEY)
diff --git a/include/linux/aio_abi.h b/include/linux/aio_abi.h
index e3ca0a4..9e01729 100644
--- a/include/linux/aio_abi.h
+++ b/include/linux/aio_abi.h
@@ -45,6 +45,14 @@
IOCB_CMD_PWRITEV = 8,
};
+/*
+ * Valid flags for the "aio_flags" member of the "struct iocb".
+ *
+ * IOCB_FLAG_RESFD - Set if the "aio_resfd" member of the "struct iocb"
+ * is valid.
+ */
+#define IOCB_FLAG_RESFD (1 << 0)
+
/* read() from /dev/aio returns these structures. */
struct io_event {
__u64 data; /* the data field from the iocb */
@@ -84,7 +92,15 @@
/* extra parameters */
__u64 aio_reserved2; /* TODO: use this for a (struct sigevent *) */
- __u64 aio_reserved3;
+
+ /* flags for the "struct iocb" */
+ __u32 aio_flags;
+
+ /*
+ * if the IOCB_FLAG_RESFD flag of "aio_flags" is set, this is an
+ * eventfd to signal AIO readiness to
+ */
+ __u32 aio_resfd;
}; /* 64 bytes */
#undef IFBIG
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
new file mode 100644
index 0000000..b2e1ba3
--- /dev/null
+++ b/include/linux/anon_inodes.h
@@ -0,0 +1,16 @@
+/*
+ * include/linux/anon_inodes.h
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_ANON_INODES_H
+#define _LINUX_ANON_INODES_H
+
+int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
+ const char *name, const struct file_operations *fops,
+ void *priv);
+
+#endif /* _LINUX_ANON_INODES_H */
+
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 773e30d..fccc6e5 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -91,6 +91,7 @@
#define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */
#define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */
#define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */
+#define AUDIT_OBJ_PID 1318 /* ptrace target */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -111,6 +112,7 @@
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
+#define AUDIT_ANOM_ABEND 1701 /* Process ended abnormally */
#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
@@ -148,6 +150,8 @@
#define AUDIT_CLASS_READ_32 5
#define AUDIT_CLASS_WRITE 6
#define AUDIT_CLASS_WRITE_32 7
+#define AUDIT_CLASS_SIGNAL 8
+#define AUDIT_CLASS_SIGNAL_32 9
/* This bitmask is used to validate user input. It represents all bits that
* are currently used in an audit field constant understood by the kernel.
@@ -337,6 +341,7 @@
#define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
extern int __init audit_register_class(int class, unsigned *list);
extern int audit_classify_syscall(int abi, unsigned syscall);
+extern int audit_classify_arch(int arch);
#ifdef CONFIG_AUDITSYSCALL
/* These are defined in auditsc.c */
/* Public API */
@@ -351,7 +356,8 @@
extern void __audit_inode(const char *name, const struct inode *inode);
extern void __audit_inode_child(const char *dname, const struct inode *inode,
const struct inode *parent);
-extern void __audit_inode_update(const struct inode *inode);
+extern void __audit_ptrace(struct task_struct *t);
+
static inline int audit_dummy_context(void)
{
void *p = current->audit_context;
@@ -372,9 +378,12 @@
if (unlikely(!audit_dummy_context()))
__audit_inode_child(dname, inode, parent);
}
-static inline void audit_inode_update(const struct inode *inode) {
+void audit_core_dumps(long signr);
+
+static inline void audit_ptrace(struct task_struct *t)
+{
if (unlikely(!audit_dummy_context()))
- __audit_inode_update(inode);
+ __audit_ptrace(t);
}
/* Private API (for audit.c only) */
@@ -447,6 +456,7 @@
return 0;
}
extern int audit_n_rules;
+extern int audit_signals;
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -457,10 +467,9 @@
#define audit_putname(n) do { ; } while (0)
#define __audit_inode(n,i) do { ; } while (0)
#define __audit_inode_child(d,i,p) do { ; } while (0)
-#define __audit_inode_update(i) do { ; } while (0)
#define audit_inode(n,i) do { ; } while (0)
#define audit_inode_child(d,i,p) do { ; } while (0)
-#define audit_inode_update(i) do { ; } while (0)
+#define audit_core_dumps(i) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
#define audit_log_task_context(b) do { ; } while (0)
@@ -477,7 +486,9 @@
#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
#define audit_mq_notify(d,n) ({ 0; })
#define audit_mq_getsetattr(d,s) ({ 0; })
+#define audit_ptrace(t) ((void)0)
#define audit_n_rules 0
+#define audit_signals 0
#endif
#ifdef CONFIG_AUDIT
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 70a157a..636502c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -225,6 +225,11 @@
return lhs->tv_nsec - rhs->tv_nsec;
}
+extern int get_compat_itimerspec(struct itimerspec *dst,
+ const struct compat_itimerspec __user *src);
+extern int put_compat_itimerspec(struct compat_itimerspec __user *dst,
+ const struct itimerspec *src);
+
asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
extern int compat_printk(const char *fmt, ...);
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
new file mode 100644
index 0000000..0d6ecc6
--- /dev/null
+++ b/include/linux/eventfd.h
@@ -0,0 +1,29 @@
+/*
+ * include/linux/eventfd.h
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_EVENTFD_H
+#define _LINUX_EVENTFD_H
+
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_EVENTFD
+
+struct file *eventfd_fget(int fd);
+int eventfd_signal(struct file *file, int n);
+
+#else /* CONFIG_EVENTFD */
+
+#define eventfd_fget(fd) ERR_PTR(-ENOSYS)
+#define eventfd_signal(f, n) 0
+
+#endif /* CONFIG_EVENTFD */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_EVENTFD_H */
+
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index f589559..4c03ee3 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -434,6 +434,10 @@
#endif
-#endif
+#else /* CONFIG_BLOCK */
+
+static inline void printk_all_partitions(void) { }
+
+#endif /* CONFIG_BLOCK */
#endif
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 37076b1..827ee74 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -275,6 +275,7 @@
#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
#define HID_QUIRK_RESET_LEDS 0x00400000
+#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000
/*
* This is the global environment of the parser. This information is
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 45170b2..276ccaa 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -65,9 +65,9 @@
.posix_timers = LIST_HEAD_INIT(sig.posix_timers), \
.cpu_timers = INIT_CPU_TIMERS(sig.cpu_timers), \
.rlim = INIT_RLIMITS, \
- .pgrp = 1, \
+ .pgrp = 0, \
.tty_old_pgrp = NULL, \
- { .__session = 1}, \
+ { .__session = 0}, \
}
extern struct nsproxy init_nsproxy;
@@ -84,10 +84,33 @@
.count = ATOMIC_INIT(1), \
.action = { { { .sa_handler = NULL, } }, }, \
.siglock = __SPIN_LOCK_UNLOCKED(sighand.siglock), \
+ .signalfd_list = LIST_HEAD_INIT(sighand.signalfd_list), \
}
extern struct group_info init_groups;
+#define INIT_STRUCT_PID { \
+ .count = ATOMIC_INIT(1), \
+ .nr = 0, \
+ /* Don't put this struct pid in pid_hash */ \
+ .pid_chain = { .next = NULL, .pprev = NULL }, \
+ .tasks = { \
+ { .first = &init_task.pids[PIDTYPE_PID].node }, \
+ { .first = &init_task.pids[PIDTYPE_PGID].node }, \
+ { .first = &init_task.pids[PIDTYPE_SID].node }, \
+ }, \
+ .rcu = RCU_HEAD_INIT, \
+}
+
+#define INIT_PID_LINK(type) \
+{ \
+ .node = { \
+ .next = NULL, \
+ .pprev = &init_struct_pid.tasks[type].first, \
+ }, \
+ .pid = &init_struct_pid, \
+}
+
/*
* INIT_TASK is used to set up the first task table, touch at
* your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -139,6 +162,11 @@
.cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \
.fs_excl = ATOMIC_INIT(0), \
.pi_lock = __SPIN_LOCK_UNLOCKED(tsk.pi_lock), \
+ .pids = { \
+ [PIDTYPE_PID] = INIT_PID_LINK(PIDTYPE_PID), \
+ [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID), \
+ [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \
+ }, \
INIT_TRACE_IRQFLAGS \
INIT_LOCKDEP \
}
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index f7b01b9..5323f62 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -241,6 +241,16 @@
#define save_and_cli(x) save_and_cli(&x)
#endif /* CONFIG_SMP */
+/* Some architectures might implement lazy enabling/disabling of
+ * interrupts. In some cases, such as stop_machine, we might want
+ * to ensure that after a local_irq_disable(), interrupts have
+ * really been disabled in hardware. Such architectures need to
+ * implement the following hook.
+ */
+#ifndef hard_irq_disable
+#define hard_irq_disable() do { } while(0)
+#endif
+
/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
frequency threaded job scheduling. For almost all the purposes
tasklets are more than enough. F.e. all serial device BHs et
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 8645181..eec0d13 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -213,6 +213,17 @@
extern void dump_stack(void);
+enum {
+ DUMP_PREFIX_NONE,
+ DUMP_PREFIX_ADDRESS,
+ DUMP_PREFIX_OFFSET
+};
+extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
+ size_t linebuflen);
+extern void print_hex_dump(const char *level, int prefix_type,
+ void *buf, size_t len);
+#define hex_asc(x) "0123456789abcdef"[x]
+
#ifdef DEBUG
/* If you are writing a driver, please use dev_dbg instead */
#define pr_debug(fmt,arg...) \
diff --git a/include/linux/magic.h b/include/linux/magic.h
index a9c6567..9d713c0 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -14,6 +14,7 @@
#define ISOFS_SUPER_MAGIC 0x9660
#define JFFS2_SUPER_MAGIC 0x72b6
#define KVMFS_SUPER_MAGIC 0x19700426
+#define ANON_INODE_FS_MAGIC 0x09041934
#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
diff --git a/include/linux/module.h b/include/linux/module.h
index 792d483..e6e0f86 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -124,7 +124,7 @@
*/
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
-/* Author, ideally of form NAME <EMAIL>[, NAME <EMAIL>]*[ and NAME <EMAIL>] */
+/* Author, ideally of form NAME[, NAME]*[ and NAME] */
#define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
/* What your module does. */
diff --git a/include/linux/mpage.h b/include/linux/mpage.h
index cc5fb75..068a0c9 100644
--- a/include/linux/mpage.h
+++ b/include/linux/mpage.h
@@ -12,7 +12,6 @@
#ifdef CONFIG_BLOCK
struct writeback_control;
-typedef int (writepage_t)(struct page *page, struct writeback_control *wbc);
int mpage_readpages(struct address_space *mapping, struct list_head *pages,
unsigned nr_pages, get_block_t get_block);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3044622..f671cd2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -467,6 +467,8 @@
/* device index hash chain */
struct hlist_node index_hlist;
+ struct net_device *link_watch_next;
+
/* register/unregister state machine */
enum { NETREG_UNINITIALIZED=0,
NETREG_REGISTERED, /* completed register_netdevice */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 022edfa..7e733a6 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -54,6 +54,14 @@
unsigned char data[0];
};
+#define XT_TARGET_INIT(__name, __size) \
+{ \
+ .target.u.user = { \
+ .target_size = XT_ALIGN(__size), \
+ .name = __name, \
+ }, \
+}
+
struct xt_standard_target
{
struct xt_entry_target target;
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 24c8786d..584cd1b 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -238,6 +238,47 @@
*/
#ifdef __KERNEL__
+/* Standard entry. */
+struct arpt_standard
+{
+ struct arpt_entry entry;
+ struct arpt_standard_target target;
+};
+
+struct arpt_error_target
+{
+ struct arpt_entry_target target;
+ char errorname[ARPT_FUNCTION_MAXNAMELEN];
+};
+
+struct arpt_error
+{
+ struct arpt_entry entry;
+ struct arpt_error_target target;
+};
+
+#define ARPT_ENTRY_INIT(__size) \
+{ \
+ .target_offset = sizeof(struct arpt_entry), \
+ .next_offset = (__size), \
+}
+
+#define ARPT_STANDARD_INIT(__verdict) \
+{ \
+ .entry = ARPT_ENTRY_INIT(sizeof(struct arpt_standard)), \
+ .target = XT_TARGET_INIT(ARPT_STANDARD_TARGET, \
+ sizeof(struct arpt_standard_target)), \
+ .target.verdict = -(__verdict) - 1, \
+}
+
+#define ARPT_ERROR_INIT \
+{ \
+ .entry = ARPT_ENTRY_INIT(sizeof(struct arpt_error)), \
+ .target = XT_TARGET_INIT(ARPT_ERROR_TARGET, \
+ sizeof(struct arpt_error_target)), \
+ .target.errorname = "ERROR", \
+}
+
#define arpt_register_target(tgt) \
({ (tgt)->family = NF_ARP; \
xt_register_target(tgt); })
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 9527296..2f46dd7 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -295,6 +295,28 @@
struct ipt_error_target target;
};
+#define IPT_ENTRY_INIT(__size) \
+{ \
+ .target_offset = sizeof(struct ipt_entry), \
+ .next_offset = (__size), \
+}
+
+#define IPT_STANDARD_INIT(__verdict) \
+{ \
+ .entry = IPT_ENTRY_INIT(sizeof(struct ipt_standard)), \
+ .target = XT_TARGET_INIT(IPT_STANDARD_TARGET, \
+ sizeof(struct xt_standard_target)), \
+ .target.verdict = -(__verdict) - 1, \
+}
+
+#define IPT_ERROR_INIT \
+{ \
+ .entry = IPT_ENTRY_INIT(sizeof(struct ipt_error)), \
+ .target = XT_TARGET_INIT(IPT_ERROR_TARGET, \
+ sizeof(struct ipt_error_target)), \
+ .target.errorname = "ERROR", \
+}
+
extern unsigned int ipt_do_table(struct sk_buff **pskb,
unsigned int hook,
const struct net_device *in,
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 61aa104..4686f83 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -123,6 +123,28 @@
struct ip6t_error_target target;
};
+#define IP6T_ENTRY_INIT(__size) \
+{ \
+ .target_offset = sizeof(struct ip6t_entry), \
+ .next_offset = (__size), \
+}
+
+#define IP6T_STANDARD_INIT(__verdict) \
+{ \
+ .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)), \
+ .target = XT_TARGET_INIT(IP6T_STANDARD_TARGET, \
+ sizeof(struct ip6t_standard_target)), \
+ .target.verdict = -(__verdict) - 1, \
+}
+
+#define IP6T_ERROR_INIT \
+{ \
+ .entry = IP6T_ENTRY_INIT(sizeof(struct ip6t_error)), \
+ .target = XT_TARGET_INIT(IP6T_ERROR_TARGET, \
+ sizeof(struct ip6t_error_target)), \
+ .target.errorname = "ERROR", \
+}
+
/*
* New IP firewall options for [gs]etsockopt at the RAW IP level.
* Unlike BSD Linux inherits IP options so you don't have to use
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 2ac27f9..1e0e4e3 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -51,6 +51,8 @@
struct rcu_head rcu;
};
+extern struct pid init_struct_pid;
+
struct pid_link
{
struct hlist_node node;
@@ -76,8 +78,7 @@
* write-held.
*/
extern int FASTCALL(attach_pid(struct task_struct *task,
- enum pid_type type, int nr));
-
+ enum pid_type type, struct pid *pid));
extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
extern void FASTCALL(transfer_pid(struct task_struct *old,
struct task_struct *new, enum pid_type));
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 17b72d8..a81897e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -88,6 +88,7 @@
struct exec_domain;
struct futex_pi_state;
+struct bio;
/*
* List of flags we want to share for kernel threads,
@@ -391,6 +392,7 @@
atomic_t count;
struct k_sigaction action[_NSIG];
spinlock_t siglock;
+ struct list_head signalfd_list;
};
struct pacct_struct {
@@ -469,6 +471,7 @@
cputime_t utime, stime, cutime, cstime;
unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
+ unsigned long inblock, oublock, cinblock, coublock;
/*
* Cumulative ns of scheduled CPU time for dead threads in the
@@ -1014,6 +1017,9 @@
/* journalling filesystem info */
void *journal_info;
+/* stacked block device info */
+ struct bio *bio_list, **bio_tail;
+
/* VM state */
struct reclaim_state *reclaim_state;
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 3fa0fab..9a5eac5 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -233,6 +233,7 @@
return sig <= _NSIG ? 1 : 0;
}
+extern int next_signal(struct sigpending *pending, sigset_t *mask);
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
extern long do_sigpending(void __user *, unsigned long);
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h
new file mode 100644
index 0000000..5104294
--- /dev/null
+++ b/include/linux/signalfd.h
@@ -0,0 +1,97 @@
+/*
+ * include/linux/signalfd.h
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_SIGNALFD_H
+#define _LINUX_SIGNALFD_H
+
+
+struct signalfd_siginfo {
+ __u32 signo;
+ __s32 err;
+ __s32 code;
+ __u32 pid;
+ __u32 uid;
+ __s32 fd;
+ __u32 tid;
+ __u32 band;
+ __u32 overrun;
+ __u32 trapno;
+ __s32 status;
+ __s32 svint;
+ __u64 svptr;
+ __u64 utime;
+ __u64 stime;
+ __u64 addr;
+
+ /*
+ * Pad strcture to 128 bytes. Remember to update the
+ * pad size when you add new memebers. We use a fixed
+ * size structure to avoid compatibility problems with
+ * future versions, and we leave extra space for additional
+ * members. We use fixed size members because this strcture
+ * comes out of a read(2) and we really don't want to have
+ * a compat on read(2).
+ */
+ __u8 __pad[48];
+};
+
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_SIGNALFD
+
+/*
+ * Deliver the signal to listening signalfd. This must be called
+ * with the sighand lock held. Same are the following that end up
+ * calling signalfd_deliver().
+ */
+void signalfd_deliver(struct task_struct *tsk, int sig);
+
+/*
+ * No need to fall inside signalfd_deliver() if no signal listeners
+ * are available.
+ */
+static inline void signalfd_notify(struct task_struct *tsk, int sig)
+{
+ if (unlikely(!list_empty(&tsk->sighand->signalfd_list)))
+ signalfd_deliver(tsk, sig);
+}
+
+/*
+ * The signal -1 is used to notify the signalfd that the sighand
+ * is on its way to be detached.
+ */
+static inline void signalfd_detach_locked(struct task_struct *tsk)
+{
+ if (unlikely(!list_empty(&tsk->sighand->signalfd_list)))
+ signalfd_deliver(tsk, -1);
+}
+
+static inline void signalfd_detach(struct task_struct *tsk)
+{
+ struct sighand_struct *sighand = tsk->sighand;
+
+ if (unlikely(!list_empty(&sighand->signalfd_list))) {
+ spin_lock_irq(&sighand->siglock);
+ signalfd_deliver(tsk, -1);
+ spin_unlock_irq(&sighand->siglock);
+ }
+}
+
+#else /* CONFIG_SIGNALFD */
+
+#define signalfd_deliver(t, s) do { } while (0)
+#define signalfd_notify(t, s) do { } while (0)
+#define signalfd_detach_locked(t) do { } while (0)
+#define signalfd_detach(t) do { } while (0)
+
+#endif /* CONFIG_SIGNALFD */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SIGNALFD_H */
+
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index c8b0426..5562fbf 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -291,4 +291,28 @@
#define MGSL_IOCGGPIO _IOR(MGSL_MAGIC_IOC,17,struct gpio_desc)
#define MGSL_IOCWAITGPIO _IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc)
+#ifdef __KERNEL__
+/* provide 32 bit ioctl compatibility on 64 bit systems */
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+struct MGSL_PARAMS32 {
+ compat_ulong_t mode;
+ unsigned char loopback;
+ unsigned short flags;
+ unsigned char encoding;
+ compat_ulong_t clock_speed;
+ unsigned char addr_filter;
+ unsigned short crc_type;
+ unsigned char preamble_length;
+ unsigned char preamble;
+ compat_ulong_t data_rate;
+ unsigned char data_bits;
+ unsigned char stop_bits;
+ unsigned char parity;
+};
+#define MGSL_IOCSPARAMS32 _IOW(MGSL_MAGIC_IOC,0,struct MGSL_PARAMS32)
+#define MGSL_IOCGPARAMS32 _IOR(MGSL_MAGIC_IOC,1,struct MGSL_PARAMS32)
+#endif
+#endif
+
#endif /* _SYNCLINK_H_ */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3139f44..b02070e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -604,6 +604,10 @@
asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
size_t len);
asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
+asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask);
+asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
+ const struct itimerspec __user *utmr);
+asmlinkage long sys_eventfd(unsigned int count);
int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
index df2a319..1218733 100644
--- a/include/linux/task_io_accounting_ops.h
+++ b/include/linux/task_io_accounting_ops.h
@@ -10,11 +10,29 @@
current->ioac.read_bytes += bytes;
}
+/*
+ * We approximate number of blocks, because we account bytes only.
+ * A 'block' is 512 bytes
+ */
+static inline unsigned long task_io_get_inblock(const struct task_struct *p)
+{
+ return p->ioac.read_bytes >> 9;
+}
+
static inline void task_io_account_write(size_t bytes)
{
current->ioac.write_bytes += bytes;
}
+/*
+ * We approximate number of blocks, because we account bytes only.
+ * A 'block' is 512 bytes
+ */
+static inline unsigned long task_io_get_oublock(const struct task_struct *p)
+{
+ return p->ioac.write_bytes >> 9;
+}
+
static inline void task_io_account_cancelled_write(size_t bytes)
{
current->ioac.cancelled_write_bytes += bytes;
@@ -31,10 +49,20 @@
{
}
+static inline unsigned long task_io_get_inblock(const struct task_struct *p)
+{
+ return 0;
+}
+
static inline void task_io_account_write(size_t bytes)
{
}
+static inline unsigned long task_io_get_oublock(const struct task_struct *p)
+{
+ return 0;
+}
+
static inline void task_io_account_cancelled_write(size_t bytes)
{
}
diff --git a/include/linux/timerfd.h b/include/linux/timerfd.h
new file mode 100644
index 0000000..cf2b10d
--- /dev/null
+++ b/include/linux/timerfd.h
@@ -0,0 +1,17 @@
+/*
+ * include/linux/timerfd.h
+ *
+ * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_TIMERFD_H
+#define _LINUX_TIMERFD_H
+
+
+#define TFD_TIMER_ABSTIME (1 << 0)
+
+
+
+#endif /* _LINUX_TIMERFD_H */
+
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 659487e..85c95cd 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -52,6 +52,11 @@
* This routine allows the tty driver to implement
* device-specific ioctl's. If the ioctl number passed in cmd
* is not recognized by the driver, it should return ENOIOCTLCMD.
+ *
+ * long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+ * unsigned int cmd, unsigned long arg);
+ *
+ * implement ioctl processing for 32 bit process on 64 bit system
*
* void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
*
@@ -132,6 +137,8 @@
int (*chars_in_buffer)(struct tty_struct *tty);
int (*ioctl)(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
+ long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg);
void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
void (*throttle)(struct tty_struct * tty);
void (*unthrottle)(struct tty_struct * tty);
@@ -193,6 +200,8 @@
int (*chars_in_buffer)(struct tty_struct *tty);
int (*ioctl)(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
+ long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+ unsigned int cmd, unsigned long arg);
void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
void (*throttle)(struct tty_struct * tty);
void (*unthrottle)(struct tty_struct * tty);
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index d75932e..6226504 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -59,6 +59,11 @@
* low-level driver can "grab" an ioctl request before the line
* discpline has a chance to see it.
*
+ * long (*compat_ioctl)(struct tty_struct * tty, struct file * file,
+ * unsigned int cmd, unsigned long arg);
+ *
+ * Process ioctl calls from 32-bit process on 64-bit system
+ *
* void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
*
* This function notifies the line discpline that a change has
@@ -118,6 +123,8 @@
const unsigned char * buf, size_t nr);
int (*ioctl)(struct tty_struct * tty, struct file * file,
unsigned int cmd, unsigned long arg);
+ long (*compat_ioctl)(struct tty_struct * tty, struct file * file,
+ unsigned int cmd, unsigned long arg);
void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
unsigned int (*poll)(struct tty_struct *, struct file *,
struct poll_table_struct *);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index daa6c12..050915b 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -111,9 +111,15 @@
balance_dirty_pages_ratelimited_nr(mapping, 1);
}
+typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc,
+ void *data);
+
int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
-extern int generic_writepages(struct address_space *mapping,
- struct writeback_control *wbc);
+int generic_writepages(struct address_space *mapping,
+ struct writeback_control *wbc);
+int write_cache_pages(struct address_space *mapping,
+ struct writeback_control *wbc, writepage_t writepage,
+ void *data);
int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
int sync_page_range(struct inode *inode, struct address_space *mapping,
loff_t pos, loff_t count);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 1c6b8bd..4732432 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -183,13 +183,6 @@
extern void nf_conntrack_flush(void);
-extern struct nf_conntrack_helper *
-nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
-extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
-
-extern struct nf_conntrack_helper *
-__nf_conntrack_helper_find_byname(const char *name);
-
extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index f32f714..96a58d8 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -56,9 +56,6 @@
*/
int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb);
- /* Called when a conntrack entry is destroyed */
- void (*destroy)(struct nf_conn *conntrack);
-
/*
* Called before tracking.
* *dataoff: offset of protocol header (TCP, UDP,...) in *pskb
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
index e765654..f974318 100644
--- a/include/net/netfilter/nf_nat_rule.h
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -10,16 +10,11 @@
unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
- struct nf_conn *ct,
- struct nf_nat_info *info);
+ struct nf_conn *ct);
extern unsigned int
-alloc_null_binding(struct nf_conn *ct,
- struct nf_nat_info *info,
- unsigned int hooknum);
+alloc_null_binding(struct nf_conn *ct, unsigned int hooknum);
extern unsigned int
-alloc_null_binding_confirmed(struct nf_conn *ct,
- struct nf_nat_info *info,
- unsigned int hooknum);
+alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum);
#endif /* _NF_NAT_RULE_H */
diff --git a/include/net/udp.h b/include/net/udp.h
index 98755eb..496f89d 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -119,9 +119,16 @@
}
+struct udp_get_port_ops {
+ int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
+ int (*saddr_any)(const struct sock *sk);
+ unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
+ const struct sock *sk);
+};
+
/* net/ipv4/udp.c */
extern int udp_get_port(struct sock *sk, unsigned short snum,
- int (*saddr_cmp)(const struct sock *, const struct sock *));
+ const struct udp_get_port_ops *ops);
extern void udp_err(struct sk_buff *, u32);
extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 635b0ea..50b4b42 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -120,5 +120,5 @@
extern void udplite4_register(void);
extern int udplite_get_port(struct sock *sk, unsigned short snum,
- int (*scmp)(const struct sock *, const struct sock *));
+ const struct udp_get_port_ops *ops);
#endif /* _UDPLITE_H */
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
new file mode 100644
index 0000000..4eea637
--- /dev/null
+++ b/include/video/atmel_lcdc.h
@@ -0,0 +1,196 @@
+/*
+ * Header file for AT91/AT32 LCD Controller
+ *
+ * Data structure and register user interface
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+#ifndef __ATMEL_LCDC_H__
+#define __ATMEL_LCDC_H__
+
+ /* LCD Controller info data structure */
+struct atmel_lcdfb_info {
+ spinlock_t lock;
+ struct fb_info *info;
+ void __iomem *mmio;
+ unsigned long irq_base;
+
+ unsigned int guard_time;
+ struct platform_device *pdev;
+ struct clk *bus_clk;
+ struct clk *lcdc_clk;
+ unsigned int default_bpp;
+ unsigned int default_lcdcon2;
+ unsigned int default_dmacon;
+ void (*atmel_lcdfb_power_control)(int on);
+ struct fb_monspecs *default_monspecs;
+ u32 pseudo_palette[16];
+};
+
+#define ATMEL_LCDC_DMABADDR1 0x00
+#define ATMEL_LCDC_DMABADDR2 0x04
+#define ATMEL_LCDC_DMAFRMPT1 0x08
+#define ATMEL_LCDC_DMAFRMPT2 0x0c
+#define ATMEL_LCDC_DMAFRMADD1 0x10
+#define ATMEL_LCDC_DMAFRMADD2 0x14
+
+#define ATMEL_LCDC_DMAFRMCFG 0x18
+#define ATMEL_LCDC_FRSIZE (0x7fffff << 0)
+#define ATMEL_LCDC_BLENGTH_OFFSET 24
+#define ATMEL_LCDC_BLENGTH (0x7f << ATMEL_LCDC_BLENGTH_OFFSET)
+
+#define ATMEL_LCDC_DMACON 0x1c
+#define ATMEL_LCDC_DMAEN (0x1 << 0)
+#define ATMEL_LCDC_DMARST (0x1 << 1)
+#define ATMEL_LCDC_DMABUSY (0x1 << 2)
+#define ATMEL_LCDC_DMAUPDT (0x1 << 3)
+#define ATMEL_LCDC_DMA2DEN (0x1 << 4)
+
+#define ATMEL_LCDC_DMA2DCFG 0x20
+#define ATMEL_LCDC_ADDRINC_OFFSET 0
+#define ATMEL_LCDC_ADDRINC (0xffff)
+#define ATMEL_LCDC_PIXELOFF_OFFSET 24
+#define ATMEL_LCDC_PIXELOFF (0x1f << 24)
+
+#define ATMEL_LCDC_LCDCON1 0x0800
+#define ATMEL_LCDC_BYPASS (1 << 0)
+#define ATMEL_LCDC_CLKVAL_OFFSET 12
+#define ATMEL_LCDC_CLKVAL (0x1ff << ATMEL_LCDC_CLKVAL_OFFSET)
+#define ATMEL_LCDC_LINCNT (0x7ff << 21)
+
+#define ATMEL_LCDC_LCDCON2 0x0804
+#define ATMEL_LCDC_DISTYPE (3 << 0)
+#define ATMEL_LCDC_DISTYPE_STNMONO (0 << 0)
+#define ATMEL_LCDC_DISTYPE_STNCOLOR (1 << 0)
+#define ATMEL_LCDC_DISTYPE_TFT (2 << 0)
+#define ATMEL_LCDC_SCANMOD (1 << 2)
+#define ATMEL_LCDC_SCANMOD_SINGLE (0 << 2)
+#define ATMEL_LCDC_SCANMOD_DUAL (1 << 2)
+#define ATMEL_LCDC_IFWIDTH (3 << 3)
+#define ATMEL_LCDC_IFWIDTH_4 (0 << 3)
+#define ATMEL_LCDC_IFWIDTH_8 (1 << 3)
+#define ATMEL_LCDC_IFWIDTH_16 (2 << 3)
+#define ATMEL_LCDC_PIXELSIZE (7 << 5)
+#define ATMEL_LCDC_PIXELSIZE_1 (0 << 5)
+#define ATMEL_LCDC_PIXELSIZE_2 (1 << 5)
+#define ATMEL_LCDC_PIXELSIZE_4 (2 << 5)
+#define ATMEL_LCDC_PIXELSIZE_8 (3 << 5)
+#define ATMEL_LCDC_PIXELSIZE_16 (4 << 5)
+#define ATMEL_LCDC_PIXELSIZE_24 (5 << 5)
+#define ATMEL_LCDC_PIXELSIZE_32 (6 << 5)
+#define ATMEL_LCDC_INVVD (1 << 8)
+#define ATMEL_LCDC_INVVD_NORMAL (0 << 8)
+#define ATMEL_LCDC_INVVD_INVERTED (1 << 8)
+#define ATMEL_LCDC_INVFRAME (1 << 9 )
+#define ATMEL_LCDC_INVFRAME_NORMAL (0 << 9)
+#define ATMEL_LCDC_INVFRAME_INVERTED (1 << 9)
+#define ATMEL_LCDC_INVLINE (1 << 10)
+#define ATMEL_LCDC_INVLINE_NORMAL (0 << 10)
+#define ATMEL_LCDC_INVLINE_INVERTED (1 << 10)
+#define ATMEL_LCDC_INVCLK (1 << 11)
+#define ATMEL_LCDC_INVCLK_NORMAL (0 << 11)
+#define ATMEL_LCDC_INVCLK_INVERTED (1 << 11)
+#define ATMEL_LCDC_INVDVAL (1 << 12)
+#define ATMEL_LCDC_INVDVAL_NORMAL (0 << 12)
+#define ATMEL_LCDC_INVDVAL_INVERTED (1 << 12)
+#define ATMEL_LCDC_CLKMOD (1 << 15)
+#define ATMEL_LCDC_CLKMOD_ACTIVEDISPLAY (0 << 15)
+#define ATMEL_LCDC_CLKMOD_ALWAYSACTIVE (1 << 15)
+#define ATMEL_LCDC_MEMOR (1 << 31)
+#define ATMEL_LCDC_MEMOR_BIG (0 << 31)
+#define ATMEL_LCDC_MEMOR_LITTLE (1 << 31)
+
+#define ATMEL_LCDC_TIM1 0x0808
+#define ATMEL_LCDC_VFP (0xff << 0)
+#define ATMEL_LCDC_VBP_OFFSET 8
+#define ATMEL_LCDC_VBP (0xff << ATMEL_LCDC_VBP_OFFSET)
+#define ATMEL_LCDC_VPW_OFFSET 16
+#define ATMEL_LCDC_VPW (0x3f << ATMEL_LCDC_VPW_OFFSET)
+#define ATMEL_LCDC_VHDLY_OFFSET 24
+#define ATMEL_LCDC_VHDLY (0xf << ATMEL_LCDC_VHDLY_OFFSET)
+
+#define ATMEL_LCDC_TIM2 0x080c
+#define ATMEL_LCDC_HBP (0xff << 0)
+#define ATMEL_LCDC_HPW_OFFSET 8
+#define ATMEL_LCDC_HPW (0x3f << ATMEL_LCDC_HPW_OFFSET)
+#define ATMEL_LCDC_HFP_OFFSET 21
+#define ATMEL_LCDC_HFP (0x7ff << ATMEL_LCDC_HFP_OFFSET)
+
+#define ATMEL_LCDC_LCDFRMCFG 0x0810
+#define ATMEL_LCDC_LINEVAL (0x7ff << 0)
+#define ATMEL_LCDC_HOZVAL_OFFSET 21
+#define ATMEL_LCDC_HOZVAL (0x7ff << ATMEL_LCDC_HOZVAL_OFFSET)
+
+#define ATMEL_LCDC_FIFO 0x0814
+#define ATMEL_LCDC_FIFOTH (0xffff)
+
+#define ATMEL_LCDC_MVAL 0x0818
+
+#define ATMEL_LCDC_DP1_2 0x081c
+#define ATMEL_LCDC_DP4_7 0x0820
+#define ATMEL_LCDC_DP3_5 0x0824
+#define ATMEL_LCDC_DP2_3 0x0828
+#define ATMEL_LCDC_DP5_7 0x082c
+#define ATMEL_LCDC_DP3_4 0x0830
+#define ATMEL_LCDC_DP4_5 0x0834
+#define ATMEL_LCDC_DP6_7 0x0838
+#define ATMEL_LCDC_DP1_2_VAL (0xff)
+#define ATMEL_LCDC_DP4_7_VAL (0xfffffff)
+#define ATMEL_LCDC_DP3_5_VAL (0xfffff)
+#define ATMEL_LCDC_DP2_3_VAL (0xfff)
+#define ATMEL_LCDC_DP5_7_VAL (0xfffffff)
+#define ATMEL_LCDC_DP3_4_VAL (0xffff)
+#define ATMEL_LCDC_DP4_5_VAL (0xfffff)
+#define ATMEL_LCDC_DP6_7_VAL (0xfffffff)
+
+#define ATMEL_LCDC_PWRCON 0x083c
+#define ATMEL_LCDC_PWR (1 << 0)
+#define ATMEL_LCDC_GUARDT_OFFSET 1
+#define ATMEL_LCDC_GUARDT (0x7f << ATMEL_LCDC_GUARDT_OFFSET)
+#define ATMEL_LCDC_BUSY (1 << 31)
+
+#define ATMEL_LCDC_CONTRAST_CTR 0x0840
+#define ATMEL_LCDC_PS (3 << 0)
+#define ATMEL_LCDC_PS_DIV1 (0 << 0)
+#define ATMEL_LCDC_PS_DIV2 (1 << 0)
+#define ATMEL_LCDC_PS_DIV4 (2 << 0)
+#define ATMEL_LCDC_PS_DIV8 (3 << 0)
+#define ATMEL_LCDC_POL (1 << 2)
+#define ATMEL_LCDC_POL_NEGATIVE (0 << 2)
+#define ATMEL_LCDC_POL_POSITIVE (1 << 2)
+#define ATMEL_LCDC_ENA (1 << 3)
+#define ATMEL_LCDC_ENA_PWMDISABLE (0 << 3)
+#define ATMEL_LCDC_ENA_PWMENABLE (1 << 3)
+
+#define ATMEL_LCDC_CONTRAST_VAL 0x0844
+#define ATMEL_LCDC_CVAL (0xff)
+
+#define ATMEL_LCDC_IER 0x0848
+#define ATMEL_LCDC_IDR 0x084c
+#define ATMEL_LCDC_IMR 0x0850
+#define ATMEL_LCDC_ISR 0x0854
+#define ATMEL_LCDC_ICR 0x0858
+#define ATMEL_LCDC_LNI (1 << 0)
+#define ATMEL_LCDC_LSTLNI (1 << 1)
+#define ATMEL_LCDC_EOFI (1 << 2)
+#define ATMEL_LCDC_UFLWI (1 << 4)
+#define ATMEL_LCDC_OWRI (1 << 5)
+#define ATMEL_LCDC_MERI (1 << 6)
+
+#define ATMEL_LCDC_LUT(n) (0x0c00 + ((n)*4))
+
+#endif /* __ATMEL_LCDC_H__ */
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index 94c7d2d..d52e45a 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -7,9 +7,6 @@
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
- *
- * $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $
- *
*/
#ifndef PM3FB_H
@@ -1119,117 +1116,10 @@
/* ***** pm3fb useful define and macro ***** */
/* ***************************************** */
-/* permedia3 -specific definitions */
-#define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
-
-/* in case it's not in linux/pci.h */
-#ifndef PCI_DEVICE_ID_3DLABS_PERMEDIA3
-#define PCI_DEVICE_ID_3DLABS_PERMEDIA3 0x000a
-#endif
-
-/* max number of simultaneous board */
-#define PM3_MAX_BOARD 4
-
/* max size of options */
#define PM3_OPTIONS_SIZE 256
/* max size of font name */
#define PM3_FONTNAME_SIZE 40
-/* do we want accelerated console */
-#define PM3FB_USE_ACCEL 1
-
-/* for driver debugging ONLY */
-/* 0 = assert only, 1 = error, 2 = info, 3+ = verbose */
-/* define PM3FB_MASTER_DEBUG 1 */
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3)
-#define PM3FB_TRACE
-#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3) */
-
-#ifdef PM3FB_MASTER_DEBUG
-#define DPRINTK(l,a,b...) do { if ((l) <= PM3FB_MASTER_DEBUG) printk("pm3fb: %s: " a, __FUNCTION__ , ## b); } while (0)
-#define DASSERT(t,a,b...) do { if (!(t)) printk("pm3fb: _assert failed: %s: " a, __FUNCTION__ , ## b); } while (0)
-#ifdef PM3FB_TRACE
-#define DTRACE printk("pm3fb: _enter %s\n", __FUNCTION__)
-#else /* PM3FB_TRACE */
-#define DTRACE
-#endif /* PM3FB_TRACE */
-#else /* PM3FB_MASTER_DEBUG */
-#define DPRINTK(l,a,b...)
-#define DASSERT(t,a,b...)
-#define DTRACE
-#endif /* PM3FB_MASTER_DEBUG */
-
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2)
-#define PM3_SHOW_CUR_MODE pm3fb_show_cur_mode(l_fb_info)
-#else
-#define PM3_SHOW_CUR_MODE /* pm3fb_show_cur_mode() */
-#endif
-
-/* ******************************************** */
-/* ***** A bunch of register-access macro ***** */
-/* ******************************************** */
-
-#define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
-#define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
-
-
-#define depth2bpp(d) ((d + 7L) & ~7L)
-#define depth2ByPP(d) (depth2bpp(d) / 8)
-
-#define depth_supported(d) ((d == 8) || (d == 12) || (d == 15) || (d == 16) || (d==32))
-
-
-#define PM3_WAIT(n) \
-do{ \
- while(PM3_READ_REG(PM3InFIFOSpace)<(n)); \
-} while(0)
-
-#define PM3_DELAY(x) do { \
- int delay = x; \
- unsigned char tmp; \
- while(delay--){tmp = PM3_READ_REG(PM3InFIFOSpace);}; \
-} while(0)
-
-#define PM3_SLOW_WRITE_REG(r,v) \
-do{ \
- DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in slow write\n"); \
- mb(); \
- PM3_WAIT(1); \
- mb(); \
- PM3_WRITE_REG(r,v); \
-} while(0)
-
-#define PM3_SET_INDEX(index) \
-do{ \
- PM3_SLOW_WRITE_REG(PM3RD_IndexHigh,(((index)>>8)&0xff)); \
- PM3_SLOW_WRITE_REG(PM3RD_IndexLow,((index)&0xff)); \
-} while(0)
-
-#define PM3_WRITE_DAC_REG(r, v) \
-do { \
- DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in write dac reg\n"); \
- PM3_SET_INDEX(r); \
- mb(); \
- PM3_WRITE_REG(PM3RD_IndexedData, v); \
-} while (0)
-
-/* next one is really a function, added as a macro to be consistent */
-#define PM3_READ_DAC_REG(r) pm3fb_read_dac_reg(l_fb_info, r)
-
-
-#define PM3_COLOR(c) \
-do { \
- if (l_fb_info->current_par->depth == 8) \
- { \
- c = (c & 0xFF); \
- c = c | (c << 8); \
- } \
- if ((l_fb_info->current_par->depth == 8) || (depth2bpp(l_fb_info->current_par->depth) == 16)) \
- { \
- c = (c & 0xFFFF); \
- c = c | (c << 16); \
- } \
-} while (0)
-
#endif /* PM3FB_H */
diff --git a/init/Kconfig b/init/Kconfig
index 322b1f8..4e009fd 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -475,13 +475,53 @@
support for "fast userspace mutexes". The resulting kernel may not
run glibc-based applications correctly.
+config ANON_INODES
+ bool "Enable anonymous inode source" if EMBEDDED
+ default y
+ help
+ Anonymous inode source for pseudo-files like epoll, signalfd,
+ timerfd and eventfd.
+
+ If unsure, say Y.
+
config EPOLL
bool "Enable eventpoll support" if EMBEDDED
default y
+ depends on ANON_INODES
help
Disabling this option will cause the kernel to be built without
support for epoll family of system calls.
+config SIGNALFD
+ bool "Enable signalfd() system call" if EMBEDDED
+ depends on ANON_INODES
+ default y
+ help
+ Enable the signalfd() system call that allows to receive signals
+ on a file descriptor.
+
+ If unsure, say Y.
+
+config TIMERFD
+ bool "Enable timerfd() system call" if EMBEDDED
+ depends on ANON_INODES
+ default y
+ help
+ Enable the timerfd() system call that allows to receive timer
+ events on a file descriptor.
+
+ If unsure, say Y.
+
+config EVENTFD
+ bool "Enable eventfd() system call" if EMBEDDED
+ depends on ANON_INODES
+ default y
+ help
+ Enable the eventfd() system call that allows to receive both
+ kernel notification (ie. KAIO) or userspace notifications.
+
+ If unsure, say Y.
+
config SHMEM
bool "Use full shmem filesystem" if EMBEDDED
default y
diff --git a/init/main.c b/init/main.c
index e8d080c..1940fa7 100644
--- a/init/main.c
+++ b/init/main.c
@@ -801,6 +801,7 @@
*/
init_pid_ns.child_reaper = current;
+ __set_special_pids(1, 1);
cad_pid = task_pid(current);
smp_prepare_cpus(max_cpus);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index d17821d..fab5707 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -681,6 +681,7 @@
if (oflag & O_CREAT) {
if (dentry->d_inode) { /* entry already exists */
+ audit_inode(name, dentry->d_inode);
error = -EEXIST;
if (oflag & O_EXCL)
goto out;
@@ -693,6 +694,7 @@
error = -ENOENT;
if (!dentry->d_inode)
goto out;
+ audit_inode(name, dentry->d_inode);
filp = do_open(dentry, oflag);
}
@@ -840,6 +842,7 @@
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
+ audit_inode(NULL, inode);
if (unlikely(!(filp->f_mode & FMODE_WRITE)))
goto out_fput;
@@ -923,6 +926,7 @@
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
+ audit_inode(NULL, inode);
if (unlikely(!(filp->f_mode & FMODE_READ)))
goto out_fput;
diff --git a/kernel/audit.h b/kernel/audit.h
index a337023..815d6f5 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -83,6 +83,7 @@
u32 field_count;
char *filterkey; /* ties events to rules */
struct audit_field *fields;
+ struct audit_field *arch_f; /* quick access to arch field */
struct audit_field *inode_f; /* quick access to an inode field */
struct audit_watch *watch; /* associated watch */
struct list_head rlist; /* entry in audit_watch.rules list */
@@ -131,17 +132,19 @@
extern int selinux_audit_rule_update(void);
#ifdef CONFIG_AUDITSYSCALL
-extern void __audit_signal_info(int sig, struct task_struct *t);
-static inline void audit_signal_info(int sig, struct task_struct *t)
+extern int __audit_signal_info(int sig, struct task_struct *t);
+static inline int audit_signal_info(int sig, struct task_struct *t)
{
- if (unlikely(audit_pid && t->tgid == audit_pid))
- __audit_signal_info(sig, t);
+ if (unlikely((audit_pid && t->tgid == audit_pid) ||
+ (audit_signals && !audit_dummy_context())))
+ return __audit_signal_info(sig, t);
+ return 0;
}
extern enum audit_state audit_filter_inodes(struct task_struct *,
struct audit_context *);
extern void audit_set_auditable(struct audit_context *);
#else
-#define audit_signal_info(s,t)
+#define audit_signal_info(s,t) AUDIT_DISABLED
#define audit_filter_inodes(t,c) AUDIT_DISABLED
#define audit_set_auditable(c)
#endif
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 3749193..6c61263 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -311,6 +311,43 @@
return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);
}
+static inline int audit_match_class_bits(int class, u32 *mask)
+{
+ int i;
+
+ if (classes[class]) {
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+ if (mask[i] & classes[class][i])
+ return 0;
+ }
+ return 1;
+}
+
+static int audit_match_signal(struct audit_entry *entry)
+{
+ struct audit_field *arch = entry->rule.arch_f;
+
+ if (!arch) {
+ /* When arch is unspecified, we must check both masks on biarch
+ * as syscall number alone is ambiguous. */
+ return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
+ entry->rule.mask) &&
+ audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
+ entry->rule.mask));
+ }
+
+ switch(audit_classify_arch(arch->val)) {
+ case 0: /* native */
+ return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
+ entry->rule.mask));
+ case 1: /* 32bit on biarch */
+ return (audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
+ entry->rule.mask));
+ default:
+ return 1;
+ }
+}
+
/* Common user-space to kernel rule translation. */
static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
{
@@ -429,6 +466,7 @@
err = -EINVAL;
goto exit_free;
}
+ entry->rule.arch_f = f;
break;
case AUDIT_PERM:
if (f->val & ~15)
@@ -519,7 +557,6 @@
case AUDIT_FSGID:
case AUDIT_LOGINUID:
case AUDIT_PERS:
- case AUDIT_ARCH:
case AUDIT_MSGTYPE:
case AUDIT_PPID:
case AUDIT_DEVMAJOR:
@@ -531,6 +568,9 @@
case AUDIT_ARG2:
case AUDIT_ARG3:
break;
+ case AUDIT_ARCH:
+ entry->rule.arch_f = f;
+ break;
case AUDIT_SUBJ_USER:
case AUDIT_SUBJ_ROLE:
case AUDIT_SUBJ_TYPE:
@@ -1221,6 +1261,9 @@
#ifdef CONFIG_AUDITSYSCALL
if (!dont_count)
audit_n_rules++;
+
+ if (!audit_match_signal(entry))
+ audit_signals++;
#endif
mutex_unlock(&audit_filter_mutex);
@@ -1294,6 +1337,9 @@
#ifdef CONFIG_AUDITSYSCALL
if (!dont_count)
audit_n_rules--;
+
+ if (!audit_match_signal(entry))
+ audit_signals--;
#endif
mutex_unlock(&audit_filter_mutex);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 628c7ac..e36481e 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -78,17 +78,15 @@
* for saving names from getname(). */
#define AUDIT_NAMES 20
-/* AUDIT_NAMES_RESERVED is the number of slots we reserve in the
- * audit_context from being used for nameless inodes from
- * path_lookup. */
-#define AUDIT_NAMES_RESERVED 7
-
/* Indicates that audit should log the full pathname. */
#define AUDIT_NAME_FULL -1
/* number of audit rules */
int audit_n_rules;
+/* determines whether we collect data for signals sent */
+int audit_signals;
+
/* When fs/namei.c:getname() is called, we store the pointer in name and
* we don't let putname() free it (instead we free all of the saved
* pointers at syscall exit time).
@@ -114,6 +112,9 @@
#define AUDIT_AUX_IPCPERM 0
+/* Number of target pids per aux struct. */
+#define AUDIT_AUX_PIDS 16
+
struct audit_aux_data_mq_open {
struct audit_aux_data d;
int oflag;
@@ -181,6 +182,13 @@
struct vfsmount *mnt;
};
+struct audit_aux_data_pids {
+ struct audit_aux_data d;
+ pid_t target_pid[AUDIT_AUX_PIDS];
+ u32 target_sid[AUDIT_AUX_PIDS];
+ int pid_count;
+};
+
/* The per-task audit context. */
struct audit_context {
int dummy; /* must be the first element */
@@ -201,6 +209,7 @@
struct vfsmount * pwdmnt;
struct audit_context *previous; /* For nested syscalls */
struct audit_aux_data *aux;
+ struct audit_aux_data *aux_pids;
/* Save things to print about task_struct */
pid_t pid, ppid;
@@ -209,6 +218,9 @@
unsigned long personality;
int arch;
+ pid_t target_pid;
+ u32 target_sid;
+
#if AUDIT_DEBUG
int put_count;
int ino_count;
@@ -654,6 +666,10 @@
context->aux = aux->next;
kfree(aux);
}
+ while ((aux = context->aux_pids)) {
+ context->aux_pids = aux->next;
+ kfree(aux);
+ }
}
static inline void audit_zero_context(struct audit_context *context,
@@ -795,6 +811,29 @@
audit_log_task_context(ab);
}
+static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+ u32 sid)
+{
+ struct audit_buffer *ab;
+ char *s = NULL;
+ u32 len;
+ int rc = 0;
+
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
+ if (!ab)
+ return 1;
+
+ if (selinux_sid_to_string(sid, &s, &len)) {
+ audit_log_format(ab, "opid=%d obj=(none)", pid);
+ rc = 1;
+ } else
+ audit_log_format(ab, "opid=%d obj=%s", pid, s);
+ audit_log_end(ab);
+ kfree(s);
+
+ return rc;
+}
+
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{
int i, call_panic = 0;
@@ -973,6 +1012,21 @@
audit_log_end(ab);
}
+ for (aux = context->aux_pids; aux; aux = aux->next) {
+ struct audit_aux_data_pids *axs = (void *)aux;
+ int i;
+
+ for (i = 0; i < axs->pid_count; i++)
+ if (audit_log_pid_context(context, axs->target_pid[i],
+ axs->target_sid[i]))
+ call_panic = 1;
+ }
+
+ if (context->target_pid &&
+ audit_log_pid_context(context, context->target_pid,
+ context->target_sid))
+ call_panic = 1;
+
if (context->pwd && context->pwdmnt) {
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
if (ab) {
@@ -1193,6 +1247,10 @@
} else {
audit_free_names(context);
audit_free_aux(context);
+ context->aux = NULL;
+ context->aux_pids = NULL;
+ context->target_pid = 0;
+ context->target_sid = 0;
kfree(context->filterkey);
context->filterkey = NULL;
tsk->audit_context = context;
@@ -1226,6 +1284,7 @@
context->names[context->name_count].name_len = AUDIT_NAME_FULL;
context->names[context->name_count].name_put = 1;
context->names[context->name_count].ino = (unsigned long)-1;
+ context->names[context->name_count].osid = 0;
++context->name_count;
if (!context->pwd) {
read_lock(¤t->fs->lock);
@@ -1279,6 +1338,28 @@
#endif
}
+static int audit_inc_name_count(struct audit_context *context,
+ const struct inode *inode)
+{
+ if (context->name_count >= AUDIT_NAMES) {
+ if (inode)
+ printk(KERN_DEBUG "name_count maxed, losing inode data: "
+ "dev=%02x:%02x, inode=%lu",
+ MAJOR(inode->i_sb->s_dev),
+ MINOR(inode->i_sb->s_dev),
+ inode->i_ino);
+
+ else
+ printk(KERN_DEBUG "name_count maxed, losing inode data");
+ return 1;
+ }
+ context->name_count++;
+#if AUDIT_DEBUG
+ context->ino_count++;
+#endif
+ return 0;
+}
+
/* Copy inode data into an audit_names. */
static void audit_copy_inode(struct audit_names *name, const struct inode *inode)
{
@@ -1316,13 +1397,10 @@
else {
/* FIXME: how much do we care about inodes that have no
* associated name? */
- if (context->name_count >= AUDIT_NAMES - AUDIT_NAMES_RESERVED)
+ if (audit_inc_name_count(context, inode))
return;
- idx = context->name_count++;
+ idx = context->name_count - 1;
context->names[idx].name = NULL;
-#if AUDIT_DEBUG
- ++context->ino_count;
-#endif
}
audit_copy_inode(&context->names[idx], inode);
}
@@ -1346,7 +1424,7 @@
{
int idx;
struct audit_context *context = current->audit_context;
- const char *found_name = NULL;
+ const char *found_parent = NULL, *found_child = NULL;
int dirlen = 0;
if (!context->in_syscall)
@@ -1354,88 +1432,73 @@
/* determine matching parent */
if (!dname)
- goto update_context;
- for (idx = 0; idx < context->name_count; idx++)
- if (context->names[idx].ino == parent->i_ino) {
- const char *name = context->names[idx].name;
+ goto add_names;
- if (!name)
- continue;
+ /* parent is more likely, look for it first */
+ for (idx = 0; idx < context->name_count; idx++) {
+ struct audit_names *n = &context->names[idx];
- if (audit_compare_dname_path(dname, name, &dirlen) == 0) {
- context->names[idx].name_len = dirlen;
- found_name = name;
- break;
- }
+ if (!n->name)
+ continue;
+
+ if (n->ino == parent->i_ino &&
+ !audit_compare_dname_path(dname, n->name, &dirlen)) {
+ n->name_len = dirlen; /* update parent data in place */
+ found_parent = n->name;
+ goto add_names;
}
-
-update_context:
- idx = context->name_count;
- if (context->name_count == AUDIT_NAMES) {
- printk(KERN_DEBUG "name_count maxed and losing %s\n",
- found_name ?: "(null)");
- return;
}
- context->name_count++;
-#if AUDIT_DEBUG
- context->ino_count++;
-#endif
- /* Re-use the name belonging to the slot for a matching parent directory.
- * All names for this context are relinquished in audit_free_names() */
- context->names[idx].name = found_name;
- context->names[idx].name_len = AUDIT_NAME_FULL;
- context->names[idx].name_put = 0; /* don't call __putname() */
- if (!inode)
- context->names[idx].ino = (unsigned long)-1;
- else
- audit_copy_inode(&context->names[idx], inode);
+ /* no matching parent, look for matching child */
+ for (idx = 0; idx < context->name_count; idx++) {
+ struct audit_names *n = &context->names[idx];
- /* A parent was not found in audit_names, so copy the inode data for the
- * provided parent. */
- if (!found_name) {
- idx = context->name_count;
- if (context->name_count == AUDIT_NAMES) {
- printk(KERN_DEBUG
- "name_count maxed and losing parent inode data: dev=%02x:%02x, inode=%lu",
- MAJOR(parent->i_sb->s_dev),
- MINOR(parent->i_sb->s_dev),
- parent->i_ino);
- return;
+ if (!n->name)
+ continue;
+
+ /* strcmp() is the more likely scenario */
+ if (!strcmp(dname, n->name) ||
+ !audit_compare_dname_path(dname, n->name, &dirlen)) {
+ if (inode)
+ audit_copy_inode(n, inode);
+ else
+ n->ino = (unsigned long)-1;
+ found_child = n->name;
+ goto add_names;
}
- context->name_count++;
-#if AUDIT_DEBUG
- context->ino_count++;
-#endif
+ }
+
+add_names:
+ if (!found_parent) {
+ if (audit_inc_name_count(context, parent))
+ return;
+ idx = context->name_count - 1;
+ context->names[idx].name = NULL;
audit_copy_inode(&context->names[idx], parent);
}
-}
-/**
- * audit_inode_update - update inode info for last collected name
- * @inode: inode being audited
- *
- * When open() is called on an existing object with the O_CREAT flag, the inode
- * data audit initially collects is incorrect. This additional hook ensures
- * audit has the inode data for the actual object to be opened.
- */
-void __audit_inode_update(const struct inode *inode)
-{
- struct audit_context *context = current->audit_context;
- int idx;
+ if (!found_child) {
+ if (audit_inc_name_count(context, inode))
+ return;
+ idx = context->name_count - 1;
- if (!context->in_syscall || !inode)
- return;
+ /* Re-use the name belonging to the slot for a matching parent
+ * directory. All names for this context are relinquished in
+ * audit_free_names() */
+ if (found_parent) {
+ context->names[idx].name = found_parent;
+ context->names[idx].name_len = AUDIT_NAME_FULL;
+ /* don't call __putname() */
+ context->names[idx].name_put = 0;
+ } else {
+ context->names[idx].name = NULL;
+ }
- if (context->name_count == 0) {
- context->name_count++;
-#if AUDIT_DEBUG
- context->ino_count++;
-#endif
+ if (inode)
+ audit_copy_inode(&context->names[idx], inode);
+ else
+ context->names[idx].ino = (unsigned long)-1;
}
- idx = context->name_count - 1;
-
- audit_copy_inode(&context->names[idx], inode);
}
/**
@@ -1880,6 +1943,14 @@
return 0;
}
+void __audit_ptrace(struct task_struct *t)
+{
+ struct audit_context *context = current->audit_context;
+
+ context->target_pid = t->pid;
+ selinux_get_task_sid(t, &context->target_sid);
+}
+
/**
* audit_avc_path - record the granting or denial of permissions
* @dentry: dentry to record
@@ -1918,15 +1989,17 @@
* If the audit subsystem is being terminated, record the task (pid)
* and uid that is doing that.
*/
-void __audit_signal_info(int sig, struct task_struct *t)
+int __audit_signal_info(int sig, struct task_struct *t)
{
+ struct audit_aux_data_pids *axp;
+ struct task_struct *tsk = current;
+ struct audit_context *ctx = tsk->audit_context;
extern pid_t audit_sig_pid;
extern uid_t audit_sig_uid;
extern u32 audit_sig_sid;
- if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
- struct task_struct *tsk = current;
- struct audit_context *ctx = tsk->audit_context;
+ if (audit_pid && t->tgid == audit_pid &&
+ (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) {
audit_sig_pid = tsk->pid;
if (ctx)
audit_sig_uid = ctx->loginuid;
@@ -1934,4 +2007,72 @@
audit_sig_uid = tsk->uid;
selinux_get_task_sid(tsk, &audit_sig_sid);
}
+
+ if (!audit_signals) /* audit_context checked in wrapper */
+ return 0;
+
+ /* optimize the common case by putting first signal recipient directly
+ * in audit_context */
+ if (!ctx->target_pid) {
+ ctx->target_pid = t->tgid;
+ selinux_get_task_sid(t, &ctx->target_sid);
+ return 0;
+ }
+
+ axp = (void *)ctx->aux_pids;
+ if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
+ axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
+ if (!axp)
+ return -ENOMEM;
+
+ axp->d.type = AUDIT_OBJ_PID;
+ axp->d.next = ctx->aux_pids;
+ ctx->aux_pids = (void *)axp;
+ }
+ BUG_ON(axp->pid_count > AUDIT_AUX_PIDS);
+
+ axp->target_pid[axp->pid_count] = t->tgid;
+ selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
+ axp->pid_count++;
+
+ return 0;
+}
+
+/**
+ * audit_core_dumps - record information about processes that end abnormally
+ * @sig: signal value
+ *
+ * If a process ends with a core dump, something fishy is going on and we
+ * should record the event for investigation.
+ */
+void audit_core_dumps(long signr)
+{
+ struct audit_buffer *ab;
+ u32 sid;
+
+ if (!audit_enabled)
+ return;
+
+ if (signr == SIGQUIT) /* don't care for those */
+ return;
+
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+ audit_log_format(ab, "auid=%u uid=%u gid=%u",
+ audit_get_loginuid(current->audit_context),
+ current->uid, current->gid);
+ selinux_get_task_sid(current, &sid);
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+
+ if (selinux_sid_to_string(sid, &ctx, &len))
+ audit_log_format(ab, " ssid=%u", sid);
+ else
+ audit_log_format(ab, " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " pid=%d comm=", current->pid);
+ audit_log_untrustedstring(ab, current->comm);
+ audit_log_format(ab, " sig=%ld", signr);
+ audit_log_end(ab);
}
diff --git a/kernel/compat.c b/kernel/compat.c
index cebb4c2..3bae374 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -475,8 +475,8 @@
return min_length;
}
-static int get_compat_itimerspec(struct itimerspec *dst,
- struct compat_itimerspec __user *src)
+int get_compat_itimerspec(struct itimerspec *dst,
+ const struct compat_itimerspec __user *src)
{
if (get_compat_timespec(&dst->it_interval, &src->it_interval) ||
get_compat_timespec(&dst->it_value, &src->it_value))
@@ -484,8 +484,8 @@
return 0;
}
-static int put_compat_itimerspec(struct compat_itimerspec __user *dst,
- struct itimerspec *src)
+int put_compat_itimerspec(struct compat_itimerspec __user *dst,
+ const struct itimerspec *src)
{
if (put_compat_timespec(&src->it_interval, &dst->it_interval) ||
put_compat_timespec(&src->it_value, &dst->it_value))
diff --git a/kernel/exit.c b/kernel/exit.c
index b0c6f0c..c6d14b8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -24,6 +24,7 @@
#include <linux/pid_namespace.h>
#include <linux/ptrace.h>
#include <linux/profile.h>
+#include <linux/signalfd.h>
#include <linux/mount.h>
#include <linux/proc_fs.h>
#include <linux/kthread.h>
@@ -42,6 +43,7 @@
#include <linux/audit.h> /* for audit_free() */
#include <linux/resource.h>
#include <linux/blkdev.h>
+#include <linux/task_io_accounting_ops.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -82,6 +84,14 @@
sighand = rcu_dereference(tsk->sighand);
spin_lock(&sighand->siglock);
+ /*
+ * Notify that this sighand has been detached. This must
+ * be called with the tsk->sighand lock held. Also, this
+ * access tsk->sighand internally, so it must be called
+ * before tsk->sighand is reset.
+ */
+ signalfd_detach_locked(tsk);
+
posix_cpu_timers_exit(tsk);
if (atomic_dec_and_test(&sig->count))
posix_cpu_timers_exit_group(tsk);
@@ -113,6 +123,8 @@
sig->nvcsw += tsk->nvcsw;
sig->nivcsw += tsk->nivcsw;
sig->sched_time += tsk->sched_time;
+ sig->inblock += task_io_get_inblock(tsk);
+ sig->oublock += task_io_get_oublock(tsk);
sig = NULL; /* Marker for below. */
}
@@ -299,12 +311,12 @@
if (process_session(curr) != session) {
detach_pid(curr, PIDTYPE_SID);
set_signal_session(curr->signal, session);
- attach_pid(curr, PIDTYPE_SID, session);
+ attach_pid(curr, PIDTYPE_SID, find_pid(session));
}
if (process_group(curr) != pgrp) {
detach_pid(curr, PIDTYPE_PGID);
curr->signal->pgrp = pgrp;
- attach_pid(curr, PIDTYPE_PGID, pgrp);
+ attach_pid(curr, PIDTYPE_PGID, find_pid(pgrp));
}
}
@@ -1193,6 +1205,12 @@
p->nvcsw + sig->nvcsw + sig->cnvcsw;
psig->cnivcsw +=
p->nivcsw + sig->nivcsw + sig->cnivcsw;
+ psig->cinblock +=
+ task_io_get_inblock(p) +
+ sig->inblock + sig->cinblock;
+ psig->coublock +=
+ task_io_get_oublock(p) +
+ sig->oublock + sig->coublock;
spin_unlock_irq(&p->parent->sighand->siglock);
}
diff --git a/kernel/fork.c b/kernel/fork.c
index 5dd3979..49530e4 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -875,6 +875,7 @@
sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
+ sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
sig->sched_time = 0;
INIT_LIST_HEAD(&sig->cpu_timers[0]);
INIT_LIST_HEAD(&sig->cpu_timers[1]);
@@ -955,7 +956,7 @@
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr,
- int pid)
+ struct pid *pid)
{
int retval;
struct task_struct *p = NULL;
@@ -1022,7 +1023,7 @@
p->did_exec = 0;
delayacct_tsk_init(p); /* Must remain after dup_task_struct() */
copy_flags(clone_flags, p);
- p->pid = pid;
+ p->pid = pid_nr(pid);
retval = -EFAULT;
if (clone_flags & CLONE_PARENT_SETTID)
if (put_user(p->pid, parent_tidptr))
@@ -1251,13 +1252,13 @@
p->signal->tty = current->signal->tty;
p->signal->pgrp = process_group(current);
set_signal_session(p->signal, process_session(current));
- attach_pid(p, PIDTYPE_PGID, process_group(p));
- attach_pid(p, PIDTYPE_SID, process_session(p));
+ attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
+ attach_pid(p, PIDTYPE_SID, task_session(current));
list_add_tail_rcu(&p->tasks, &init_task.tasks);
__get_cpu_var(process_counts)++;
}
- attach_pid(p, PIDTYPE_PID, p->pid);
+ attach_pid(p, PIDTYPE_PID, pid);
nr_threads++;
}
@@ -1321,7 +1322,8 @@
struct task_struct *task;
struct pt_regs regs;
- task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, NULL, 0);
+ task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, NULL,
+ &init_struct_pid);
if (!IS_ERR(task))
init_idle(task, cpu);
@@ -1371,7 +1373,7 @@
clone_flags |= CLONE_PTRACE;
}
- p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr);
+ p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
@@ -1420,12 +1422,15 @@
#define ARCH_MIN_MMSTRUCT_ALIGN 0
#endif
-static void sighand_ctor(void *data, struct kmem_cache *cachep, unsigned long flags)
+static void sighand_ctor(void *data, struct kmem_cache *cachep,
+ unsigned long flags)
{
struct sighand_struct *sighand = data;
- if (flags & SLAB_CTOR_CONSTRUCTOR)
+ if (flags & SLAB_CTOR_CONSTRUCTOR) {
spin_lock_init(&sighand->siglock);
+ INIT_LIST_HEAD(&sighand->signalfd_list);
+ }
}
void __init proc_caches_init(void)
@@ -1451,7 +1456,6 @@
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
}
-
/*
* Check constraints on flags passed to the unshare system call and
* force unsharing of additional process context as appropriate.
diff --git a/kernel/pid.c b/kernel/pid.c
index d3ad724..eb66bd2 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -27,11 +27,13 @@
#include <linux/bootmem.h>
#include <linux/hash.h>
#include <linux/pid_namespace.h>
+#include <linux/init_task.h>
#define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
static struct hlist_head *pid_hash;
static int pidhash_shift;
static struct kmem_cache *pid_cachep;
+struct pid init_struct_pid = INIT_STRUCT_PID;
int pid_max = PID_MAX_DEFAULT;
@@ -247,13 +249,16 @@
}
EXPORT_SYMBOL_GPL(find_pid);
-int fastcall attach_pid(struct task_struct *task, enum pid_type type, int nr)
+/*
+ * attach_pid() must be called with the tasklist_lock write-held.
+ */
+int fastcall attach_pid(struct task_struct *task, enum pid_type type,
+ struct pid *pid)
{
struct pid_link *link;
- struct pid *pid;
link = &task->pids[type];
- link->pid = pid = find_pid(nr);
+ link->pid = pid;
hlist_add_head_rcu(&link->node, &pid->tasks[type]);
return 0;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4d50e06..ad7949a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -18,6 +18,7 @@
#include <linux/ptrace.h>
#include <linux/security.h>
#include <linux/signal.h>
+#include <linux/audit.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -161,6 +162,8 @@
{
int retval;
+ audit_ptrace(task);
+
retval = -EPERM;
if (task->pid <= 1)
goto out;
diff --git a/kernel/signal.c b/kernel/signal.c
index 2ac3a66..364fc95 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -21,6 +21,7 @@
#include <linux/syscalls.h>
#include <linux/ptrace.h>
#include <linux/signal.h>
+#include <linux/signalfd.h>
#include <linux/capability.h>
#include <linux/freezer.h>
#include <linux/pid_namespace.h>
@@ -113,8 +114,7 @@
/* Given the mask, find the first available signal that should be serviced. */
-static int
-next_signal(struct sigpending *pending, sigset_t *mask)
+int next_signal(struct sigpending *pending, sigset_t *mask)
{
unsigned long i, *s, *m, x;
int sig = 0;
@@ -497,6 +497,11 @@
int error = -EINVAL;
if (!valid_signal(sig))
return error;
+
+ error = audit_signal_info(sig, t); /* Let audit system see the signal */
+ if (error)
+ return error;
+
error = -EPERM;
if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
&& ((sig != SIGCONT) ||
@@ -506,10 +511,7 @@
&& !capable(CAP_KILL))
return error;
- error = security_task_kill(t, info, sig, 0);
- if (!error)
- audit_signal_info(sig, t); /* Let audit system see the signal */
- return error;
+ return security_task_kill(t, info, sig, 0);
}
/* forward decl */
@@ -630,6 +632,12 @@
int ret = 0;
/*
+ * Deliver the signal to listening signalfds. This must be called
+ * with the sighand lock held.
+ */
+ signalfd_notify(t, sig);
+
+ /*
* fast-pathed signals for kernel-internal things like SIGSTOP
* or SIGKILL.
*/
@@ -1280,6 +1288,11 @@
ret = 1;
goto out;
}
+ /*
+ * Deliver the signal to listening signalfds. This must be called
+ * with the sighand lock held.
+ */
+ signalfd_notify(p, sig);
list_add_tail(&q->list, &p->pending.list);
sigaddset(&p->pending.signal, sig);
@@ -1323,6 +1336,11 @@
q->info.si_overrun++;
goto out;
}
+ /*
+ * Deliver the signal to listening signalfds. This must be called
+ * with the sighand lock held.
+ */
+ signalfd_notify(p, sig);
/*
* Put this signal on the shared-pending queue.
@@ -1983,6 +2001,8 @@
/*
* If you change siginfo_t structure, please be sure
* this code is fixed accordingly.
+ * Please remember to update the signalfd_copyinfo() function
+ * inside fs/signalfd.c too, in case siginfo_t changes.
* It should never copy any pad contained in the structure
* to avoid security leaks, but must copy the generic
* 3 ints plus the relevant union member.
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index daabb74..fcee2a8 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -8,6 +8,8 @@
#include <linux/sched.h>
#include <linux/stop_machine.h>
#include <linux/syscalls.h>
+#include <linux/interrupt.h>
+
#include <asm/atomic.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -45,6 +47,7 @@
if (stopmachine_state == STOPMACHINE_DISABLE_IRQ
&& !irqs_disabled) {
local_irq_disable();
+ hard_irq_disable();
irqs_disabled = 1;
/* Ack: irqs disabled. */
smp_mb(); /* Must read state first. */
@@ -124,6 +127,7 @@
/* Make them disable irqs. */
local_irq_disable();
+ hard_irq_disable();
stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);
return 0;
diff --git a/kernel/sys.c b/kernel/sys.c
index cdb7e94..872271c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -14,6 +14,7 @@
#include <linux/prctl.h>
#include <linux/highuid.h>
#include <linux/fs.h>
+#include <linux/resource.h>
#include <linux/kernel.h>
#include <linux/kexec.h>
#include <linux/workqueue.h>
@@ -29,6 +30,7 @@
#include <linux/signal.h>
#include <linux/cn_proc.h>
#include <linux/getcpu.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
@@ -658,7 +660,7 @@
int error = -EINVAL;
struct pid *pgrp;
- if (which > 2 || which < 0)
+ if (which > PRIO_USER || which < PRIO_PROCESS)
goto out;
/* normalize: avoid signed division (rounding problems) */
@@ -722,7 +724,7 @@
long niceval, retval = -ESRCH;
struct pid *pgrp;
- if (which > 2 || which < 0)
+ if (which > PRIO_USER || which < PRIO_PROCESS)
return -EINVAL;
read_lock(&tasklist_lock);
@@ -1486,7 +1488,7 @@
if (process_group(p) != pgid) {
detach_pid(p, PIDTYPE_PGID);
p->signal->pgrp = pgid;
- attach_pid(p, PIDTYPE_PGID, pgid);
+ attach_pid(p, PIDTYPE_PGID, find_pid(pgid));
}
err = 0;
@@ -2082,6 +2084,8 @@
r->ru_nivcsw = p->signal->cnivcsw;
r->ru_minflt = p->signal->cmin_flt;
r->ru_majflt = p->signal->cmaj_flt;
+ r->ru_inblock = p->signal->cinblock;
+ r->ru_oublock = p->signal->coublock;
if (who == RUSAGE_CHILDREN)
break;
@@ -2093,6 +2097,8 @@
r->ru_nivcsw += p->signal->nivcsw;
r->ru_minflt += p->signal->min_flt;
r->ru_majflt += p->signal->maj_flt;
+ r->ru_inblock += p->signal->inblock;
+ r->ru_oublock += p->signal->oublock;
t = p;
do {
utime = cputime_add(utime, t->utime);
@@ -2101,6 +2107,8 @@
r->ru_nivcsw += t->nivcsw;
r->ru_minflt += t->min_flt;
r->ru_majflt += t->maj_flt;
+ r->ru_inblock += task_io_get_inblock(t);
+ r->ru_oublock += task_io_get_oublock(t);
t = next_thread(t);
} while (t != p);
break;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index d7306d0..b6d77a8 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -141,3 +141,8 @@
cond_syscall(sys_bdflush);
cond_syscall(sys_ioprio_set);
cond_syscall(sys_ioprio_get);
+
+/* New file descriptors */
+cond_syscall(sys_signalfd);
+cond_syscall(sys_timerfd);
+cond_syscall(sys_eventfd);
diff --git a/lib/Makefile b/lib/Makefile
index 1f65b46..c8c8e20 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -13,7 +13,7 @@
lib-y += kobject.o kref.o kobject_uevent.o klist.o
obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
- bust_spinlocks.o
+ bust_spinlocks.o hexdump.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/audit.c b/lib/audit.c
index 3b1289f..8e7dc1c 100644
--- a/lib/audit.c
+++ b/lib/audit.c
@@ -23,6 +23,16 @@
~0U
};
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+ return 0;
+}
+
int audit_classify_syscall(int abi, unsigned syscall)
{
switch(syscall) {
@@ -49,6 +59,7 @@
audit_register_class(AUDIT_CLASS_READ, read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+ audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
return 0;
}
diff --git a/lib/hexdump.c b/lib/hexdump.c
new file mode 100644
index 0000000..e6da5b7
--- /dev/null
+++ b/lib/hexdump.c
@@ -0,0 +1,104 @@
+/*
+ * lib/hexdump.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+/**
+ * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @linebuf: where to put the converted data
+ * @linebuflen: total size of @linebuf, including space for terminating NUL
+ *
+ * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
+ * 16 bytes of input data converted to hex + ASCII output.
+ *
+ * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
+ * to a hex + ASCII dump at the supplied memory location.
+ * The converted output is always NUL-terminated.
+ *
+ * E.g.:
+ * hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf));
+ *
+ * example output buffer:
+ * 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
+ */
+void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
+ size_t linebuflen)
+{
+ const u8 *ptr = buf;
+ u8 ch;
+ int j, lx = 0;
+
+ for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) {
+ if (j && !(j % 4))
+ linebuf[lx++] = ' ';
+ ch = ptr[j];
+ linebuf[lx++] = hex_asc(ch >> 4);
+ linebuf[lx++] = hex_asc(ch & 0x0f);
+ }
+ if ((lx + 2) < linebuflen) {
+ linebuf[lx++] = ' ';
+ linebuf[lx++] = ' ';
+ }
+ for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++)
+ linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
+ linebuf[lx++] = '\0';
+}
+EXPORT_SYMBOL(hex_dump_to_buffer);
+
+/**
+ * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
+ * to the kernel log at the specified kernel log level, with an optional
+ * leading prefix.
+ *
+ * E.g.:
+ * print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET:
+ * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS:
+ * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrstuvwxyz{|}~.
+ */
+void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
+{
+ u8 *ptr = buf;
+ int i, linelen, remaining = len;
+ unsigned char linebuf[100];
+
+ for (i = 0; i < len; i += 16) {
+ linelen = min(remaining, 16);
+ remaining -= 16;
+ hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf));
+
+ switch (prefix_type) {
+ case DUMP_PREFIX_ADDRESS:
+ printk("%s%*p: %s\n", level,
+ (int)(2 * sizeof(void *)), ptr + i, linebuf);
+ break;
+ case DUMP_PREFIX_OFFSET:
+ printk("%s%.8x: %s\n", level, i, linebuf);
+ break;
+ default:
+ printk("%s%s\n", level, linebuf);
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL(print_hex_dump);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 63cd888..eec1481 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -588,31 +588,27 @@
}
/**
- * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them.
+ * write_cache_pages - walk the list of dirty pages of the given address space and write all of them.
* @mapping: address space structure to write
* @wbc: subtract the number of written pages from *@wbc->nr_to_write
+ * @writepage: function called for each page
+ * @data: data passed to writepage function
*
- * This is a library function, which implements the writepages()
- * address_space_operation.
- *
- * If a page is already under I/O, generic_writepages() skips it, even
+ * If a page is already under I/O, write_cache_pages() skips it, even
* if it's dirty. This is desirable behaviour for memory-cleaning writeback,
* but it is INCORRECT for data-integrity system calls such as fsync(). fsync()
* and msync() need to guarantee that all the data which was dirty at the time
* the call was made get new I/O started against them. If wbc->sync_mode is
* WB_SYNC_ALL then we were called for data integrity and we must wait for
* existing IO to complete.
- *
- * Derived from mpage_writepages() - if you fix this you should check that
- * also!
*/
-int generic_writepages(struct address_space *mapping,
- struct writeback_control *wbc)
+int write_cache_pages(struct address_space *mapping,
+ struct writeback_control *wbc, writepage_t writepage,
+ void *data)
{
struct backing_dev_info *bdi = mapping->backing_dev_info;
int ret = 0;
int done = 0;
- int (*writepage)(struct page *page, struct writeback_control *wbc);
struct pagevec pvec;
int nr_pages;
pgoff_t index;
@@ -625,12 +621,6 @@
return 0;
}
- writepage = mapping->a_ops->writepage;
-
- /* deal with chardevs and other special file */
- if (!writepage)
- return 0;
-
pagevec_init(&pvec, 0);
if (wbc->range_cyclic) {
index = mapping->writeback_index; /* Start from prev offset */
@@ -682,8 +672,7 @@
continue;
}
- ret = (*writepage)(page, wbc);
- mapping_set_error(mapping, ret);
+ ret = (*writepage)(page, wbc, data);
if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
unlock_page(page);
@@ -710,6 +699,38 @@
mapping->writeback_index = index;
return ret;
}
+EXPORT_SYMBOL(write_cache_pages);
+
+/*
+ * Function used by generic_writepages to call the real writepage
+ * function and set the mapping flags on error
+ */
+static int __writepage(struct page *page, struct writeback_control *wbc,
+ void *data)
+{
+ struct address_space *mapping = data;
+ int ret = mapping->a_ops->writepage(page, wbc);
+ mapping_set_error(mapping, ret);
+ return ret;
+}
+
+/**
+ * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them.
+ * @mapping: address space structure to write
+ * @wbc: subtract the number of written pages from *@wbc->nr_to_write
+ *
+ * This is a library function, which implements the writepages()
+ * address_space_operation.
+ */
+int generic_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+{
+ /* deal with chardevs and other special file */
+ if (!mapping->a_ops->writepage)
+ return 0;
+
+ return write_cache_pages(mapping, wbc, __writepage, mapping);
+}
EXPORT_SYMBOL(generic_writepages);
diff --git a/mm/thrash.c b/mm/thrash.c
index 9ef9071..c4c5205 100644
--- a/mm/thrash.c
+++ b/mm/thrash.c
@@ -48,9 +48,8 @@
if (current_interval < current->mm->last_interval)
current->mm->token_priority++;
else {
- current->mm->token_priority--;
- if (unlikely(current->mm->token_priority < 0))
- current->mm->token_priority = 0;
+ if (likely(current->mm->token_priority > 0))
+ current->mm->token_priority--;
}
/* Check if we deserve the token */
if (current->mm->token_priority >
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 9832d9a..8faf27e 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -698,7 +698,7 @@
{
struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu);
- INIT_DELAYED_WORK(vmstat_work, vmstat_update);
+ INIT_DELAYED_WORK_DEFERRABLE(vmstat_work, vmstat_update);
schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu);
}
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index d342e89..ceadfcf 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -174,7 +174,7 @@
static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
- struct hid_device *hid = dev->private;
+ struct hid_device *hid = input_get_drvdata(dev);
struct hidp_session *session = hid->driver_data;
return hidp_queue_event(session, dev, type, code, value);
@@ -182,7 +182,7 @@
static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
- struct hidp_session *session = dev->private;
+ struct hidp_session *session = input_get_drvdata(dev);
return hidp_queue_event(session, dev, type, code, value);
}
@@ -630,7 +630,7 @@
struct input_dev *input = session->input;
int i;
- input->private = session;
+ input_set_drvdata(input, session);
input->name = "Bluetooth HID Boot Protocol Device";
@@ -663,7 +663,7 @@
input->relbit[0] |= BIT(REL_WHEEL);
}
- input->cdev.dev = hidp_get_device(session);
+ input->dev.parent = hidp_get_device(session);
input->event = hidp_input_event;
@@ -737,10 +737,8 @@
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
hidp_send_report(session, report);
- if (hidinput_connect(hid) == 0) {
+ if (hidinput_connect(hid) == 0)
hid->claimed |= HID_CLAIMED_INPUT;
- hid_ff_init(hid);
- }
}
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
@@ -864,7 +862,7 @@
if (session->hid)
hid_free_device(session->hid);
- kfree(session->input);
+ input_free_device(session->input);
kfree(session);
return err;
}
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index e3c26a9..a5e372b 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -19,7 +19,6 @@
#include <linux/rtnetlink.h>
#include <linux/jiffies.h>
#include <linux/spinlock.h>
-#include <linux/list.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
@@ -27,8 +26,7 @@
enum lw_bits {
- LW_RUNNING = 0,
- LW_SE_USED
+ LW_URGENT = 0,
};
static unsigned long linkwatch_flags;
@@ -37,17 +35,9 @@
static void linkwatch_event(struct work_struct *dummy);
static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
-static LIST_HEAD(lweventlist);
+static struct net_device *lweventlist;
static DEFINE_SPINLOCK(lweventlist_lock);
-struct lw_event {
- struct list_head list;
- struct net_device *dev;
-};
-
-/* Avoid kmalloc() for most systems */
-static struct lw_event singleevent;
-
static unsigned char default_operstate(const struct net_device *dev)
{
if (!netif_carrier_ok(dev))
@@ -87,25 +77,102 @@
}
-/* Must be called with the rtnl semaphore held */
-void linkwatch_run_queue(void)
+static int linkwatch_urgent_event(struct net_device *dev)
{
- struct list_head head, *n, *next;
+ return netif_running(dev) && netif_carrier_ok(dev) &&
+ dev->qdisc != dev->qdisc_sleeping;
+}
+
+
+static void linkwatch_add_event(struct net_device *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&lweventlist_lock, flags);
+ dev->link_watch_next = lweventlist;
+ lweventlist = dev;
+ spin_unlock_irqrestore(&lweventlist_lock, flags);
+}
+
+
+static void linkwatch_schedule_work(int urgent)
+{
+ unsigned long delay = linkwatch_nextevent - jiffies;
+
+ if (test_bit(LW_URGENT, &linkwatch_flags))
+ return;
+
+ /* Minimise down-time: drop delay for up event. */
+ if (urgent) {
+ if (test_and_set_bit(LW_URGENT, &linkwatch_flags))
+ return;
+ delay = 0;
+ }
+
+ /* If we wrap around we'll delay it by at most HZ. */
+ if (delay > HZ)
+ delay = 0;
+
+ /*
+ * This is true if we've scheduled it immeditately or if we don't
+ * need an immediate execution and it's already pending.
+ */
+ if (schedule_delayed_work(&linkwatch_work, delay) == !delay)
+ return;
+
+ /* Don't bother if there is nothing urgent. */
+ if (!test_bit(LW_URGENT, &linkwatch_flags))
+ return;
+
+ /* It's already running which is good enough. */
+ if (!cancel_delayed_work(&linkwatch_work))
+ return;
+
+ /* Otherwise we reschedule it again for immediate exection. */
+ schedule_delayed_work(&linkwatch_work, 0);
+}
+
+
+static void __linkwatch_run_queue(int urgent_only)
+{
+ struct net_device *next;
+
+ /*
+ * Limit the number of linkwatch events to one
+ * per second so that a runaway driver does not
+ * cause a storm of messages on the netlink
+ * socket. This limit does not apply to up events
+ * while the device qdisc is down.
+ */
+ if (!urgent_only)
+ linkwatch_nextevent = jiffies + HZ;
+ /* Limit wrap-around effect on delay. */
+ else if (time_after(linkwatch_nextevent, jiffies + HZ))
+ linkwatch_nextevent = jiffies;
+
+ clear_bit(LW_URGENT, &linkwatch_flags);
spin_lock_irq(&lweventlist_lock);
- list_replace_init(&lweventlist, &head);
+ next = lweventlist;
+ lweventlist = NULL;
spin_unlock_irq(&lweventlist_lock);
- list_for_each_safe(n, next, &head) {
- struct lw_event *event = list_entry(n, struct lw_event, list);
- struct net_device *dev = event->dev;
+ while (next) {
+ struct net_device *dev = next;
- if (event == &singleevent) {
- clear_bit(LW_SE_USED, &linkwatch_flags);
- } else {
- kfree(event);
+ next = dev->link_watch_next;
+
+ if (urgent_only && !linkwatch_urgent_event(dev)) {
+ linkwatch_add_event(dev);
+ continue;
}
+ /*
+ * Make sure the above read is complete since it can be
+ * rewritten as soon as we clear the bit below.
+ */
+ smp_mb__before_clear_bit();
+
/* We are about to handle this device,
* so new events can be accepted
*/
@@ -124,58 +191,39 @@
dev_put(dev);
}
+
+ if (lweventlist)
+ linkwatch_schedule_work(0);
+}
+
+
+/* Must be called with the rtnl semaphore held */
+void linkwatch_run_queue(void)
+{
+ __linkwatch_run_queue(0);
}
static void linkwatch_event(struct work_struct *dummy)
{
- /* Limit the number of linkwatch events to one
- * per second so that a runaway driver does not
- * cause a storm of messages on the netlink
- * socket
- */
- linkwatch_nextevent = jiffies + HZ;
- clear_bit(LW_RUNNING, &linkwatch_flags);
-
rtnl_lock();
- linkwatch_run_queue();
+ __linkwatch_run_queue(time_after(linkwatch_nextevent, jiffies));
rtnl_unlock();
}
void linkwatch_fire_event(struct net_device *dev)
{
+ int urgent = linkwatch_urgent_event(dev);
+
if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
- unsigned long flags;
- struct lw_event *event;
-
- if (test_and_set_bit(LW_SE_USED, &linkwatch_flags)) {
- event = kmalloc(sizeof(struct lw_event), GFP_ATOMIC);
-
- if (unlikely(event == NULL)) {
- clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
- return;
- }
- } else {
- event = &singleevent;
- }
-
dev_hold(dev);
- event->dev = dev;
- spin_lock_irqsave(&lweventlist_lock, flags);
- list_add_tail(&event->list, &lweventlist);
- spin_unlock_irqrestore(&lweventlist_lock, flags);
+ linkwatch_add_event(dev);
+ } else if (!urgent)
+ return;
- if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
- unsigned long delay = linkwatch_nextevent - jiffies;
-
- /* If we wrap around we'll delay it by at most HZ. */
- if (delay > HZ)
- delay = 0;
- schedule_delayed_work(&linkwatch_work, delay);
- }
- }
+ linkwatch_schedule_work(urgent);
}
EXPORT_SYMBOL(linkwatch_fire_event);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 7edea2a..75c0230 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -15,128 +15,34 @@
#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
(1 << NF_ARP_FORWARD))
-/* Standard entry. */
-struct arpt_standard
-{
- struct arpt_entry entry;
- struct arpt_standard_target target;
-};
-
-struct arpt_error_target
-{
- struct arpt_entry_target target;
- char errorname[ARPT_FUNCTION_MAXNAMELEN];
-};
-
-struct arpt_error
-{
- struct arpt_entry entry;
- struct arpt_error_target target;
-};
-
static struct
{
struct arpt_replace repl;
struct arpt_standard entries[3];
struct arpt_error term;
-} initial_table __initdata
-= { { "filter", FILTER_VALID_HOOKS, 4,
- sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
- { [NF_ARP_IN] = 0,
- [NF_ARP_OUT] = sizeof(struct arpt_standard),
- [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), },
- { [NF_ARP_IN] = 0,
- [NF_ARP_OUT] = sizeof(struct arpt_standard),
- [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), },
- 0, NULL, { } },
- {
- /* ARP_IN */
- {
- {
- {
- { 0 }, { 0 }, { 0 }, { 0 },
- 0, 0,
- { { 0, }, { 0, } },
- { { 0, }, { 0, } },
- 0, 0,
- 0, 0,
- 0, 0,
- "", "", { 0 }, { 0 },
- 0, 0
- },
- sizeof(struct arpt_entry),
- sizeof(struct arpt_standard),
- 0,
- { 0, 0 }, { } },
- { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 }
- },
- /* ARP_OUT */
- {
- {
- {
- { 0 }, { 0 }, { 0 }, { 0 },
- 0, 0,
- { { 0, }, { 0, } },
- { { 0, }, { 0, } },
- 0, 0,
- 0, 0,
- 0, 0,
- "", "", { 0 }, { 0 },
- 0, 0
- },
- sizeof(struct arpt_entry),
- sizeof(struct arpt_standard),
- 0,
- { 0, 0 }, { } },
- { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 }
- },
- /* ARP_FORWARD */
- {
- {
- {
- { 0 }, { 0 }, { 0 }, { 0 },
- 0, 0,
- { { 0, }, { 0, } },
- { { 0, }, { 0, } },
- 0, 0,
- 0, 0,
- 0, 0,
- "", "", { 0 }, { 0 },
- 0, 0
- },
- sizeof(struct arpt_entry),
- sizeof(struct arpt_standard),
- 0,
- { 0, 0 }, { } },
- { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 }
- }
- },
- /* ERROR */
- {
- {
- {
- { 0 }, { 0 }, { 0 }, { 0 },
- 0, 0,
- { { 0, }, { 0, } },
- { { 0, }, { 0, } },
- 0, 0,
- 0, 0,
- 0, 0,
- "", "", { 0 }, { 0 },
- 0, 0
- },
- sizeof(struct arpt_entry),
- sizeof(struct arpt_error),
- 0,
- { 0, 0 }, { } },
- { { { { ARPT_ALIGN(sizeof(struct arpt_error_target)), ARPT_ERROR_TARGET } },
- { } },
- "ERROR"
- }
- }
+} initial_table __initdata = {
+ .repl = {
+ .name = "filter",
+ .valid_hooks = FILTER_VALID_HOOKS,
+ .num_entries = 4,
+ .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
+ .hook_entry = {
+ [NF_ARP_IN] = 0,
+ [NF_ARP_OUT] = sizeof(struct arpt_standard),
+ [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
+ },
+ .underflow = {
+ [NF_ARP_IN] = 0,
+ [NF_ARP_OUT] = sizeof(struct arpt_standard),
+ [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
+ },
+ },
+ .entries = {
+ ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */
+ ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */
+ ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */
+ },
+ .term = ARPT_ERROR_INIT,
};
static struct arpt_table packet_filter = {
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 4272890..4f51c1d 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -26,53 +26,29 @@
struct ipt_replace repl;
struct ipt_standard entries[3];
struct ipt_error term;
-} initial_table __initdata
-= { { "filter", FILTER_VALID_HOOKS, 4,
- sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
- { [NF_IP_LOCAL_IN] = 0,
- [NF_IP_FORWARD] = sizeof(struct ipt_standard),
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
- { [NF_IP_LOCAL_IN] = 0,
- [NF_IP_FORWARD] = sizeof(struct ipt_standard),
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
- 0, NULL, { } },
- {
- /* LOCAL_IN */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* FORWARD */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* LOCAL_OUT */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } }
- },
- /* ERROR */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_error),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
- { } },
- "ERROR"
- }
- }
+} initial_table __initdata = {
+ .repl = {
+ .name = "filter",
+ .valid_hooks = FILTER_VALID_HOOKS,
+ .num_entries = 4,
+ .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
+ .hook_entry = {
+ [NF_IP_LOCAL_IN] = 0,
+ [NF_IP_FORWARD] = sizeof(struct ipt_standard),
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
+ },
+ .underflow = {
+ [NF_IP_LOCAL_IN] = 0,
+ [NF_IP_FORWARD] = sizeof(struct ipt_standard),
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
+ },
+ },
+ .entries = {
+ IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
+ },
+ .term = IPT_ERROR_INIT, /* ERROR */
};
static struct xt_table packet_filter = {
@@ -105,7 +81,8 @@
if ((*pskb)->len < sizeof(struct iphdr)
|| ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
if (net_ratelimit())
- printk("ipt_hook: happy cracking.\n");
+ printk("iptable_filter: ignoring short SOCK_RAW "
+ "packet.\n");
return NF_ACCEPT;
}
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 9278802..902446f 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -33,73 +33,35 @@
struct ipt_replace repl;
struct ipt_standard entries[5];
struct ipt_error term;
-} initial_table __initdata
-= { { "mangle", MANGLE_VALID_HOOKS, 6,
- sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
- { [NF_IP_PRE_ROUTING] = 0,
- [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
- [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
- [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 },
- { [NF_IP_PRE_ROUTING] = 0,
- [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
- [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
- [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4 },
- 0, NULL, { } },
- {
- /* PRE_ROUTING */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* LOCAL_IN */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* FORWARD */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* LOCAL_OUT */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* POST_ROUTING */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_standard),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- },
- /* ERROR */
- { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ipt_entry),
- sizeof(struct ipt_error),
- 0, { 0, 0 }, { } },
- { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
- { } },
- "ERROR"
- }
- }
+} initial_table __initdata = {
+ .repl = {
+ .name = "mangle",
+ .valid_hooks = MANGLE_VALID_HOOKS,
+ .num_entries = 6,
+ .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
+ .hook_entry = {
+ [NF_IP_PRE_ROUTING] = 0,
+ [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
+ [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
+ [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
+ },
+ .underflow = {
+ [NF_IP_PRE_ROUTING] = 0,
+ [NF_IP_LOCAL_IN] = sizeof(struct ipt_standard),
+ [NF_IP_FORWARD] = sizeof(struct ipt_standard) * 2,
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
+ [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
+ },
+ },
+ .entries = {
+ IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
+ },
+ .term = IPT_ERROR_INIT, /* ERROR */
};
static struct xt_table packet_mangler = {
@@ -138,7 +100,8 @@
if ((*pskb)->len < sizeof(struct iphdr)
|| ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
if (net_ratelimit())
- printk("ipt_hook: happy cracking.\n");
+ printk("iptable_mangle: ignoring short SOCK_RAW "
+ "packet.\n");
return NF_ACCEPT;
}
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 18c3d4c..d6e5033 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -5,6 +5,7 @@
*/
#include <linux/module.h>
#include <linux/netfilter_ipv4/ip_tables.h>
+#include <net/ip.h>
#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
@@ -21,62 +22,18 @@
.size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
.hook_entry = {
[NF_IP_PRE_ROUTING] = 0,
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) },
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard)
+ },
.underflow = {
[NF_IP_PRE_ROUTING] = 0,
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) },
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard)
+ },
},
.entries = {
- /* PRE_ROUTING */
- {
- .entry = {
- .target_offset = sizeof(struct ipt_entry),
- .next_offset = sizeof(struct ipt_standard),
- },
- .target = {
- .target = {
- .u = {
- .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
- },
- },
- .verdict = -NF_ACCEPT - 1,
- },
- },
-
- /* LOCAL_OUT */
- {
- .entry = {
- .target_offset = sizeof(struct ipt_entry),
- .next_offset = sizeof(struct ipt_standard),
- },
- .target = {
- .target = {
- .u = {
- .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
- },
- },
- .verdict = -NF_ACCEPT - 1,
- },
- },
+ IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
},
- /* ERROR */
- .term = {
- .entry = {
- .target_offset = sizeof(struct ipt_entry),
- .next_offset = sizeof(struct ipt_error),
- },
- .target = {
- .target = {
- .u = {
- .user = {
- .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
- .name = IPT_ERROR_TARGET,
- },
- },
- },
- .errorname = "ERROR",
- },
- }
+ .term = IPT_ERROR_INIT, /* ERROR */
};
static struct xt_table packet_raw = {
@@ -98,6 +55,24 @@
return ipt_do_table(pskb, hook, in, out, &packet_raw);
}
+static unsigned int
+ipt_local_hook(unsigned int hook,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr) ||
+ ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+ if (net_ratelimit())
+ printk("iptable_raw: ignoring short SOCK_RAW"
+ "packet.\n");
+ return NF_ACCEPT;
+ }
+ return ipt_do_table(pskb, hook, in, out, &packet_raw);
+}
+
/* 'raw' is the very first table. */
static struct nf_hook_ops ipt_ops[] = {
{
@@ -108,7 +83,7 @@
.owner = THIS_MODULE,
},
{
- .hook = ipt_hook,
+ .hook = ipt_local_hook,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_RAW,
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 2534f71..6740736 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -46,77 +46,20 @@
.hook_entry = {
[NF_IP_PRE_ROUTING] = 0,
[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
+ },
.underflow = {
[NF_IP_PRE_ROUTING] = 0,
[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
- [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
+ [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
+ },
},
.entries = {
- /* PRE_ROUTING */
- {
- .entry = {
- .target_offset = sizeof(struct ipt_entry),
- .next_offset = sizeof(struct ipt_standard),
- },
- .target = {
- .target = {
- .u = {
- .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
- },
- },
- .verdict = -NF_ACCEPT - 1,
- },
- },
- /* POST_ROUTING */
- {
- .entry = {
- .target_offset = sizeof(struct ipt_entry),
- .next_offset = sizeof(struct ipt_standard),
- },
- .target = {
- .target = {
- .u = {
- .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
- },
- },
- .verdict = -NF_ACCEPT - 1,
- },
- },
- /* LOCAL_OUT */
- {
- .entry = {
- .target_offset = sizeof(struct ipt_entry),
- .next_offset = sizeof(struct ipt_standard),
- },
- .target = {
- .target = {
- .u = {
- .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
- },
- },
- .verdict = -NF_ACCEPT - 1,
- },
- },
+ IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
+ IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
},
- /* ERROR */
- .term = {
- .entry = {
- .target_offset = sizeof(struct ipt_entry),
- .next_offset = sizeof(struct ipt_error),
- },
- .target = {
- .target = {
- .u = {
- .user = {
- .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
- .name = IPT_ERROR_TARGET,
- },
- },
- },
- .errorname = "ERROR",
- },
- }
+ .term = IPT_ERROR_INIT, /* ERROR */
};
static struct xt_table nat_table = {
@@ -230,9 +173,7 @@
}
inline unsigned int
-alloc_null_binding(struct nf_conn *ct,
- struct nf_nat_info *info,
- unsigned int hooknum)
+alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
{
/* Force range to this IP; let proto decide mapping for
per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
@@ -251,9 +192,7 @@
}
unsigned int
-alloc_null_binding_confirmed(struct nf_conn *ct,
- struct nf_nat_info *info,
- unsigned int hooknum)
+alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
{
__be32 ip
= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
@@ -275,8 +214,7 @@
unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
- struct nf_conn *ct,
- struct nf_nat_info *info)
+ struct nf_conn *ct)
{
int ret;
@@ -285,7 +223,7 @@
if (ret == NF_ACCEPT) {
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
/* NUL mapping */
- ret = alloc_null_binding(ct, info, hooknum);
+ ret = alloc_null_binding(ct, hooknum);
}
return ret;
}
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 64bbed2..55dac36 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -80,7 +80,6 @@
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
struct nf_conn_nat *nat;
- struct nf_nat_info *info;
/* maniptype == SRC for postrouting. */
enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
@@ -129,7 +128,6 @@
}
/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
case IP_CT_NEW:
- info = &nat->info;
/* Seen it before? This can happen for loopback, retrans,
or local packets.. */
@@ -138,14 +136,13 @@
if (unlikely(nf_ct_is_confirmed(ct)))
/* NAT module was loaded late */
- ret = alloc_null_binding_confirmed(ct, info,
- hooknum);
+ ret = alloc_null_binding_confirmed(ct, hooknum);
else if (hooknum == NF_IP_LOCAL_IN)
/* LOCAL_IN hook doesn't have a chain! */
- ret = alloc_null_binding(ct, info, hooknum);
+ ret = alloc_null_binding(ct, hooknum);
else
ret = nf_nat_rule_find(pskb, hooknum, in, out,
- ct, info);
+ ct);
if (ret != NF_ACCEPT) {
return ret;
@@ -160,10 +157,8 @@
/* ESTABLISHED */
NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
- info = &nat->info;
}
- NF_CT_ASSERT(info);
return nf_nat_packet(ct, ctinfo, hooknum, pskb);
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 66026df..4c7e95f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -118,15 +118,15 @@
* Note about this hash function :
* Typical use is probably daddr = 0, only dport is going to vary hash
*/
-static inline unsigned int hash_port_and_addr(__u16 port, __be32 addr)
+static inline unsigned int udp_hash_port(__u16 port)
{
- addr ^= addr >> 16;
- addr ^= addr >> 8;
- return port ^ addr;
+ return port;
}
static inline int __udp_lib_port_inuse(unsigned int hash, int port,
- __be32 daddr, struct hlist_head udptable[])
+ const struct sock *this_sk,
+ struct hlist_head udptable[],
+ const struct udp_get_port_ops *ops)
{
struct sock *sk;
struct hlist_node *node;
@@ -138,7 +138,10 @@
inet = inet_sk(sk);
if (inet->num != port)
continue;
- if (inet->rcv_saddr == daddr)
+ if (this_sk) {
+ if (ops->saddr_cmp(sk, this_sk))
+ return 1;
+ } else if (ops->saddr_any(sk))
return 1;
}
return 0;
@@ -151,12 +154,11 @@
* @snum: port number to look up
* @udptable: hash list table, must be of UDP_HTABLE_SIZE
* @port_rover: pointer to record of last unallocated port
- * @saddr_comp: AF-dependent comparison of bound local IP addresses
+ * @ops: AF-dependent address operations
*/
int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover,
- int (*saddr_comp)(const struct sock *sk1,
- const struct sock *sk2 ) )
+ const struct udp_get_port_ops *ops)
{
struct hlist_node *node;
struct hlist_head *head;
@@ -176,8 +178,7 @@
for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
int size;
- hash = hash_port_and_addr(result,
- inet_sk(sk)->rcv_saddr);
+ hash = ops->hash_port_and_rcv_saddr(result, sk);
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
if (hlist_empty(head)) {
if (result > sysctl_local_port_range[1])
@@ -203,17 +204,16 @@
result = sysctl_local_port_range[0]
+ ((result - sysctl_local_port_range[0]) &
(UDP_HTABLE_SIZE - 1));
- hash = hash_port_and_addr(result, 0);
+ hash = udp_hash_port(result);
if (__udp_lib_port_inuse(hash, result,
- 0, udptable))
+ NULL, udptable, ops))
continue;
- if (!inet_sk(sk)->rcv_saddr)
+ if (ops->saddr_any(sk))
break;
- hash = hash_port_and_addr(result,
- inet_sk(sk)->rcv_saddr);
+ hash = ops->hash_port_and_rcv_saddr(result, sk);
if (! __udp_lib_port_inuse(hash, result,
- inet_sk(sk)->rcv_saddr, udptable))
+ sk, udptable, ops))
break;
}
if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -221,7 +221,7 @@
gotit:
*port_rover = snum = result;
} else {
- hash = hash_port_and_addr(snum, 0);
+ hash = udp_hash_port(snum);
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head)
@@ -231,12 +231,11 @@
(!sk2->sk_reuse || !sk->sk_reuse) &&
(!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
- (*saddr_comp)(sk, sk2))
+ ops->saddr_cmp(sk, sk2))
goto fail;
- if (inet_sk(sk)->rcv_saddr) {
- hash = hash_port_and_addr(snum,
- inet_sk(sk)->rcv_saddr);
+ if (!ops->saddr_any(sk)) {
+ hash = ops->hash_port_and_rcv_saddr(snum, sk);
head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head)
@@ -248,7 +247,7 @@
!sk->sk_bound_dev_if ||
sk2->sk_bound_dev_if ==
sk->sk_bound_dev_if) &&
- (*saddr_comp)(sk, sk2))
+ ops->saddr_cmp(sk, sk2))
goto fail;
}
}
@@ -266,12 +265,12 @@
}
int udp_get_port(struct sock *sk, unsigned short snum,
- int (*scmp)(const struct sock *, const struct sock *))
+ const struct udp_get_port_ops *ops)
{
- return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
+ return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops);
}
-int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
{
struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
@@ -280,9 +279,33 @@
inet1->rcv_saddr == inet2->rcv_saddr ));
}
+static int ipv4_rcv_saddr_any(const struct sock *sk)
+{
+ return !inet_sk(sk)->rcv_saddr;
+}
+
+static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
+{
+ addr ^= addr >> 16;
+ addr ^= addr >> 8;
+ return port ^ addr;
+}
+
+static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
+ const struct sock *sk)
+{
+ return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
+}
+
+const struct udp_get_port_ops udp_ipv4_ops = {
+ .saddr_cmp = ipv4_rcv_saddr_equal,
+ .saddr_any = ipv4_rcv_saddr_any,
+ .hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
+};
+
static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
{
- return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
+ return udp_get_port(sk, snum, &udp_ipv4_ops);
}
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
@@ -297,8 +320,8 @@
unsigned int hash, hashwild;
int score, best = -1, hport = ntohs(dport);
- hash = hash_port_and_addr(hport, daddr);
- hashwild = hash_port_and_addr(hport, 0);
+ hash = ipv4_hash_port_and_addr(hport, daddr);
+ hashwild = udp_hash_port(hport);
read_lock(&udp_hash_lock);
@@ -1198,8 +1221,8 @@
struct sock *sk, *skw, *sknext;
int dif;
int hport = ntohs(uh->dest);
- unsigned int hash = hash_port_and_addr(hport, daddr);
- unsigned int hashwild = hash_port_and_addr(hport, 0);
+ unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
+ unsigned int hashwild = udp_hash_port(hport);
dif = skb->dev->ifindex;
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 820a477..06d9419 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -5,14 +5,14 @@
#include <net/protocol.h>
#include <net/inet_common.h>
+extern const struct udp_get_port_ops udp_ipv4_ops;
+
extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover,
- int (*)(const struct sock*,const struct sock*));
-extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
-
+ const struct udp_get_port_ops *ops);
extern int udp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen);
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index f34fd68..3653b32 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -19,14 +19,15 @@
static int udplite_port_rover;
int udplite_get_port(struct sock *sk, unsigned short p,
- int (*c)(const struct sock *, const struct sock *))
+ const struct udp_get_port_ops *ops)
{
- return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
+ return __udp_lib_get_port(sk, p, udplite_hash,
+ &udplite_port_rover, ops);
}
static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
{
- return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
+ return udplite_get_port(sk, snum, &udp_ipv4_ops);
}
static int udplite_rcv(struct sk_buff *skb)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d02685c..c7ea248 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4204,6 +4204,10 @@
return err;
ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+ ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+ ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+#endif
register_netdevice_notifier(&ipv6_dev_notf);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6d8e4ac..14be0b9 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -660,6 +660,14 @@
Hop-by-hop options.
**********************************/
+/*
+ * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
+ */
+static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
+{
+ return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
+}
+
/* Router Alert as of RFC 2711 */
static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
@@ -688,25 +696,25 @@
if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
nh[optoff+1]);
- IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+ IP6_INC_STATS_BH(ipv6_skb_idev(skb),
IPSTATS_MIB_INHDRERRORS);
goto drop;
}
pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
if (pkt_len <= IPV6_MAXPLEN) {
- IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
return 0;
}
if (ipv6_hdr(skb)->payload_len) {
- IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
+ IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
return 0;
}
if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
- IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
+ IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
goto drop;
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f508171..4704b5f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -463,10 +463,17 @@
*/
if (xrlim_allow(dst, 1*HZ))
ndisc_send_redirect(skb, n, target);
- } else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK
- |IPV6_ADDR_LINKLOCAL)) {
+ } else {
+ int addrtype = ipv6_addr_type(&hdr->saddr);
+
/* This check is security critical. */
- goto error;
+ if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK))
+ goto error;
+ if (addrtype & IPV6_ADDR_LINKLOCAL) {
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH,
+ ICMPV6_NOT_NEIGHBOUR, 0, skb->dev);
+ goto error;
+ }
}
if (skb->len > dst_mtu(dst)) {
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 76f0cf6..7e32e2a 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -24,53 +24,29 @@
struct ip6t_replace repl;
struct ip6t_standard entries[3];
struct ip6t_error term;
-} initial_table __initdata
-= { { "filter", FILTER_VALID_HOOKS, 4,
- sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
- { [NF_IP6_LOCAL_IN] = 0,
- [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
- [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 },
- { [NF_IP6_LOCAL_IN] = 0,
- [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
- [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 },
- 0, NULL, { } },
- {
- /* LOCAL_IN */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* FORWARD */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* LOCAL_OUT */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } }
- },
- /* ERROR */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_error),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
- { } },
- "ERROR"
- }
- }
+} initial_table __initdata = {
+ .repl = {
+ .name = "filter",
+ .valid_hooks = FILTER_VALID_HOOKS,
+ .num_entries = 4,
+ .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
+ .hook_entry = {
+ [NF_IP6_LOCAL_IN] = 0,
+ [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
+ [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
+ },
+ .underflow = {
+ [NF_IP6_LOCAL_IN] = 0,
+ [NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
+ [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
+ },
+ },
+ .entries = {
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
+ },
+ .term = IP6T_ERROR_INIT, /* ERROR */
};
static struct xt_table packet_filter = {
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index a9f10e3..f2d2649 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -32,73 +32,35 @@
struct ip6t_replace repl;
struct ip6t_standard entries[5];
struct ip6t_error term;
-} initial_table __initdata
-= { { "mangle", MANGLE_VALID_HOOKS, 6,
- sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
- { [NF_IP6_PRE_ROUTING] = 0,
- [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
- [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
- [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
- [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4},
- { [NF_IP6_PRE_ROUTING] = 0,
- [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
- [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
- [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
- [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4},
- 0, NULL, { } },
- {
- /* PRE_ROUTING */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* LOCAL_IN */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* FORWARD */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* LOCAL_OUT */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } },
- /* POST_ROUTING */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_standard),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
- -NF_ACCEPT - 1 } }
- },
- /* ERROR */
- { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
- 0,
- sizeof(struct ip6t_entry),
- sizeof(struct ip6t_error),
- 0, { 0, 0 }, { } },
- { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
- { } },
- "ERROR"
- }
- }
+} initial_table __initdata = {
+ .repl = {
+ .name = "mangle",
+ .valid_hooks = MANGLE_VALID_HOOKS,
+ .num_entries = 6,
+ .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
+ .hook_entry = {
+ [NF_IP6_PRE_ROUTING] = 0,
+ [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
+ [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
+ [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
+ [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
+ },
+ .underflow = {
+ [NF_IP6_PRE_ROUTING] = 0,
+ [NF_IP6_LOCAL_IN] = sizeof(struct ip6t_standard),
+ [NF_IP6_FORWARD] = sizeof(struct ip6t_standard) * 2,
+ [NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
+ [NF_IP6_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
+ },
+ },
+ .entries = {
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
+ },
+ .term = IP6T_ERROR_INIT, /* ERROR */
};
static struct xt_table packet_mangler = {
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index a3eb5b8..0acda45 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -35,56 +35,10 @@
},
},
.entries = {
- /* PRE_ROUTING */
- {
- .entry = {
- .target_offset = sizeof(struct ip6t_entry),
- .next_offset = sizeof(struct ip6t_standard),
- },
- .target = {
- .target = {
- .u = {
- .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
- },
- },
- .verdict = -NF_ACCEPT - 1,
- },
- },
-
- /* LOCAL_OUT */
- {
- .entry = {
- .target_offset = sizeof(struct ip6t_entry),
- .next_offset = sizeof(struct ip6t_standard),
- },
- .target = {
- .target = {
- .u = {
- .target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
- },
- },
- .verdict = -NF_ACCEPT - 1,
- },
- },
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
+ IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
},
- /* ERROR */
- .term = {
- .entry = {
- .target_offset = sizeof(struct ip6t_entry),
- .next_offset = sizeof(struct ip6t_error),
- },
- .target = {
- .target = {
- .u = {
- .user = {
- .target_size = IP6T_ALIGN(sizeof(struct ip6t_error_target)),
- .name = IP6T_ERROR_TARGET,
- },
- },
- },
- .errorname = "ERROR",
- },
- }
+ .term = IP6T_ERROR_INIT, /* ERROR */
};
static struct xt_table packet_raw = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b083c09..a7ae59c 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -52,9 +52,28 @@
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
+static int ipv6_rcv_saddr_any(const struct sock *sk)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ return ipv6_addr_any(&np->rcv_saddr);
+}
+
+static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
+ const struct sock *sk)
+{
+ return port;
+}
+
+const struct udp_get_port_ops udp_ipv6_ops = {
+ .saddr_cmp = ipv6_rcv_saddr_equal,
+ .saddr_any = ipv6_rcv_saddr_any,
+ .hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
+};
+
static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
{
- return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
+ return udp_get_port(sk, snum, &udp_ipv6_ops);
}
static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 6e252f3..36b0c11 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,6 +6,8 @@
#include <net/addrconf.h>
#include <net/inet_common.h>
+extern const struct udp_get_port_ops udp_ipv6_ops;
+
extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index f54016a..c40a513 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -37,7 +37,7 @@
static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
{
- return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
+ return udplite_get_port(sk, snum, &udp_ipv6_ops);
}
struct proto udplitev6_prot = {
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 822917d..3e07e9d 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -17,6 +17,7 @@
* scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
* SSID)
*/
+#include <linux/delay.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
@@ -27,7 +28,6 @@
#include <linux/rtnetlink.h>
#include <net/iw_handler.h>
#include <asm/types.h>
-#include <asm/delay.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e132c8a..e8b5c2d 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -299,7 +299,6 @@
{
struct nf_conn *ct = (struct nf_conn *)nfct;
struct nf_conn_help *help = nfct_help(ct);
- struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto;
typeof(nf_conntrack_destroyed) destroyed;
@@ -317,10 +316,6 @@
* destroy_conntrack() MUST NOT be called with a write lock
* to nf_conntrack_lock!!! -HW */
rcu_read_lock();
- l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
- if (l3proto && l3proto->destroy)
- l3proto->destroy(ct);
-
l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
if (l4proto && l4proto->destroy)
@@ -893,8 +888,13 @@
NF_CT_DUMP_TUPLE(newreply);
ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
- if (!ct->master && help && help->expecting == 0)
- help->helper = __nf_ct_helper_find(newreply);
+ if (!ct->master && help && help->expecting == 0) {
+ struct nf_conntrack_helper *helper;
+ helper = __nf_ct_helper_find(newreply);
+ if (helper)
+ memset(&help->help, 0, sizeof(help->help));
+ help->helper = helper;
+ }
write_unlock_bh(&nf_conntrack_lock);
}
EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index aa1a97ee..d6d39e2 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -830,11 +830,6 @@
char *helpname;
int err;
- if (!help) {
- /* FIXME: we need to reallocate and rehash */
- return -EBUSY;
- }
-
/* don't change helper of sibling connections */
if (ct->master)
return -EINVAL;
@@ -843,25 +838,34 @@
if (err < 0)
return err;
- helper = __nf_conntrack_helper_find_byname(helpname);
- if (!helper) {
- if (!strcmp(helpname, ""))
- helper = NULL;
- else
- return -EINVAL;
- }
-
- if (help->helper) {
- if (!helper) {
+ if (!strcmp(helpname, "")) {
+ if (help && help->helper) {
/* we had a helper before ... */
nf_ct_remove_expectations(ct);
help->helper = NULL;
- } else {
- /* need to zero data of old helper */
- memset(&help->help, 0, sizeof(help->help));
}
+
+ return 0;
}
+ if (!help) {
+ /* FIXME: we need to reallocate and rehash */
+ return -EBUSY;
+ }
+
+ helper = __nf_conntrack_helper_find_byname(helpname);
+ if (helper == NULL)
+ return -EINVAL;
+
+ if (help->helper == helper)
+ return 0;
+
+ if (help->helper)
+ /* we had a helper before ... */
+ nf_ct_remove_expectations(ct);
+
+ /* need to zero data of old helper */
+ memset(&help->help, 0, sizeof(help->help));
help->helper = helper;
return 0;
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index f4ea8fe..189ded5 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -134,12 +134,66 @@
nf_ct_l3proto_module_put(match->family);
}
+#ifdef CONFIG_COMPAT
+struct compat_xt_conntrack_info
+{
+ compat_uint_t statemask;
+ compat_uint_t statusmask;
+ struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
+ struct in_addr sipmsk[IP_CT_DIR_MAX];
+ struct in_addr dipmsk[IP_CT_DIR_MAX];
+ compat_ulong_t expires_min;
+ compat_ulong_t expires_max;
+ u_int8_t flags;
+ u_int8_t invflags;
+};
+
+static void compat_from_user(void *dst, void *src)
+{
+ struct compat_xt_conntrack_info *cm = src;
+ struct xt_conntrack_info m = {
+ .statemask = cm->statemask,
+ .statusmask = cm->statusmask,
+ .expires_min = cm->expires_min,
+ .expires_max = cm->expires_max,
+ .flags = cm->flags,
+ .invflags = cm->invflags,
+ };
+ memcpy(m.tuple, cm->tuple, sizeof(m.tuple));
+ memcpy(m.sipmsk, cm->sipmsk, sizeof(m.sipmsk));
+ memcpy(m.dipmsk, cm->dipmsk, sizeof(m.dipmsk));
+ memcpy(dst, &m, sizeof(m));
+}
+
+static int compat_to_user(void __user *dst, void *src)
+{
+ struct xt_conntrack_info *m = src;
+ struct compat_xt_conntrack_info cm = {
+ .statemask = m->statemask,
+ .statusmask = m->statusmask,
+ .expires_min = m->expires_min,
+ .expires_max = m->expires_max,
+ .flags = m->flags,
+ .invflags = m->invflags,
+ };
+ memcpy(cm.tuple, m->tuple, sizeof(cm.tuple));
+ memcpy(cm.sipmsk, m->sipmsk, sizeof(cm.sipmsk));
+ memcpy(cm.dipmsk, m->dipmsk, sizeof(cm.dipmsk));
+ return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif
+
static struct xt_match conntrack_match = {
.name = "conntrack",
.match = match,
.checkentry = checkentry,
.destroy = destroy,
.matchsize = sizeof(struct xt_conntrack_info),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_xt_conntrack_info),
+ .compat_from_user = compat_from_user,
+ .compat_to_user = compat_to_user,
+#endif
.family = AF_INET,
.me = THIS_MODULE,
};
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 3385ee5..f28bb2d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -71,12 +71,9 @@
/* Kick device.
- Note, that this procedure can be called by a watchdog timer, so that
- we do not check dev->tbusy flag here.
- Returns: 0 - queue is empty.
- >0 - queue is not empty, but throttled.
- <0 - queue is not empty. Device is throttled, if dev->tbusy != 0.
+ Returns: 0 - queue is empty or throttled.
+ >0 - queue is not empty.
NOTE: Called under dev->queue_lock with locally disabled BH.
*/
@@ -115,7 +112,7 @@
kfree_skb(skb);
if (net_ratelimit())
printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
- return -1;
+ goto out;
}
__get_cpu_var(netdev_rx_stat).cpu_collision++;
goto requeue;
@@ -135,10 +132,12 @@
netif_tx_unlock(dev);
}
spin_lock(&dev->queue_lock);
- return -1;
+ q = dev->qdisc;
+ goto out;
}
if (ret == NETDEV_TX_LOCKED && nolock) {
spin_lock(&dev->queue_lock);
+ q = dev->qdisc;
goto collision;
}
}
@@ -163,26 +162,28 @@
*/
requeue:
- if (skb->next)
+ if (unlikely(q == &noop_qdisc))
+ kfree_skb(skb);
+ else if (skb->next)
dev->gso_skb = skb;
else
q->ops->requeue(skb, q);
netif_schedule(dev);
- return 1;
+ return 0;
}
+
+out:
BUG_ON((int) q->q.qlen < 0);
return q->q.qlen;
}
void __qdisc_run(struct net_device *dev)
{
- if (unlikely(dev->qdisc == &noop_qdisc))
- goto out;
+ do {
+ if (!qdisc_restart(dev))
+ break;
+ } while (!netif_queue_stopped(dev));
- while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
- /* NOTHING */;
-
-out:
clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
}
@@ -544,6 +545,7 @@
void dev_deactivate(struct net_device *dev)
{
struct Qdisc *qdisc;
+ struct sk_buff *skb;
spin_lock_bh(&dev->queue_lock);
qdisc = dev->qdisc;
@@ -551,8 +553,12 @@
qdisc_reset(qdisc);
+ skb = dev->gso_skb;
+ dev->gso_skb = NULL;
spin_unlock_bh(&dev->queue_lock);
+ kfree_skb(skb);
+
dev_watchdog_down(dev);
/* Wait for outstanding dev_queue_xmit calls. */
@@ -561,11 +567,6 @@
/* Wait for outstanding qdisc_run calls. */
while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
yield();
-
- if (dev->gso_skb) {
- kfree_skb(dev->gso_skb);
- dev->gso_skb = NULL;
- }
}
void dev_init_scheduler(struct net_device *dev)
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index d24914d..f05ad9a 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -94,14 +94,13 @@
struct net_device *dev = sch->dev;
struct teql_sched_data *q = qdisc_priv(sch);
- __skb_queue_tail(&q->q, skb);
- if (q->q.qlen <= dev->tx_queue_len) {
+ if (q->q.qlen < dev->tx_queue_len) {
+ __skb_queue_tail(&q->q, skb);
sch->bstats.bytes += skb->len;
sch->bstats.packets++;
return 0;
}
- __skb_unlink(skb, &q->q);
kfree_skb(skb);
sch->qstats.drops++;
return NET_XMIT_DROP;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 83a76ba..4dcdabf 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4164,6 +4164,7 @@
rwlock_t *addr_lock;
int err = 0;
void *addrs;
+ void *buf;
int bytes_copied = 0;
if (len != sizeof(struct sctp_getaddrs_old))
@@ -4217,13 +4218,14 @@
}
}
+ buf = addrs;
list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
memcpy(&temp, &addr->a, sizeof(temp));
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
- memcpy(addrs, &temp, addrlen);
- to += addrlen;
+ memcpy(buf, &temp, addrlen);
+ buf += addrlen;
bytes_copied += addrlen;
cnt ++;
if (cnt >= getaddrs.addr_num) break;
@@ -4266,6 +4268,7 @@
size_t space_left;
int bytes_copied = 0;
void *addrs;
+ void *buf;
if (len <= sizeof(struct sctp_getaddrs))
return -EINVAL;
@@ -4316,6 +4319,7 @@
}
}
+ buf = addrs;
list_for_each(pos, &bp->address_list) {
addr = list_entry(pos, struct sctp_sockaddr_entry, list);
memcpy(&temp, &addr->a, sizeof(temp));
@@ -4325,8 +4329,8 @@
err = -ENOMEM; /*fixme: right error?*/
goto error;
}
- memcpy(addrs, &temp, addrlen);
- to += addrlen;
+ memcpy(buf, &temp, addrlen);
+ buf += addrlen;
bytes_copied += addrlen;
cnt ++;
space_left -= addrlen;
@@ -5227,7 +5231,12 @@
/* Allocate HMAC for generating cookie. */
if (sctp_hmac_alg) {
tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
- if (!tfm) {
+ if (IS_ERR(tfm)) {
+ if (net_ratelimit()) {
+ printk(KERN_INFO
+ "SCTP: failed to load transform for %s: %ld\n",
+ sctp_hmac_alg, PTR_ERR(tfm));
+ }
err = -ENOSYS;
goto out;
}
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 661ea2d..bfecb35 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -141,11 +141,6 @@
* an ABORT, so we need to include it in the sac_info.
*/
if (chunk) {
- /* sctp_inqu_pop() has allready pulled off the chunk
- * header. We need to put it back temporarily
- */
- skb_push(chunk->skb, sizeof(sctp_chunkhdr_t));
-
/* Copy the chunk data to a new skb and reserve enough
* head room to use as notification.
*/
@@ -155,9 +150,6 @@
if (!skb)
goto fail;
- /* put back the chunk header now that we have a copy */
- skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
-
/* Embed the event fields inside the cloned skb. */
event = sctp_skb2event(skb);
sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
@@ -168,7 +160,8 @@
/* Trim the buffer to the right length. */
skb_trim(skb, sizeof(struct sctp_assoc_change) +
- ntohs(chunk->chunk_hdr->length));
+ ntohs(chunk->chunk_hdr->length) -
+ sizeof(sctp_chunkhdr_t));
} else {
event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
MSG_NOTIFICATION, gfp);