diff options
170 files changed, 3232 insertions, 1295 deletions
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 15fc8fbef67e..4820366b6ae8 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -259,9 +259,9 @@ sub dibusb { } sub nxt2002 { - my $sourcefile = "Broadband4PC_4_2_11.zip"; + my $sourcefile = "Technisat_DVB-PC_4_4_COMPACT.zip"; my $url = "http://www.bbti.us/download/windows/$sourcefile"; - my $hash = "c6d2ea47a8f456d887ada0cfb718ff2a"; + my $hash = "476befae8c7c1bb9648954060b1eec1f"; my $outfile = "dvb-fe-nxt2002.fw"; my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); @@ -269,8 +269,8 @@ sub nxt2002 { wgetfile($sourcefile, $url); unzip($sourcefile, $tmpdir); - verify("$tmpdir/SkyNETU.sys", $hash); - extract("$tmpdir/SkyNETU.sys", 375832, 5908, $outfile); + verify("$tmpdir/SkyNET.sys", $hash); + extract("$tmpdir/SkyNET.sys", 331624, 5908, $outfile); $outfile; } diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 421bcfff6ad2..43ab119963d5 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -57,6 +57,15 @@ Who: Jody McIntyre <scjody@steamballoon.com> --------------------------- +What: sbp2: module parameter "force_inquiry_hack" +When: July 2006 +Why: Superceded by parameter "workarounds". Both parameters are meant to be + used ad-hoc and for single devices only, i.e. not in modprobe.conf, + therefore the impact of this feature replacement should be low. +Who: Stefan Richter <stefanr@s5r6.in-berlin.de> + +--------------------------- + What: Video4Linux API 1 ioctls and video_decoder.h from Video devices. When: July 2006 Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6 diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README index 43e836c07ae8..e9cc8bb26f7d 100644 --- a/Documentation/firmware_class/README +++ b/Documentation/firmware_class/README @@ -105,20 +105,3 @@ on the setup, so I think that the choice on what firmware to make persistent should be left to userspace. - - Why register_firmware()+__init can be useful: - - For boot devices needing firmware. - - To make the transition easier: - The firmware can be declared __init and register_firmware() - called on module_init. Then the firmware is warranted to be - there even if "firmware hotplug userspace" is not there yet or - it doesn't yet provide the needed firmware. - Once the firmware is widely available in userspace, it can be - removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE). - - In either case, if firmware hotplug support is there, it can move the - firmware out of kernel memory into the real filesystem for later - usage. - - Note: If persistence is implemented on top of initramfs, - register_firmware() may not be appropriate. - diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c index ad3edaba4533..87feccdb5c9f 100644 --- a/Documentation/firmware_class/firmware_sample_driver.c +++ b/Documentation/firmware_class/firmware_sample_driver.c @@ -5,8 +5,6 @@ * * Sample code on how to use request_firmware() from drivers. * - * Note that register_firmware() is currently useless. - * */ #include <linux/module.h> @@ -17,11 +15,6 @@ #include "linux/firmware.h" -#define WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE -#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE -char __init inkernel_firmware[] = "let's say that this is firmware\n"; -#endif - static struct device ghost_device = { .bus_id = "ghost0", }; @@ -104,10 +97,6 @@ static void sample_probe_async(void) static int sample_init(void) { -#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE - register_firmware("sample_driver_fw", inkernel_firmware, - sizeof(inkernel_firmware)); -#endif device_initialize(&ghost_device); /* since there is no real hardware insertion I just call the * sample probe functions here */ diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt index c5beb548cfc4..21ed51173662 100644 --- a/Documentation/watchdog/watchdog-api.txt +++ b/Documentation/watchdog/watchdog-api.txt @@ -36,6 +36,9 @@ timeout or margin. The simplest way to ping the watchdog is to write some data to the device. So a very simple watchdog daemon would look like this: +#include <stdlib.h> +#include <fcntl.h> + int main(int argc, const char *argv[]) { int fd=open("/dev/watchdog",O_WRONLY); if (fd==-1) { diff --git a/MAINTAINERS b/MAINTAINERS index 753584cf4e7e..bd10b2af2223 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -40,11 +40,20 @@ trivial patch so apply some common sense. PLEASE document known bugs. If it doesn't work for everything or does something very odd once a month document it. + PLEASE remember that submissions must be made under the terms + of the OSDL certificate of contribution + (http://www.osdl.org/newsroom/press_releases/2004/2004_05_24_dco.html) + and should include a Signed-off-by: line. + 6. Make sure you have the right to send any changes you make. If you do changes at work you may find your employer owns the patch not you. -7. Happy hacking. +7. When sending security related changes or reports to a maintainer + please Cc: security@kernel.org, especially if the maintainer + does not respond. + +8. Happy hacking. ----------------------------------- @@ -969,7 +978,7 @@ S: Maintained EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com -L: ext3-users@redhat.com +L: ext2-devel@lists.sourceforge.net S: Maintained F71805F HARDWARE MONITORING DRIVER @@ -1530,12 +1539,28 @@ W: http://jfs.sourceforge.net/ T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git S: Supported +JOURNALLING LAYER FOR BLOCK DEVICS (JBD) +P: Stephen Tweedie, Andrew Morton +M: sct@redhat.com, akpm@osdl.org +L: ext2-devel@lists.sourceforge.net +S: Maintained + KCONFIG P: Roman Zippel M: zippel@linux-m68k.org L: kbuild-devel@lists.sourceforge.net S: Maintained +KDUMP +P: Vivek Goyal +M: vgoyal@in.ibm.com +P: Haren Myneni +M: hbabu@us.ibm.com +L: fastboot@lists.osdl.org +L: linux-kernel@vger.kernel.org +W: http://lse.sourceforge.net/kdump/ +S: Maintained + KERNEL AUTOMOUNTER (AUTOFS) P: H. Peter Anvin M: hpa@zytor.com diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 98356f810007..02e188d98e7d 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -95,7 +95,10 @@ static void __init mainstone_init_irq(void) for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) { set_irq_chip(irq, &mainstone_irq_chip); set_irq_handler(irq, do_level_IRQ); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14)) + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN); + else + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } set_irq_flags(MAINSTONE_IRQ(8), 0); set_irq_flags(MAINSTONE_IRQ(12), 0); diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S index 832fb86a03b4..73de2eaca22a 100644 --- a/arch/arm/mach-s3c2410/sleep.S +++ b/arch/arm/mach-s3c2410/sleep.S @@ -59,8 +59,7 @@ ENTRY(s3c2410_cpu_suspend) mrc p15, 0, r5, c13, c0, 0 @ PID mrc p15, 0, r6, c3, c0, 0 @ Domain ID mrc p15, 0, r7, c2, c0, 0 @ translation table base address - mrc p15, 0, r8, c2, c0, 0 @ auxiliary control register - mrc p15, 0, r9, c1, c0, 0 @ control register + mrc p15, 0, r8, c1, c0, 0 @ control register stmia r0, { r4 - r13 } @@ -165,7 +164,6 @@ ENTRY(s3c2410_cpu_resume) mcr p15, 0, r5, c13, c0, 0 @ PID mcr p15, 0, r6, c3, c0, 0 @ Domain ID mcr p15, 0, r7, c2, c0, 0 @ translation table base - mcr p15, 0, r8, c1, c1, 0 @ auxilliary control #ifdef CONFIG_DEBUG_RESUME mov r3, #'R' @@ -173,7 +171,7 @@ ENTRY(s3c2410_cpu_resume) #endif ldr r2, =resume_with_mmu - mcr p15, 0, r9, c1, c0, 0 @ turn on MMU, etc + mcr p15, 0, r8, c1, c0, 0 @ turn on MMU, etc nop @ second-to-last before mmu mov pc, r2 @ go back to virtual address diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 013b85df18c6..3d4b2f3d116a 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -1341,6 +1341,14 @@ int __init APIC_init_uniprocessor (void) connect_bsp_APIC(); + /* + * Hack: In case of kdump, after a crash, kernel might be booting + * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid + * might be zero if read from MP tables. Get it from LAPIC. + */ +#ifdef CONFIG_CRASH_DUMP + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); +#endif phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); setup_local_APIC(); diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 2d22f5761b1d..0e498369f35e 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -130,9 +130,8 @@ static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl, print_symbol("%s", addr); printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS; - if (printed) - printk(" "); + printk(" "); else printk("\n"); @@ -212,7 +211,6 @@ static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp, } stack = esp; - printk(log_lvl); for(i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index ae6534ad8161..3df1371d4520 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -651,7 +651,7 @@ void __init mem_init(void) * Specifically, in the case of x86, we will always add * memory to the highmem for now. */ -#ifdef CONFIG_HOTPLUG_MEMORY +#ifdef CONFIG_MEMORY_HOTPLUG #ifndef CONFIG_NEED_MULTIPLE_NODES int add_memory(u64 start, u64 size) { diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index f6a8853cd1b4..9ea35398e10d 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -134,7 +134,7 @@ CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y CONFIG_NUMA=y -CONFIG_NODES_SHIFT=8 +CONFIG_NODES_SHIFT=10 CONFIG_VIRTUAL_MEM_MAP=y CONFIG_HOLES_IN_ZONE=y CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y @@ -1159,7 +1159,7 @@ CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 7956eb9058fc..d58c1c5c903a 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -416,7 +416,7 @@ iosapic_end_level_irq (unsigned int irq) ia64_vector vec = irq_to_vector(irq); struct iosapic_rte_info *rte; - move_irq(irq); + move_native_irq(irq); list_for_each_entry(rte, &iosapic_intr_info[vec].rtes, rte_list) iosapic_eoi(rte->addr, vec); } @@ -458,7 +458,7 @@ iosapic_ack_edge_irq (unsigned int irq) { irq_desc_t *idesc = irq_descp(irq); - move_irq(irq); + move_native_irq(irq); /* * Once we have recorded IRQ_PENDING already, we can mask the * interrupt for real. This prevents IRQ storms from unhandled diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index 5ce908ef9c95..9c72ea3f6432 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -101,7 +101,6 @@ void set_irq_affinity_info (unsigned int irq, int hwid, int redir) if (irq < NR_IRQS) { irq_affinity[irq] = mask; - set_irq_info(irq, mask); irq_redir[irq] = (char) (redir & 0xff); } } diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 029f09901b85..ce19ad4e92ec 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -272,7 +272,7 @@ static inline void stop_hz_timer(void) next = next_timer_interrupt(); do { seq = read_seqbegin_irqsave(&xtime_lock, flags); - timer = (__u64)(next - jiffies) + jiffies_64; + timer = (__u64 next) - (__u64 jiffies) + jiffies_64; } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); todval = -1ULL; /* Be careful about overflows. */ diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 6e1135cc03b0..2856551bddf1 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -79,6 +79,7 @@ sys_call_table: /*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 /*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare +/*300*/ .long sys_set_robust_list, sys_get_robust_list #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -190,6 +191,6 @@ sunos_sys_table: /*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys #endif diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index d4b39cd30310..1136fc465e37 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -78,8 +78,9 @@ sys_call_table32: .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid /*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64 -/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat +/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare +/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list #endif /* CONFIG_COMPAT */ @@ -147,8 +148,9 @@ sys_call_table: .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid /*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 -/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat +/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare +/*300*/ .word sys_set_robust_list, sys_get_robust_list #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -261,5 +263,5 @@ sunos_sys_table: /*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys #endif diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 1eaa5dae6174..fa1d19ca700a 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -514,13 +514,13 @@ static void __kprobes resume_execution(struct kprobe *p, *tos = orig_rip + (*tos - copy_rip); break; case 0xff: - if ((*insn & 0x30) == 0x10) { + if ((insn[1] & 0x30) == 0x10) { /* call absolute, indirect */ /* Fix return addr; rip is correct. */ next_rip = regs->rip; *tos = orig_rip + (*tos - copy_rip); - } else if (((*insn & 0x31) == 0x20) || /* jmp near, absolute indirect */ - ((*insn & 0x31) == 0x21)) { /* jmp far, absolute indirect */ + } else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ + ((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ /* rip is correct. */ next_rip = regs->rip; } diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 472318205236..0c99ae6a3407 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -86,18 +86,9 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count) static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); static void fw_class_dev_release(struct class_device *class_dev); -int firmware_class_uevent(struct class_device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); -static struct class firmware_class = { - .name = "firmware", - .uevent = firmware_class_uevent, - .release = fw_class_dev_release, -}; - -int -firmware_class_uevent(struct class_device *class_dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int firmware_class_uevent(struct class_device *class_dev, char **envp, + int num_envp, char *buffer, int buffer_size) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); int i = 0, len = 0; @@ -116,6 +107,12 @@ firmware_class_uevent(struct class_device *class_dev, char **envp, return 0; } +static struct class firmware_class = { + .name = "firmware", + .uevent = firmware_class_uevent, + .release = fw_class_dev_release, +}; + static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf) { @@ -493,25 +490,6 @@ release_firmware(const struct firmware *fw) } } -/** - * register_firmware: - provide a firmware image for later usage - * @name: name of firmware image file - * @data: buffer pointer for the firmware image - * @size: size of the data buffer area - * - * Make sure that @data will be available by requesting firmware @name. - * - * Note: This will not be possible until some kind of persistence - * is available. - **/ -void -register_firmware(const char *name, const u8 *data, size_t size) -{ - /* This is meaningless without firmware caching, so until we - * decide if firmware caching is reasonable just leave it as a - * noop */ -} - /* Async support */ struct firmware_work { struct work_struct work; @@ -630,4 +608,3 @@ module_exit(firmware_class_exit); EXPORT_SYMBOL(release_firmware); EXPORT_SYMBOL(request_firmware); EXPORT_SYMBOL(request_firmware_nowait); -EXPORT_SYMBOL(register_firmware); diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index a13395e2c372..fa2ba9ebe42a 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c @@ -33,11 +33,6 @@ * 82801E (C-ICH) : document number 273599-001, 273645-002, * 82801EB (ICH5) : document number 252516-001, 252517-003, * 82801ER (ICH5R) : document number 252516-001, 252517-003, - * 82801FB (ICH6) : document number 301473-002, 301474-007, - * 82801FR (ICH6R) : document number 301473-002, 301474-007, - * 82801FBM (ICH6-M) : document number 301473-002, 301474-007, - * 82801FW (ICH6W) : document number 301473-001, 301474-007, - * 82801FRW (ICH6RW) : document number 301473-001, 301474-007 * * 20000710 Nils Faerber * Initial Version 0.01 @@ -66,6 +61,10 @@ * 20050807 Wim Van Sebroeck <wim@iguana.be> * 0.08 Make sure that the watchdog is only "armed" when started. * (Kernel Bug 4251) + * 20060416 Wim Van Sebroeck <wim@iguana.be> + * 0.09 Remove support for the ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW and + * ICH7 chipsets. (See Kernel Bug 6031 - other code will support these + * chipsets) */ /* @@ -90,7 +89,7 @@ #include "i8xx_tco.h" /* Module and version information */ -#define TCO_VERSION "0.08" +#define TCO_VERSION "0.09" #define TCO_MODULE_NAME "i8xx TCO timer" #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION #define PFX TCO_MODULE_NAME ": " @@ -391,11 +390,6 @@ static struct pci_device_id i8xx_tco_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, }, { 0, }, /* End of list */ }; diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 9dc54736e4eb..1ea04e9b2b0b 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c @@ -423,6 +423,12 @@ static int s3c2410wdt_probe(struct platform_device *pdev) if (tmr_atboot && started == 0) { printk(KERN_INFO PFX "Starting Watchdog Timer\n"); s3c2410wdt_start(); + } else if (!tmr_atboot) { + /* if we're not enabling the watchdog, then ensure it is + * disabled if it has been left running from the bootloader + * or other source */ + + s3c2410wdt_stop(); } return 0; diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index 515ce7572049..20b88f9b7be2 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -377,7 +377,7 @@ static int __init sc1200wdt_init(void) { int ret; - printk(banner); + printk("%s\n", banner); spin_lock_init(&sc1200wdt_lock); sema_init(&open_sem, 1); diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 78e30f803671..ffca8b63ee79 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -553,6 +553,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw, if (irq != NULL) *irq = pmac_ide[ix].irq; + + hw->dev = &pmac_ide[ix].mdev->ofdev.dev; } #define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x))) diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 19222878aae9..11f13778f139 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -553,7 +553,7 @@ static void ohci_initialize(struct ti_ohci *ohci) * register content. * To actually enable physical responses is the job of our interrupt * handler which programs the physical request filter. */ - reg_write(ohci, OHCI1394_PhyUpperBound, 0xffff0000); + reg_write(ohci, OHCI1394_PhyUpperBound, 0x01000000); DBGMSG("physUpperBoundOffset=%08x", reg_read(ohci, OHCI1394_PhyUpperBound)); diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index f4206604db03..8a23fb54c693 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -42,6 +42,7 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/string.h> +#include <linux/stringify.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/fs.h> @@ -117,7 +118,8 @@ MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default */ static int max_sectors = SBP2_MAX_SECTORS; module_param(max_sectors, int, 0444); -MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = 255)"); +MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = " + __stringify(SBP2_MAX_SECTORS) ")"); /* * Exclusive login to sbp2 device? In most cases, the sbp2 driver should @@ -135,18 +137,45 @@ module_param(exclusive_login, int, 0644); MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)"); /* - * SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on - * if your sbp2 device is not properly handling the SCSI inquiry command. - * This hack makes the inquiry look more like a typical MS Windows inquiry - * by enforcing 36 byte inquiry and avoiding access to mode_sense page 8. + * If any of the following workarounds is required for your device to work, + * please submit the kernel messages logged by sbp2 to the linux1394-devel + * mailing list. * - * If force_inquiry_hack=1 is required for your device to work, - * please submit the logged sbp2_firmware_revision value of this device to - * the linux1394-devel mailing list. + * - 128kB max transfer + * Limit transfer size. Necessary for some old bridges. + * + * - 36 byte inquiry + * When scsi_mod probes the device, let the inquiry command look like that + * from MS Windows. + * + * - skip mode page 8 + * Suppress sending of mode_sense for mode page 8 if the device pretends to + * support the SCSI Primary Block commands instead of Reduced Block Commands. + * + * - fix capacity + * Tell sd_mod to correct the last sector number reported by read_capacity. + * Avoids access beyond actual disk limits on devices with an off-by-one bug. + * Don't use this with devices which don't have this bug. + * + * - override internal blacklist + * Instead of adding to the built-in blacklist, use only the workarounds + * specified in the module load parameter. + * Useful if a blacklist entry interfered with a non-broken device. */ +static int sbp2_default_workarounds; +module_param_named(workarounds, sbp2_default_workarounds, int, 0644); +MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" + ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS) + ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) + ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) + ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) + ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) + ", or a combination)"); + +/* legacy parameter */ static int force_inquiry_hack; module_param(force_inquiry_hack, int, 0644); -MODULE_PARM_DESC(force_inquiry_hack, "Force SCSI inquiry hack (default = 0)"); +MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'"); /* * Export information about protocols/devices supported by this driver. @@ -266,14 +295,55 @@ static struct hpsb_protocol_driver sbp2_driver = { }; /* - * List of device firmwares that require the inquiry hack. - * Yields a few false positives but did not break other devices so far. + * List of devices with known bugs. + * + * The firmware_revision field, masked with 0xffff00, is the best indicator + * for the type of bridge chip of a device. It yields a few false positives + * but this did not break correctly behaving devices so far. */ -static u32 sbp2_broken_inquiry_list[] = { - 0x00002800, /* Stefan Richter <stefanr@s5r6.in-berlin.de> */ - /* DViCO Momobay CX-1 */ - 0x00000200 /* Andreas Plesch <plesch@fas.harvard.edu> */ - /* QPS Fire DVDBurner */ +static const struct { + u32 firmware_revision; + u32 model_id; + unsigned workarounds; +} sbp2_workarounds_table[] = { + /* TSB42AA9 */ { + .firmware_revision = 0x002800, + .workarounds = SBP2_WORKAROUND_INQUIRY_36 | + SBP2_WORKAROUND_MODE_SENSE_8, + }, + /* Initio bridges, actually only needed for some older ones */ { + .firmware_revision = 0x000200, + .workarounds = SBP2_WORKAROUND_INQUIRY_36, + }, + /* Symbios bridge */ { + .firmware_revision = 0xa0b800, + .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, + }, + /* + * Note about the following Apple iPod blacklist entries: + * + * There are iPods (2nd gen, 3rd gen) with model_id==0. Since our + * matching logic treats 0 as a wildcard, we cannot match this ID + * without rewriting the matching routine. Fortunately these iPods + * do not feature the read_capacity bug according to one report. + * Read_capacity behaviour as well as model_id could change due to + * Apple-supplied firmware updates though. + */ + /* iPod 4th generation */ { + .firmware_revision = 0x0a2700, + .model_id = 0x000021, + .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, + }, + /* iPod mini */ { + .firmware_revision = 0x0a2700, + .model_id = 0x000023, + .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, + }, + /* iPod Photo */ { + .firmware_revision = 0x0a2700, + .model_id = 0x00007e, + .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, + } }; /************************************** @@ -765,11 +835,16 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud /* Register the status FIFO address range. We could use the same FIFO * for targets at different nodes. However we need different FIFOs per - * target in order to support multi-unit devices. */ + * target in order to support multi-unit devices. + * The FIFO is located out of the local host controller's physical range + * but, if possible, within the posted write area. Status writes will + * then be performed as unified transactions. This slightly reduces + * bandwidth usage, and some Prolific based devices seem to require it. + */ scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace( &sbp2_highlevel, ud->ne->host, &sbp2_ops, sizeof(struct sbp2_status_block), sizeof(quadlet_t), - ~0ULL, ~0ULL); + 0x010000000000ULL, CSR1212_ALL_SPACE_END); if (!scsi_id->status_fifo_addr) { SBP2_ERR("failed to allocate status FIFO address range"); goto failed_alloc; @@ -1450,7 +1525,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, struct csr1212_dentry *dentry; u64 management_agent_addr; u32 command_set_spec_id, command_set, unit_characteristics, - firmware_revision, workarounds; + firmware_revision; + unsigned workarounds; int i; SBP2_DEBUG_ENTER(); @@ -1506,12 +1582,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, case SBP2_FIRMWARE_REVISION_KEY: /* Firmware revision */ firmware_revision = kv->value.immediate; - if (force_inquiry_hack) - SBP2_INFO("sbp2_firmware_revision = %x", - (unsigned int)firmware_revision); - else - SBP2_DEBUG("sbp2_firmware_revision = %x", - (unsigned int)firmware_revision); + SBP2_DEBUG("sbp2_firmware_revision = %x", + (unsigned int)firmware_revision); break; default: @@ -1519,41 +1591,44 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, } } - /* This is the start of our broken device checking. We try to hack - * around oddities and known defects. */ - workarounds = 0x0; + workarounds = sbp2_default_workarounds; + if (force_inquiry_hack) { + SBP2_WARN("force_inquiry_hack is deprecated. " + "Use parameter 'workarounds' instead."); + workarounds |= SBP2_WORKAROUND_INQUIRY_36; + } - /* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a - * bridge with 128KB max transfer size limitation. For sanity, we - * only voice this when the current max_sectors setting - * exceeds the 128k limit. By default, that is not the case. - * - * It would be really nice if we could detect this before the scsi - * host gets initialized. That way we can down-force the - * max_sectors to account for it. That is not currently - * possible. */ - if ((firmware_revision & 0xffff00) == - SBP2_128KB_BROKEN_FIRMWARE && - (max_sectors * 512) > (128*1024)) { - SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.", - NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid)); - SBP2_WARN("WARNING: Current max_sectors setting is larger than 128KB (%d sectors)!", - max_sectors); - workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER; - } - - /* Check for a blacklisted set of devices that require us to force - * a 36 byte host inquiry. This can be overriden as a module param - * (to force all hosts). */ - for (i = 0; i < ARRAY_SIZE(sbp2_broken_inquiry_list); i++) { - if ((firmware_revision & 0xffff00) == - sbp2_broken_inquiry_list[i]) { - SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround", - NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid)); - workarounds |= SBP2_BREAKAGE_INQUIRY_HACK; - break; /* No need to continue. */ + if (!(workarounds & SBP2_WORKAROUND_OVERRIDE)) + for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { + if (sbp2_workarounds_table[i].firmware_revision && + sbp2_workarounds_table[i].firmware_revision != + (firmware_revision & 0xffff00)) + continue; + if (sbp2_workarounds_table[i].model_id && + sbp2_workarounds_table[i].model_id != ud->model_id) + continue; + workarounds |= sbp2_workarounds_table[i].workarounds; + break; } - } + + if (workarounds) + SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x " + "(firmware_revision 0x%06x, vendor_id 0x%06x," + " model_id 0x%06x)", + NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), + workarounds, firmware_revision, + ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id, + ud->model_id); + + /* We would need one SCSI host template for each target to adjust + * max_sectors on the fly, therefore warn only. */ + if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && + (max_sectors * 512) > (128 * 1024)) + SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB " + "max transfer size. WARNING: Current max_sectors " + "setting is larger than 128KB (%d sectors)", + NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), + max_sectors); /* If this is a logical unit directory entry, process the parent * to get the values. */ @@ -2447,19 +2522,25 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev) scsi_id->sdev = sdev; - if (force_inquiry_hack || - scsi_id->workarounds & SBP2_BREAKAGE_INQUIRY_HACK) { + if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36) sdev->inquiry_len = 36; - sdev->skip_ms_page_8 = 1; - } return 0; } static int sbp2scsi_slave_configure(struct scsi_device *sdev) { + struct scsi_id_instance_data *scsi_id = + (struct scsi_id_instance_data *)sdev->host->hostdata[0]; + blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; + + if (sdev->type == TYPE_DISK && + scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) + sdev->skip_ms_page_8 = 1; + if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) + sdev->fix_capacity = 1; return 0; } @@ -2603,7 +2684,9 @@ static int sbp2_module_init(void) scsi_driver_template.cmd_per_lun = 1; } - /* Set max sectors (module load option). Default is 255 sectors. */ + if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && + (max_sectors * 512) > (128 * 1024)) + max_sectors = 128 * 1024 / 512; scsi_driver_template.max_sectors = max_sectors; /* Register our high level driver with 1394 stack */ diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index e2d357a9ea3a..f4ccc9d0fba4 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -227,11 +227,6 @@ struct sbp2_status_block { #define SBP2_SW_VERSION_ENTRY 0x00010483 /* - * Other misc defines - */ -#define SBP2_128KB_BROKEN_FIRMWARE 0xa0b800 - -/* * SCSI specific stuff */ @@ -239,6 +234,13 @@ struct sbp2_status_block { #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ #define SBP2_MAX_CMDS 8 /* This should be safe */ +/* Flags for detected oddities and brokeness */ +#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 +#define SBP2_WORKAROUND_INQUIRY_36 0x2 +#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 +#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 +#define SBP2_WORKAROUND_OVERRIDE 0x100 + /* This is the two dma types we use for cmd_dma below */ enum cmd_dma_types { CMD_DMA_NONE, @@ -268,10 +270,6 @@ struct sbp2_command_info { }; -/* A list of flags for detected oddities and brokeness. */ -#define SBP2_BREAKAGE_128K_MAX_TRANSFER 0x1 -#define SBP2_BREAKAGE_INQUIRY_HACK 0x2 - struct sbp2scsi_host_info; /* @@ -345,7 +343,7 @@ struct scsi_id_instance_data { struct Scsi_Host *scsi_host; /* Device specific workarounds/brokeness */ - u32 workarounds; + unsigned workarounds; }; /* Sbp2 host data structure (one per IEEE1394 host) */ diff --git a/drivers/infiniband/core/uverbs_mem.c b/drivers/infiniband/core/uverbs_mem.c index 36a32c315668..efe147dbeb42 100644 --- a/drivers/infiniband/core/uverbs_mem.c +++ b/drivers/infiniband/core/uverbs_mem.c @@ -211,8 +211,10 @@ void ib_umem_release_on_close(struct ib_device *dev, struct ib_umem *umem) */ work = kmalloc(sizeof *work, GFP_KERNEL); - if (!work) + if (!work) { + mmput(mm); return; + } INIT_WORK(&work->work, ib_umem_account, work); work->mm = mm; diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 1985b5dfa481..798e13e14faf 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -182,7 +182,7 @@ struct mthca_cmd_context { u8 status; }; -static int fw_cmd_doorbell = 1; +static int fw_cmd_doorbell = 0; module_param(fw_cmd_doorbell, int, 0644); MODULE_PARM_DESC(fw_cmd_doorbell, "post FW commands through doorbell page if nonzero " "(and supported by FW)"); diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 19765f6f8d58..07c13be07a4a 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -1727,23 +1727,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, ind = qp->rq.next_ind; - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) { - nreq = 0; - - doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0); - doorbell[1] = cpu_to_be32(qp->qpn << 8); - - wmb(); - - mthca_write64(doorbell, - dev->kar + MTHCA_RECEIVE_DOORBELL, - MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); - - qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB; - size0 = 0; - } - + for (nreq = 0; wr; wr = wr->next) { if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) { mthca_err(dev, "RQ %06x full (%u head, %u tail," " %d max, %d nreq)\n", qp->qpn, @@ -1797,6 +1781,23 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, ++ind; if (unlikely(ind >= qp->rq.max)) ind -= qp->rq.max; + + ++nreq; + if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) { + nreq = 0; + + doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0); + doorbell[1] = cpu_to_be32(qp->qpn << 8); + + wmb(); + + mthca_write64(doorbell, + dev->kar + MTHCA_RECEIVE_DOORBELL, + MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); + + qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB; + size0 = 0; + } } out: diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index c32ce4348e1b..9cbdffa08dc2 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -340,7 +340,10 @@ static void srp_disconnect_target(struct srp_target_port *target) /* XXX should send SRP_I_LOGOUT request */ init_completion(&target->done); - ib_send_cm_dreq(target->cm_id, NULL, 0); + if (ib_send_cm_dreq(target->cm_id, NULL, 0)) { + printk(KERN_DEBUG PFX "Sending CM DREQ failed\n"); + return; + } wait_for_completion(&target->done); } @@ -351,7 +354,6 @@ static void srp_remove_work(void *target_ptr) spin_lock_irq(target->scsi_host->host_lock); if (target->state != SRP_TARGET_DEAD) { spin_unlock_irq(target->scsi_host->host_lock); - scsi_host_put(target->scsi_host); return; } target->state = SRP_TARGET_REMOVED; @@ -365,8 +367,6 @@ static void srp_remove_work(void *target_ptr) ib_destroy_cm_id(target->cm_id); srp_free_target_ib(target); scsi_host_put(target->scsi_host); - /* And another put to really free the target port... */ - scsi_host_put(target->scsi_host); } static int srp_connect_target(struct srp_target_port *target) @@ -1241,7 +1241,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) list_for_each_entry_safe(req, tmp, &target->req_queue, list) if (req->scmnd->device == scmnd->device) { req->scmnd->result = DID_RESET << 16; - scmnd->scsi_done(scmnd); + req->scmnd->scsi_done(req->scmnd); srp_remove_req(target, req); } diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 3585fb1f3344..2ac90242d263 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -2880,7 +2880,7 @@ isdn_tty_cmd_ATand(char **p, modem_info * info) p[0]++; i = 0; while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) && - (i < ISDN_LMSNLEN)) + (i < ISDN_LMSNLEN - 1)) m->lmsn[i++] = *p[0]++; m->lmsn[i] = '\0'; break; diff --git a/drivers/md/md.c b/drivers/md/md.c index d7316b829a62..3ca3cfb03a7e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2252,7 +2252,7 @@ action_store(mddev_t *mddev, const char *page, size_t len) } else { if (cmd_match(page, "check")) set_bit(MD_RECOVERY_CHECK, &mddev->recovery); - else if (cmd_match(page, "repair")) + else if (!cmd_match(page, "repair")) return -EINVAL; set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); set_bit(MD_RECOVERY_SYNC, &mddev->recovery); diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index fffc711c260c..344d83aae3ec 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -8,22 +8,54 @@ config VIDEO_DEV tristate "Video For Linux" ---help--- Support for audio/video capture and overlay devices and FM radio - cards. The exact capabilities of each device vary. User tools for - this are available from - <ftp://ftp.uk.linux.org/pub/linux/video4linux/>. + cards. The exact capabilities of each device vary. This kernel includes support for the new Video for Linux Two API, (V4L2) as well as the original system. Drivers and applications need to be rewritten to use V4L2, but drivers for popular cards and applications for most video capture functions already exist. - Documentation for the original API is included in the file - <file:Documentation/video4linux/API.html>. Documentation for V4L2 is - available on the web at <http://bytesex.org/v4l/>. + Additional info and docs are available on the web at + <http://linuxtv.org> + + Documentation for V4L2 is also available on the web at + <http://bytesex.org/v4l/>. To compile this driver as a module, choose M here: the module will be called videodev. +config VIDEO_V4L1 + boolean "Enable Video For Linux API 1 (DEPRECATED)" + depends on VIDEO_DEV + select VIDEO_V4L1_COMPAT + default y + ---help--- + Enables a compatibility API used by most V4L2 devices to allow + its usage with legacy applications that supports only V4L1 api. + + If you are unsure as to whether this is required, answer Y. + +config VIDEO_V4L1_COMPAT + boolean "Enable Video For Linux API 1 compatible Layer" + depends on VIDEO_DEV + default y + ---help--- + This api were developed to be used at Kernel 2.2 and 2.4, but + lacks support for several video standards. There are several + drivers at kernel that still depends on it. + + Documentation for the original API is included in the file + <Documentation/video4linux/API.html>. + + User tools for this are available from + <ftp://ftp.uk.linux.org/pub/linux/video4linux/>. + + If you are unsure as to whether this is required, answer Y. + +config VIDEO_V4L2 + tristate + default y + source "drivers/media/video/Kconfig" source "drivers/media/radio/Kconfig" @@ -65,4 +97,3 @@ config USB_DABUSB module will be called dabusb. endmenu - diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 6a901a0268e1..9c45b983e0de 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -4,6 +4,7 @@ config VIDEO_SAA7146 config VIDEO_SAA7146_VV tristate + select VIDEO_V4L2 select VIDEO_BUF select VIDEO_VIDEOBUF select VIDEO_SAA7146 diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index 376ca48f1d1d..f28d721b8bb5 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -7,6 +7,7 @@ config DVB_BT8XX select DVB_CX24110 select DVB_OR51211 select DVB_LGDT330X + select DVB_ZL10353 select FW_LOADER help Support for PCI cards based on the Bt8xx PCI bridge. Examples are diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 71b575dc22bd..9325d039ea65 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -902,7 +902,10 @@ static int cinergyt2_probe (struct usb_interface *intf, return -ENOMEM; } - dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE); + if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) { + kfree(cinergyt2); + return err; + } cinergyt2->demux.priv = cinergyt2; cinergyt2->demux.filternum = 256; diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 4f8f257e6795..a051790161b0 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -106,6 +106,8 @@ struct dvb_frontend_private { unsigned long tune_mode_flags; unsigned int delay; unsigned int reinitialise; + int tone; + int voltage; /* swzigzag values */ unsigned int state; @@ -537,6 +539,12 @@ static int dvb_frontend_thread(void *data) if (fepriv->reinitialise) { dvb_frontend_init(fe); + if (fepriv->tone != -1) { + fe->ops->set_tone(fe, fepriv->tone); + } + if (fepriv->voltage != -1) { + fe->ops->set_voltage(fe, fepriv->voltage); + } fepriv->reinitialise = 0; } @@ -788,6 +796,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_SET_TONE: if (fe->ops->set_tone) { err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); + fepriv->tone = (fe_sec_tone_mode_t) parg; fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } @@ -796,6 +805,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_SET_VOLTAGE: if (fe->ops->set_voltage) { err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg); + fepriv->voltage = (fe_sec_voltage_t) parg; fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } @@ -995,6 +1005,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) /* normal tune mode when opened R/W */ fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; + fepriv->tone = -1; + fepriv->voltage = -1; } return ret; diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 96fe0ecae250..3852430d0260 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -219,8 +219,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, return -ENOMEM; } - mutex_unlock(&dvbdev_register_lock); - memcpy(dvbdev, template, sizeof(struct dvb_device)); dvbdev->type = type; dvbdev->id = id; @@ -231,6 +229,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, list_add_tail (&dvbdev->list_head, &adap->device_list); + mutex_unlock(&dvbdev_register_lock); + devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), S_IFCHR | S_IRUSR | S_IWUSR, "dvb/adapter%d/%s%d", adap->num, dnames[type], id); diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 7edd6362b9cc..1f0d3e995c8d 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -150,6 +150,15 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); } +static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 b = 0; + if (onoff) + return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0); + else + return 0; +} + static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff) { u8 buf[2] = { 0x03, 0x00 }; @@ -544,7 +553,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_lgdt3303_frontend_attach, .tuner_attach = cxusb_lgh064f_tuner_attach, @@ -589,7 +598,7 @@ static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_dee1601_frontend_attach, .tuner_attach = cxusb_dee1601_tuner_attach, @@ -638,7 +647,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_mt352_frontend_attach, .tuner_attach = cxusb_lgz201_tuner_attach, @@ -683,7 +692,7 @@ static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_mt352_frontend_attach, .tuner_attach = cxusb_dtt7579_tuner_attach, diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index d661c6f9cbe5..691dc840dcc0 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -29,6 +29,9 @@ #include "dvb_frontend.h" #include "cx24123.h" +#define XTAL 10111000 + +static int force_band; static int debug; #define dprintk(args...) \ do { \ @@ -52,6 +55,7 @@ struct cx24123_state u32 VGAarg; u32 bandselectarg; u32 pllarg; + u32 FILTune; /* The Demod/Tuner can't easily provide these, we cache them */ u32 currentfreq; @@ -63,43 +67,33 @@ static struct { u32 symbolrate_low; u32 symbolrate_high; - u32 VCAslope; - u32 VCAoffset; - u32 VGA1offset; - u32 VGA2offset; u32 VCAprogdata; u32 VGAprogdata; + u32 FILTune; } cx24123_AGC_vals[] = { { .symbolrate_low = 1000000, .symbolrate_high = 4999999, - .VCAslope = 0x07, - .VCAoffset = 0x0f, - .VGA1offset = 0x1f8, - .VGA2offset = 0x1f8, - .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8, - .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07, + /* the specs recommend other values for VGA offsets, + but tests show they are wrong */ + .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0, + .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x07, + .FILTune = 0x27f /* 0.41 V */ }, { .symbolrate_low = 5000000, .symbolrate_high = 14999999, - .VCAslope = 0x1f, - .VCAoffset = 0x1f, - .VGA1offset = 0x1e0, - .VGA2offset = 0x180, - .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, - .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f, + .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0, + .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x1f, + .FILTune = 0x317 /* 0.90 V */ }, { .symbolrate_low = 15000000, .symbolrate_high = 45000000, - .VCAslope = 0x3f, - .VCAoffset = 0x3f, - .VGA1offset = 0x180, - .VGA2offset = 0x100, - .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180, - .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f, + .VGAprogdata = (1 << 19) | (0x100 << 9) | 0x180, + .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x3f, + .FILTune = 0x145 /* 2.70 V */ }, }; @@ -112,91 +106,80 @@ static struct { u32 freq_low; u32 freq_high; - u32 bandselect; u32 VCOdivider; - u32 VCOnumber; u32 progdata; } cx24123_bandselect_vals[] = { + /* band 1 */ { .freq_low = 950000, - .freq_high = 1018999, - .bandselect = 0x40, - .VCOdivider = 4, - .VCOnumber = 7, - .progdata = (0 << 18) | (0 << 9) | 0x40, - }, - { - .freq_low = 1019000, .freq_high = 1074999, - .bandselect = 0x80, .VCOdivider = 4, - .VCOnumber = 8, - .progdata = (0 << 18) | (0 << 9) | 0x80, + .progdata = (0 << 19) | (0 << 9) | 0x40, }, + + /* band 2 */ { .freq_low = 1075000, - .freq_high = 1227999, - .bandselect = 0x01, - .VCOdivider = 2, - .VCOnumber = 1, - .progdata = (0 << 18) | (1 << 9) | 0x01, + .freq_high = 1177999, + .VCOdivider = 4, + .progdata = (0 << 19) | (0 << 9) | 0x80, }, + + /* band 3 */ { - .freq_low = 1228000, - .freq_high = 1349999, - .bandselect = 0x02, + .freq_low = 1178000, + .freq_high = 1295999, .VCOdivider = 2, - .VCOnumber = 2, - .progdata = (0 << 18) | (1 << 9) | 0x02, + .progdata = (0 << 19) | (1 << 9) | 0x01, }, + + /* band 4 */ { - .freq_low = 1350000, - .freq_high = 1481999, - .bandselect = 0x04, + .freq_low = 1296000, + .freq_high = 1431999, .VCOdivider = 2, - .VCOnumber = 3, - .progdata = (0 << 18) | (1 << 9) | 0x04, + .progdata = (0 << 19) | (1 << 9) | 0x02, }, + + /* band 5 */ { - .freq_low = 1482000, - .freq_high = 1595999, - .bandselect = 0x08, + .freq_low = 1432000, + .freq_high = 1575999, .VCOdivider = 2, - .VCOnumber = 4, - .progdata = (0 << 18) | (1 << 9) | 0x08, + .progdata = (0 << 19) | (1 << 9) | 0x04, }, + + /* band 6 */ { - .freq_low = 1596000, + .freq_low = 1576000, .freq_high = 1717999, - .bandselect = 0x10, .VCOdivider = 2, - .VCOnumber = 5, - .progdata = (0 << 18) | (1 << 9) | 0x10, + .progdata = (0 << 19) | (1 << 9) | 0x08, }, + + /* band 7 */ { .freq_low = 1718000, .freq_high = 1855999, - .bandselect = 0x20, .VCOdivider = 2, - .VCOnumber = 6, - .progdata = (0 << 18) | (1 << 9) | 0x20, + .progdata = (0 << 19) | (1 << 9) | 0x10, }, + + /* band 8 */ { .freq_low = 1856000, .freq_high = 2035999, - .bandselect = 0x40, .VCOdivider = 2, - .VCOnumber = 7, - .progdata = (0 << 18) | (1 << 9) | 0x40, + .progdata = (0 << 19) | (1 << 9) | 0x20, }, + + /* band 9 */ { .freq_low = 2036000, - .freq_high = 2149999, - .bandselect = 0x80, + .freq_high = 2150000, .VCOdivider = 2, - .VCOnumber = 8, - .progdata = (0 << 18) | (1 << 9) | 0x80, + .progdata = (0 << 19) | (1 << 9) | 0x40, }, }; @@ -207,49 +190,44 @@ static struct { { {0x00, 0x03}, /* Reset system */ {0x00, 0x00}, /* Clear reset */ - {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */ - {0x03, 0x07}, - {0x04, 0x10}, - {0x05, 0x04}, - {0x06, 0x31}, - {0x0d, 0x02}, - {0x0e, 0x03}, - {0x0f, 0xfe}, - {0x10, 0x01}, - {0x14, 0x01}, - {0x15, 0x98}, - {0x16, 0x00}, - {0x17, 0x01}, - {0x1b, 0x05}, - {0x1c, 0x80}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x20, 0x41}, - {0x21, 0x15}, - {0x27, 0x14}, - {0x28, 0x46}, - {0x29, 0x00}, - {0x2a, 0xb0}, - {0x2b, 0x73}, - {0x2c, 0x00}, + {0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */ + {0x04, 0x10}, /* MPEG */ + {0x05, 0x04}, /* MPEG */ + {0x06, 0x31}, /* MPEG (default) */ + {0x0b, 0x00}, /* Freq search start point (default) */ + {0x0c, 0x00}, /* Demodulator sample gain (default) */ + {0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */ + {0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */ + {0x0f, 0xfe}, /* FEC search mask (all supported codes) */ + {0x10, 0x01}, /* Default search inversion, no repeat (default) */ + {0x16, 0x00}, /* Enable reading of frequency */ + {0x17, 0x01}, /* Enable EsNO Ready Counter */ + {0x1c, 0x80}, /* Enable error counter */ + {0x20, 0x00}, /* Tuner burst clock rate = 500KHz */ + {0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */ + {0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */ + {0x29, 0x00}, /* DiSEqC LNB_DC off */ + {0x2a, 0xb0}, /* DiSEqC Parameters (default) */ + {0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */ + {0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */ {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00}, {0x30, 0x00}, {0x31, 0x00}, - {0x32, 0x8c}, - {0x33, 0x00}, + {0x32, 0x8c}, /* DiSEqC Parameters (default) */ + {0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */ {0x34, 0x00}, - {0x35, 0x03}, - {0x36, 0x02}, - {0x37, 0x3a}, - {0x3a, 0x00}, /* Enable AGC accumulator */ - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x05}, - {0x56, 0x41}, - {0x57, 0xff}, - {0x67, 0x83}, + {0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */ + {0x36, 0x02}, /* DiSEqC Parameters (default) */ + {0x37, 0x3a}, /* DiSEqC Parameters (default) */ + {0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */ + {0x44, 0x00}, /* Constellation (default) */ + {0x45, 0x00}, /* Symbol count (default) */ + {0x46, 0x0d}, /* Symbol rate estimator on (default) */ + {0x56, 0x41}, /* Various (default) */ + {0x57, 0xff}, /* Error Counter Window (default) */ + {0x67, 0x83}, /* Non-DCII symbol clock */ }; static int cx24123_writereg(struct cx24123_state* state, int reg, int data) @@ -258,6 +236,10 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data) struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; int err; + if (debug>1) + printk("cx24123: %s: write reg 0x%02x, value 0x%02x\n", + __FUNCTION__,reg, data); + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { printk("%s: writereg error(err == %i, reg == 0x%02x," " data == 0x%02x)\n", __FUNCTION__, err, reg, data); @@ -274,6 +256,10 @@ static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data) struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 }; int err; + if (debug>1) + printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n", + __FUNCTION__,reg, data); + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { printk("%s: writelnbreg error (err == %i, reg == 0x%02x," " data == 0x%02x)\n", __FUNCTION__, err, reg, data); @@ -303,6 +289,9 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg) return ret; } + if (debug>1) + printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret); + return b1[0]; } @@ -313,17 +302,23 @@ static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg) static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) { + u8 nom_reg = cx24123_readreg(state, 0x0e); + u8 auto_reg = cx24123_readreg(state, 0x10); + switch (inversion) { case INVERSION_OFF: - cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f); - cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); + dprintk("%s: inversion off\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg & ~0x80); + cx24123_writereg(state, 0x10, auto_reg | 0x80); break; case INVERSION_ON: - cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80); - cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); + dprintk("%s: inversion on\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x80); + cx24123_writereg(state, 0x10, auto_reg | 0x80); break; case INVERSION_AUTO: - cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f); + dprintk("%s: inversion auto\n",__FUNCTION__); + cx24123_writereg(state, 0x10, auto_reg & ~0x80); break; default: return -EINVAL; @@ -338,92 +333,191 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers val = cx24123_readreg(state, 0x1b) >> 7; - if (val == 0) + if (val == 0) { + dprintk("%s: read inversion off\n",__FUNCTION__); *inversion = INVERSION_OFF; - else + } else { + dprintk("%s: read inversion on\n",__FUNCTION__); *inversion = INVERSION_ON; + } return 0; } static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) { + u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07; + if ( (fec < FEC_NONE) || (fec > FEC_AUTO) ) fec = FEC_AUTO; - /* Hardware has 5/11 and 3/5 but are never unused */ switch (fec) { - case FEC_NONE: - return cx24123_writereg(state, 0x0f, 0x01); case FEC_1_2: - return cx24123_writereg(state, 0x0f, 0x02); + dprintk("%s: set FEC to 1/2\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x01); + cx24123_writereg(state, 0x0f, 0x02); + break; case FEC_2_3: - return cx24123_writereg(state, 0x0f, 0x04); + dprintk("%s: set FEC to 2/3\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x02); + cx24123_writereg(state, 0x0f, 0x04); + break; case FEC_3_4: - return cx24123_writereg(state, 0x0f, 0x08); + dprintk("%s: set FEC to 3/4\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x03); + cx24123_writereg(state, 0x0f, 0x08); + break; + case FEC_4_5: + dprintk("%s: set FEC to 4/5\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x04); + cx24123_writereg(state, 0x0f, 0x10); + break; case FEC_5_6: - return cx24123_writereg(state, 0x0f, 0x20); + dprintk("%s: set FEC to 5/6\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x05); + cx24123_writereg(state, 0x0f, 0x20); + break; + case FEC_6_7: + dprintk("%s: set FEC to 6/7\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x06); + cx24123_writereg(state, 0x0f, 0x40); + break; case FEC_7_8: - return cx24123_writereg(state, 0x0f, 0x80); + dprintk("%s: set FEC to 7/8\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x07); + cx24123_writereg(state, 0x0f, 0x80); + break; case FEC_AUTO: - return cx24123_writereg(state, 0x0f, 0xae); + dprintk("%s: set FEC to auto\n",__FUNCTION__); + cx24123_writereg(state, 0x0f, 0xfe); + break; default: return -EOPNOTSUPP; } + + return 0; } static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) { int ret; - u8 val; ret = cx24123_readreg (state, 0x1b); if (ret < 0) return ret; - val = ret & 0x07; - switch (val) { + ret = ret & 0x07; + + switch (ret) { case 1: *fec = FEC_1_2; break; - case 3: + case 2: *fec = FEC_2_3; break; - case 4: + case 3: *fec = FEC_3_4; break; - case 5: + case 4: *fec = FEC_4_5; break; - case 6: + case 5: *fec = FEC_5_6; break; + case 6: + *fec = FEC_6_7; + break; case 7: *fec = FEC_7_8; break; - case 2: /* *fec = FEC_3_5; break; */ - case 0: /* *fec = FEC_5_11; break; */ - *fec = FEC_AUTO; - break; default: - *fec = FEC_NONE; // can't happen + /* this can happen when there's no lock */ + *fec = FEC_NONE; } return 0; } -/* fixme: Symbol rates < 3MSps may not work because of precision loss */ +/* Approximation of closest integer of log2(a/b). It actually gives the + lowest integer i such that 2^i >= round(a/b) */ +static u32 cx24123_int_log2(u32 a, u32 b) +{ + u32 exp, nearest = 0; + u32 div = a / b; + if(a % b >= b / 2) ++div; + if(div < (1 << 31)) + { + for(exp = 1; div > exp; nearest++) + exp += exp; + } + return nearest; +} + static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) { - u32 val; + u32 tmp, sample_rate, ratio, sample_gain; + u8 pll_mult; + + /* check if symbol rate is within limits */ + if ((srate > state->ops.info.symbol_rate_max) || + (srate < state->ops.info.symbol_rate_min)) + return -EOPNOTSUPP;; + + /* choose the sampling rate high enough for the required operation, + while optimizing the power consumed by the demodulator */ + if (srate < (XTAL*2)/2) + pll_mult = 2; + else if (srate < (XTAL*3)/2) + pll_mult = 3; + else if (srate < (XTAL*4)/2) + pll_mult = 4; + else if (srate < (XTAL*5)/2) + pll_mult = 5; + else if (srate < (XTAL*6)/2) + pll_mult = 6; + else if (srate < (XTAL*7)/2) + pll_mult = 7; + else if (srate < (XTAL*8)/2) + pll_mult = 8; + else + pll_mult = 9; + + + sample_rate = pll_mult * XTAL; + + /* + SYSSymbolRate[21:0] = (srate << 23) / sample_rate + + We have to use 32 bit unsigned arithmetic without precision loss. + The maximum srate is 45000000 or 0x02AEA540. This number has + only 6 clear bits on top, hence we can shift it left only 6 bits + at a time. Borrowed from cx24110.c + */ + + tmp = srate << 6; + ratio = tmp / sample_rate; + + tmp = (tmp % sample_rate) << 6; + ratio = (ratio << 6) + (tmp / sample_rate); + + tmp = (tmp % sample_rate) << 6; + ratio = (ratio << 6) + (tmp / sample_rate); + + tmp = (tmp % sample_rate) << 5; + ratio = (ratio << 5) + (tmp / sample_rate); + + + cx24123_writereg(state, 0x01, pll_mult * 6); - val = (srate / 1185) * 100; + cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f ); + cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff ); + cx24123_writereg(state, 0x0a, (ratio ) & 0xff ); - /* Compensate for scaling up, by removing 17 symbols per 1Msps */ - val = val - (17 * (srate / 1000000)); + /* also set the demodulator sample gain */ + sample_gain = cx24123_int_log2(sample_rate, srate); + tmp = cx24123_readreg(state, 0x0c) & ~0xe0; + cx24123_writereg(state, 0x0c, tmp | sample_gain << 5); - cx24123_writereg(state, 0x08, (val >> 16) & 0xff ); - cx24123_writereg(state, 0x09, (val >> 8) & 0xff ); - cx24123_writereg(state, 0x0a, (val ) & 0xff ); + dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain); return 0; } @@ -437,6 +531,9 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa struct cx24123_state *state = fe->demodulator_priv; u32 ndiv = 0, adiv = 0, vco_div = 0; int i = 0; + int pump = 2; + int band = 0; + int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); /* Defaults for low freq, low rate */ state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; @@ -444,38 +541,49 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa state->bandselectarg = cx24123_bandselect_vals[0].progdata; vco_div = cx24123_bandselect_vals[0].VCOdivider; - /* For the given symbolerate, determine the VCA and VGA programming bits */ + /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */ for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) { if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && - (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { + (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; + state->FILTune = cx24123_AGC_vals[i].FILTune; } } - /* For the given frequency, determine the bandselect programming bits */ - for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++) + /* determine the band to use */ + if(force_band < 1 || force_band > num_bands) { - if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && - (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { - state->bandselectarg = cx24123_bandselect_vals[i].progdata; - vco_div = cx24123_bandselect_vals[i].VCOdivider; + for (i = 0; i < num_bands; i++) + { + if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && + (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) + band = i; } } + else + band = force_band - 1; + + state->bandselectarg = cx24123_bandselect_vals[band].progdata; + vco_div = cx24123_bandselect_vals[band].VCOdivider; + + /* determine the charge pump current */ + if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 ) + pump = 0x01; + else + pump = 0x02; /* Determine the N/A dividers for the requested lband freq (in kHz). */ - /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */ - ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff; - adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f; + /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */ + ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff; + adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f; if (adiv == 0) - adiv++; + ndiv++; - /* determine the correct pll frequency values. */ - /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */ - state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14); - state->pllarg |= (ndiv << 5) | adiv; + /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */ + state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv; return 0; } @@ -489,6 +597,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par struct cx24123_state *state = fe->demodulator_priv; unsigned long timeout; + dprintk("%s: pll writereg called, data=0x%08x\n",__FUNCTION__,data); + /* align the 21 bytes into to bit23 boundary */ data = data << 3; @@ -538,6 +648,9 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { struct cx24123_state *state = fe->demodulator_priv; + u8 val; + + dprintk("frequency=%i\n", p->frequency); if (cx24123_pll_calculate(fe, p) != 0) { printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); @@ -552,6 +665,14 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet cx24123_pll_writereg(fe, p, state->bandselectarg); cx24123_pll_writereg(fe, p, state->pllarg); + /* set the FILTUNE voltage */ + val = cx24123_readreg(state, 0x28) & ~0x3; + cx24123_writereg(state, 0x27, state->FILTune >> 2); + cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3)); + + dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg, + state->bandselectarg,state->pllarg); + return 0; } @@ -560,6 +681,8 @@ static int cx24123_initfe(struct dvb_frontend* fe) struct cx24123_state *state = fe->demodulator_priv; int i; + dprintk("%s: init frontend\n",__FUNCTION__); + /* Configure the demod to a good set of defaults */ for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); @@ -587,10 +710,13 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage switch (voltage) { case SEC_VOLTAGE_13: + dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */ case SEC_VOLTAGE_18: + dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */ case SEC_VOLTAGE_OFF: + dprintk("%s: isl5421 voltage off\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val & 0x30); default: return -EINVAL; @@ -624,13 +750,93 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage return 0; } -static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, - struct dvb_diseqc_master_cmd *cmd) +/* wait for diseqc queue to become ready (or timeout) */ +static void cx24123_wait_for_diseqc(struct cx24123_state *state) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(200); + while (!(cx24123_readreg(state, 0x29) & 0x40)) { + if(time_after(jiffies, timeout)) { + printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__); + break; + } + msleep(10); + } +} + +static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) { - /* fixme: Implement diseqc */ - printk("%s: No support yet\n",__FUNCTION__); + struct cx24123_state *state = fe->demodulator_priv; + int i, val; + + dprintk("%s:\n",__FUNCTION__); + + /* check if continuous tone has been stopped */ + if (state->config->use_isl6421) + val = cx24123_readlnbreg(state, 0x00) & 0x10; + else + val = cx24123_readreg(state, 0x29) & 0x10; - return -ENOTSUPP; + + if (val) { + printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); + return -ENOTSUPP; + } + + /* wait for diseqc queue ready */ + cx24123_wait_for_diseqc(state); + + /* select tone mode */ + cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8); + + for (i = 0; i < cmd->msg_len; i++) + cx24123_writereg(state, 0x2C + i, cmd->msg[i]); + + val = cx24123_readreg(state, 0x29); + cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); + + /* wait for diseqc message to finish sending */ + cx24123_wait_for_diseqc(state); + + return 0; +} + +static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) +{ + struct cx24123_state *state = fe->demodulator_priv; + int val; + + dprintk("%s:\n", __FUNCTION__); + + /* check if continuous tone has been stoped */ + if (state->config->use_isl6421) + val = cx24123_readlnbreg(state, 0x00) & 0x10; + else + val = cx24123_readreg(state, 0x29) & 0x10; + + + if (val) { + printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); + return -ENOTSUPP; + } + + cx24123_wait_for_diseqc(state); + + /* select tone mode */ + val = cx24123_readreg(state, 0x2a) & 0xf8; + cx24123_writereg(state, 0x2a, val | 0x04); + + val = cx24123_readreg(state, 0x29); + + if (burst == SEC_MINI_A) + cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00)); + else if (burst == SEC_MINI_B) + cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08)); + else + return -EINVAL; + + cx24123_wait_for_diseqc(state); + + return 0; } static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) @@ -642,13 +848,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) *status = 0; if (lock & 0x01) - *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; + *status |= FE_HAS_SIGNAL; + if (sync & 0x02) + *status |= FE_HAS_CARRIER; if (sync & 0x04) *status |= FE_HAS_VITERBI; if (sync & 0x08) - *status |= FE_HAS_CARRIER; + *status |= FE_HAS_SYNC; if (sync & 0x80) - *status |= FE_HAS_SYNC | FE_HAS_LOCK; + *status |= FE_HAS_LOCK; return 0; } @@ -681,6 +889,8 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber) else state->snr = 0; + dprintk("%s: BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr); + *ber = state->lastber; return 0; @@ -691,6 +901,8 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str struct cx24123_state *state = fe->demodulator_priv; *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */ + dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength); + return 0; } @@ -699,6 +911,8 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr) struct cx24123_state *state = fe->demodulator_priv; *snr = state->snr; + dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr); + return 0; } @@ -707,6 +921,8 @@ static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) struct cx24123_state *state = fe->demodulator_priv; *ucblocks = state->lastber; + dprintk("%s: ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks); + return 0; } @@ -714,6 +930,8 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par { struct cx24123_state *state = fe->demodulator_priv; + dprintk("%s: set_frontend\n",__FUNCTION__); + if (state->config->set_ts_params) state->config->set_ts_params(fe, 0); @@ -737,6 +955,8 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par { struct cx24123_state *state = fe->demodulator_priv; + dprintk("%s: get_frontend\n",__FUNCTION__); + if (cx24123_get_inversion(state, &p->inversion) != 0) { printk("%s: Failed to get inversion status\n",__FUNCTION__); return -EREMOTEIO; @@ -763,8 +983,10 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) switch (tone) { case SEC_TONE_ON: + dprintk("%s: isl6421 sec tone on\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val | 0x10); case SEC_TONE_OFF: + dprintk("%s: isl6421 sec tone off\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val & 0x2f); default: printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); @@ -855,12 +1077,13 @@ static struct dvb_frontend_ops cx24123_ops = { .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = 1011, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, + .frequency_tolerance = 5000, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_RECOVER }, @@ -875,12 +1098,16 @@ static struct dvb_frontend_ops cx24123_ops = { .read_snr = cx24123_read_snr, .read_ucblocks = cx24123_read_ucblocks, .diseqc_send_master_cmd = cx24123_send_diseqc_msg, + .diseqc_send_burst = cx24123_diseqc_send_burst, .set_tone = cx24123_set_tone, .set_voltage = cx24123_set_voltage, }; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +module_param(force_band, int, 0644); +MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off)."); MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware"); MODULE_AUTHOR("Steven Toth"); diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b6e2c387a04c..791706ec1da3 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -235,8 +235,8 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = { .max = 863000000, .count = 3, .entries = { - { 160000000, 44000000, 62500, 0xce, 0x01 }, - { 455000000, 44000000, 62500, 0xce, 0x02 }, + { 165000000, 44000000, 62500, 0xce, 0x01 }, + { 450000000, 44000000, 62500, 0xce, 0x02 }, { 999999999, 44000000, 62500, 0xce, 0x04 }, }, }; diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile index 86ca84b2be6e..ce6a9aaf937e 100644 --- a/drivers/media/dvb/pluto2/Makefile +++ b/drivers/media/dvb/pluto2/Makefile @@ -1,3 +1,3 @@ -obj-$(CONFIG_DVB_PLUTO2) = pluto2.o +obj-$(CONFIG_DVB_PLUTO2) += pluto2.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 5b2aadb8385c..c26e23291511 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -1,8 +1,7 @@ config DVB_AV7110 tristate "AV7110 cards" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select FW_LOADER - select VIDEO_DEV select VIDEO_SAA7146_VV select DVB_VES1820 select DVB_VES1X93 @@ -59,7 +58,7 @@ config DVB_AV7110_OSD config DVB_BUDGET tristate "Budget cards" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0299 select DVB_VES1X93 @@ -80,7 +79,7 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0297 select DVB_STV0299 @@ -100,8 +99,7 @@ config DVB_BUDGET_CI config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" - depends on DVB_CORE && PCI - select VIDEO_DEV + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select DVB_STV0299 select DVB_TDA1004X @@ -119,7 +117,7 @@ config DVB_BUDGET_AV config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" - depends on DVB_CORE && DVB_BUDGET + depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1 select DVB_AV7110 select DVB_STV0299 select DVB_VES1X93 diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 8efe3ce5f66c..8a7cd7d505cf 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1190,8 +1190,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio SAA7146_HPS_SYNC_PORT_A); saa7113_setinput(budget_av, 0); - } else { - ciintf_init(budget_av); } /* fixme: find some sane values here... */ @@ -1211,6 +1209,10 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); + if (!budget_av->has_saa7113) { + ciintf_init(budget_av); + } + return 0; } diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 5f91036f5b87..e64a609cf4ff 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -71,6 +71,7 @@ struct budget_ci { struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet; int slot_status; + int ci_irq; struct dvb_ca_en50221 ca; char ir_dev_name[50]; u8 tuner_pll_address; /* used for philips_tdm1316l configs */ @@ -276,8 +277,10 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) if (slot != 0) return -EINVAL; - // trigger on RISING edge during reset so we know when READY is re-asserted - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + if (budget_ci->ci_irq) { + // trigger on RISING edge during reset so we know when READY is re-asserted + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } budget_ci->slot_status = SLOTSTATUS_RESET; ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); @@ -370,11 +373,50 @@ static void ciintf_interrupt(unsigned long data) } } +static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct budget_ci *budget_ci = (struct budget_ci *) ca->data; + unsigned int flags; + + // ensure we don't get spurious IRQs during initialisation + if (!budget_ci->budget.ci_present) + return -EINVAL; + + // read the CAM status + flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); + if (flags & CICONTROL_CAMDETECT) { + // mark it as present if it wasn't before + if (budget_ci->slot_status & SLOTSTATUS_NONE) { + budget_ci->slot_status = SLOTSTATUS_PRESENT; + } + + // during a RESET, we check if we can read from IO memory to see when CAM is ready + if (budget_ci->slot_status & SLOTSTATUS_RESET) { + if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) { + budget_ci->slot_status = SLOTSTATUS_READY; + } + } + } else { + budget_ci->slot_status = SLOTSTATUS_NONE; + } + + if (budget_ci->slot_status != SLOTSTATUS_NONE) { + if (budget_ci->slot_status & SLOTSTATUS_READY) { + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + } + return DVB_CA_EN50221_POLL_CAM_PRESENT; + } + + return 0; +} + static int ciintf_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; int flags; int result; + int ci_version; + int ca_flags; memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); @@ -382,16 +424,29 @@ static int ciintf_init(struct budget_ci *budget_ci) saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); // test if it is there - if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) { + ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); + if ((ci_version & 0xa0) != 0xa0) { result = -ENODEV; goto error; } + // determine whether a CAM is present or not flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); budget_ci->slot_status = SLOTSTATUS_NONE; if (flags & CICONTROL_CAMDETECT) budget_ci->slot_status = SLOTSTATUS_PRESENT; + // version 0xa2 of the CI firmware doesn't generate interrupts + if (ci_version == 0xa2) { + ca_flags = 0; + budget_ci->ci_irq = 0; + } else { + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | + DVB_CA_EN50221_FLAG_IRQ_FR | + DVB_CA_EN50221_FLAG_IRQ_DA; + budget_ci->ci_irq = 1; + } + // register CI interface budget_ci->ca.owner = THIS_MODULE; budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem; @@ -401,23 +456,27 @@ static int ciintf_init(struct budget_ci *budget_ci) budget_ci->ca.slot_reset = ciintf_slot_reset; budget_ci->ca.slot_shutdown = ciintf_slot_shutdown; budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable; + budget_ci->ca.poll_slot_status = ciintf_poll_slot_status; budget_ci->ca.data = budget_ci; if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter, &budget_ci->ca, - DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | - DVB_CA_EN50221_FLAG_IRQ_FR | - DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) { + ca_flags, 1)) != 0) { printk("budget_ci: CI interface detected, but initialisation failed.\n"); goto error; } + // Setup CI slot IRQ - tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); - if (budget_ci->slot_status != SLOTSTATUS_NONE) { - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); - } else { - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + if (budget_ci->ci_irq) { + tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); + if (budget_ci->slot_status != SLOTSTATUS_NONE) { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); + } else { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); } - saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); + + // enable interface ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET, 1, 0); @@ -426,10 +485,12 @@ static int ciintf_init(struct budget_ci *budget_ci) budget_ci->budget.ci_present = 1; // forge a fake CI IRQ so the CAM state is setup correctly - flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; - if (budget_ci->slot_status != SLOTSTATUS_NONE) - flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; - dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); + if (budget_ci->ci_irq) { + flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; + if (budget_ci->slot_status != SLOTSTATUS_NONE) + flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); + } return 0; @@ -443,9 +504,13 @@ static void ciintf_deinit(struct budget_ci *budget_ci) struct saa7146_dev *saa = budget_ci->budget.dev; // disable CI interrupts - saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); - saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); - tasklet_kill(&budget_ci->ciintf_irq_tasklet); + if (budget_ci->ci_irq) { + saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); + saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); + tasklet_kill(&budget_ci->ciintf_irq_tasklet); + } + + // reset interface ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, @@ -473,7 +538,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) if (*isr & MASK_10) ttpci_budget_irq10_handler(dev, isr); - if ((*isr & MASK_03) && (budget_ci->budget.ci_present)) + if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq)) tasklet_schedule(&budget_ci->ciintf_irq_tasklet); } diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 248fdc7accfb..6ceae38125c7 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1507,7 +1507,11 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i mutex_unlock(&ttusb->semi2c); - dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); + if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) { + ttusb_free_iso_urbs(ttusb); + kfree(ttusb); + return result; + } ttusb->adapter.priv = ttusb; /* i2c */ diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index d318be383de6..3fff75763693 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -7,7 +7,7 @@ menu "Radio Adapters" config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these AM/FM radio cards, and then fill in the port address below. @@ -25,7 +25,7 @@ config RADIO_CADET config RADIO_RTRACK tristate "AIMSlab RadioTrack (aka RadioReveal) support" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address below. @@ -59,7 +59,7 @@ config RADIO_RTRACK_PORT config RADIO_RTRACK2 tristate "AIMSlab RadioTrack II support" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have this FM radio card, and then fill in the port address below. @@ -82,7 +82,7 @@ config RADIO_RTRACK2_PORT config RADIO_AZTECH tristate "Aztech/Packard Bell Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address below. @@ -106,7 +106,7 @@ config RADIO_AZTECH_PORT config RADIO_GEMTEK tristate "GemTek Radio Card support" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have this FM radio card, and then fill in the port address below. @@ -131,7 +131,7 @@ config RADIO_GEMTEK_PORT config RADIO_GEMTEK_PCI tristate "GemTek PCI Radio Card support" - depends on VIDEO_DEV && PCI + depends on VIDEO_V4L1 && PCI ---help--- Choose Y here if you have this PCI FM radio card. @@ -145,7 +145,7 @@ config RADIO_GEMTEK_PCI config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio" - depends on VIDEO_DEV && PCI + depends on VIDEO_V4L1 && PCI ---help--- Choose Y here if you have this radio card. This card may also be found as Gemtek PCI FM. @@ -160,7 +160,7 @@ config RADIO_MAXIRADIO config RADIO_MAESTRO tristate "Maestro on board radio" - depends on VIDEO_DEV + depends on VIDEO_V4L1 ---help--- Say Y here to directly support the on-board radio tuner on the Maestro 2 or 2E sound card. @@ -175,7 +175,7 @@ config RADIO_MAESTRO config RADIO_MIROPCM20 tristate "miroSOUND PCM20 radio" - depends on ISA && VIDEO_DEV && SOUND_ACI_MIXER + depends on ISA && VIDEO_V4L1 && SOUND_ACI_MIXER ---help--- Choose Y here if you have this FM radio card. You also need to say Y to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound") @@ -208,7 +208,7 @@ config RADIO_MIROPCM20_RDS config RADIO_SF16FMI tristate "SF16FMI Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards. If you compile the driver into the kernel and your card is not PnP one, you @@ -225,7 +225,7 @@ config RADIO_SF16FMI config RADIO_SF16FMR2 tristate "SF16FMR2 Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards. @@ -239,7 +239,7 @@ config RADIO_SF16FMR2 config RADIO_TERRATEC tristate "TerraTec ActiveRadio ISA Standalone" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have this FM radio card, and then fill in the port address below. (TODO) @@ -268,7 +268,7 @@ config RADIO_TERRATEC_PORT config RADIO_TRUST tristate "Trust FM radio card" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 help This is a driver for the Trust FM radio cards. Say Y if you have such a card and want to use it under Linux. @@ -286,7 +286,7 @@ config RADIO_TRUST_PORT config RADIO_TYPHOON tristate "Typhoon Radio (a.k.a. EcoRadio)" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address and the frequency used for muting below. @@ -330,7 +330,7 @@ config RADIO_TYPHOON_MUTEFREQ config RADIO_ZOLTRIX tristate "Zoltrix Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address below. diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 85888a8a93c9..7124e534cc7f 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -2,10 +2,10 @@ # Multimedia Video device configuration # -menu "Video For Linux" +menu "Video Capture Adapters" depends on VIDEO_DEV -comment "Video Adapters" +comment "Video Capture Adapters" config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" @@ -16,11 +16,23 @@ config VIDEO_ADV_DEBUG V4L devices. In doubt, say N. +config VIDEO_VIVI + tristate "Virtual Video Driver" + depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 + select VIDEO_BUF + default n + ---help--- + Enables a virtual video driver. This device shows a color bar + and a timestamp, as a real device would generate by using V4L2 + api. + Say Y here if you want to test video apps or debug V4L devices. + In doubt, say N. + source "drivers/media/video/bt8xx/Kconfig" config VIDEO_SAA6588 tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" - depends on VIDEO_DEV && I2C && VIDEO_BT848 + depends on I2C && VIDEO_BT848 help Support for Radio Data System (RDS) decoder. This allows seeing @@ -32,7 +44,7 @@ config VIDEO_SAA6588 config VIDEO_PMS tristate "Mediavision Pro Movie Studio Video For Linux" - depends on VIDEO_DEV && ISA + depends on ISA && VIDEO_V4L1 help Say Y if you have such a thing. @@ -41,7 +53,7 @@ config VIDEO_PMS config VIDEO_PLANB tristate "PlanB Video-In on PowerMac" - depends on PPC_PMAC && VIDEO_DEV && BROKEN + depends on PPC_PMAC && VIDEO_V4L1 && BROKEN help PlanB is the V4L driver for the PowerMac 7x00/8x00 series video input hardware. If you want to experiment with this, say Y. @@ -52,7 +64,7 @@ config VIDEO_PLANB config VIDEO_BWQCAM tristate "Quickcam BW Video For Linux" - depends on VIDEO_DEV && PARPORT + depends on PARPORT && VIDEO_V4L1 help Say Y have if you the black and white version of the QuickCam camera. See the next option for the color version. @@ -62,7 +74,7 @@ config VIDEO_BWQCAM config VIDEO_CQCAM tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" - depends on EXPERIMENTAL && VIDEO_DEV && PARPORT + depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1 help This is the video4linux driver for the colour version of the Connectix QuickCam. If you have one of these cameras, say Y here, @@ -73,7 +85,7 @@ config VIDEO_CQCAM config VIDEO_W9966 tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" - depends on PARPORT_1284 && VIDEO_DEV && PARPORT + depends on PARPORT_1284 && PARPORT && VIDEO_V4L1 help Video4linux driver for Winbond's w9966 based Webcams. Currently tested with the LifeView FlyCam Supra. @@ -86,7 +98,7 @@ config VIDEO_W9966 config VIDEO_CPIA tristate "CPiA Video For Linux" - depends on VIDEO_DEV + depends on VIDEO_V4L1 ---help--- This is the video4linux driver for cameras based on Vision's CPiA (Colour Processor Interface ASIC), such as the Creative Labs Video @@ -123,7 +135,7 @@ source "drivers/media/video/cpia2/Kconfig" config VIDEO_SAA5246A tristate "SAA5246A, SAA5281 Teletext processor" - depends on VIDEO_DEV && I2C + depends on I2C && VIDEO_V4L1 help Support for I2C bus based teletext using the SAA5246A or SAA5281 chip. Useful only if you live in Europe. @@ -150,7 +162,7 @@ config TUNER_3036 config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" - depends on VIDEO_DEV && I2C && SGI_IP22 && EXPERIMENTAL + depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L1 select I2C_ALGO_SGI help Say Y here to build in support for the Vino video input system found @@ -158,7 +170,7 @@ config VIDEO_VINO config VIDEO_STRADIS tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && VIDEO_DEV && PCI + depends on EXPERIMENTAL && PCI && VIDEO_V4L1 help Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video driver for PCI. There is a product page at @@ -166,7 +178,7 @@ config VIDEO_STRADIS config VIDEO_ZORAN tristate "Zoran ZR36057/36067 Video For Linux" - depends on VIDEO_DEV && PCI && I2C_ALGOBIT + depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 help Say Y for support for MJPEG capture cards based on the Zoran 36057/36067 PCI controller chipset. This includes the Iomega @@ -214,7 +226,7 @@ config VIDEO_ZORAN_LML33R10 config VIDEO_ZR36120 tristate "Zoran ZR36120/36125 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && BROKEN + depends on PCI && I2C && VIDEO_V4L1 && BROKEN help Support for ZR36120/ZR36125 based frame grabber/overlay boards. This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV, @@ -226,7 +238,7 @@ config VIDEO_ZR36120 config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" - depends on VIDEO_DEV && PCI && SONYPI + depends on PCI && SONYPI && VIDEO_V4L1 ---help--- This is the video4linux driver for the Motion Eye camera found in the Vaio Picturebook laptops. Please read the material in @@ -242,7 +254,7 @@ source "drivers/media/video/saa7134/Kconfig" config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select VIDEO_TUNER ---help--- @@ -254,8 +266,9 @@ config VIDEO_MXB config VIDEO_DPC tristate "Philips-Semiconductors 'dpc7146 demonstration board'" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV + select VIDEO_V4L2 ---help--- This is a video4linux driver for the 'dpc7146 demonstration board' by Philips-Semiconductors. It's the reference design @@ -268,8 +281,9 @@ config VIDEO_DPC config VIDEO_HEXIUM_ORION tristate "Hexium HV-PCI6 and Orion frame grabber" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV + select VIDEO_V4L2 ---help--- This is a video4linux driver for the Hexium HV-PCI6 and Orion frame grabber cards by Hexium. @@ -279,8 +293,9 @@ config VIDEO_HEXIUM_ORION config VIDEO_HEXIUM_GEMINI tristate "Hexium Gemini frame grabber" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV + select VIDEO_V4L2 ---help--- This is a video4linux driver for the Hexium Gemini frame grabber card by Hexium. Please note that the Gemini Dual @@ -293,7 +308,7 @@ source "drivers/media/video/cx88/Kconfig" config VIDEO_OVCAMCHIP tristate "OmniVision Camera Chip support" - depends on VIDEO_DEV && I2C + depends on I2C && VIDEO_V4L1 ---help--- Support for the OmniVision OV6xxx and OV7xxx series of camera chips. This driver is intended to be used with the ov511 and w9968cf USB @@ -304,7 +319,7 @@ config VIDEO_OVCAMCHIP config VIDEO_M32R_AR tristate "AR devices" - depends on M32R + depends on M32R && VIDEO_V4L1 ---help--- This is a video4linux driver for the Renesas AR (Artificial Retina) camera module. @@ -365,17 +380,17 @@ config VIDEO_WM8739 source "drivers/media/video/cx25840/Kconfig" config VIDEO_SAA711X - tristate "Philips SAA7113/4/5 video decoders" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)" + depends on VIDEO_V4L1 && I2C && EXPERIMENTAL ---help--- - Support for the Philips SAA7113/4/5 video decoders. + Old support for the Philips SAA7113/4 video decoders. To compile this driver as a module, choose M here: the module will be called saa7115. config VIDEO_SAA7127 tristate "Philips SAA7127/9 digital video encoders" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL ---help--- Support for the Philips SAA7127/9 digital video encoders. @@ -384,7 +399,7 @@ config VIDEO_SAA7127 config VIDEO_UPD64031A tristate "NEC Electronics uPD64031A Ghost Reduction" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL ---help--- Support for the NEC Electronics uPD64031A Ghost Reduction video chip. It is most often found in NTSC TV cards made for @@ -396,7 +411,7 @@ config VIDEO_UPD64031A config VIDEO_UPD64083 tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL ---help--- Support for the NEC Electronics uPD64083 3-Dimensional Y/C separation video chip. It is used to improve the quality of @@ -418,7 +433,7 @@ source "drivers/media/video/em28xx/Kconfig" config USB_DSBR tristate "D-Link USB FM radio support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL + depends on USB && VIDEO_V4L1 && EXPERIMENTAL ---help--- Say Y here if you want to connect this type of radio to your computer's USB port. Note that the audio is not digital, and @@ -434,7 +449,7 @@ source "drivers/media/video/et61x251/Kconfig" config USB_OV511 tristate "USB OV511 Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See <file:Documentation/video4linux/ov511.txt> @@ -445,7 +460,7 @@ config USB_OV511 config USB_SE401 tristate "USB SE401 Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See <file:Documentation/video4linux/se401.txt> @@ -458,7 +473,7 @@ source "drivers/media/video/sn9c102/Kconfig" config USB_STV680 tristate "USB STV680 (Pencam) Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. This includes the Pencam line of cameras. @@ -470,7 +485,7 @@ config USB_STV680 config USB_W9968CF tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_DEV && I2C + depends on USB && VIDEO_V4L1 && I2C select VIDEO_OVCAMCHIP ---help--- Say Y here if you want support for cameras based on OV681 or diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index b3ea2d63db9b..9debef9be8c8 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -10,7 +10,8 @@ tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ msp3400-objs := msp3400-driver.o msp3400-kthreads.o -obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o +obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o +obj-$(CONFIG_VIDEO_V4L1_COMPAT) += v4l1-compat.o obj-$(CONFIG_VIDEO_BT848) += bt8xx/ obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o @@ -84,4 +85,8 @@ obj-$(CONFIG_USB_IBMCAM) += usbvideo/ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ obj-$(CONFIG_USB_VICAM) += usbvideo/ +obj-$(CONFIG_VIDEO_VIVI) += vivi.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT + diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 085477c12612..153f6a4a96c9 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile index db641a36b197..a096a03418aa 100644 --- a/drivers/media/video/bt8xx/Makefile +++ b/drivers/media/video/bt8xx/Makefile @@ -8,5 +8,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ obj-$(CONFIG_VIDEO_BT848) += bttv.o -EXTRA_CFLAGS += -I$(src)/.. +EXTRA_CFLAGS += -Idrivers/media/video EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index f209a7492051..2b64aa835b42 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -2991,13 +2991,13 @@ void __devinit bttv_idcard(struct bttv *btv) if (UNSET != audiomux[0]) { gpiobits = 0; - for (i = 0; i < 5; i++) { + for (i = 0; i < 4; i++) { bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i]; gpiobits |= audiomux[i]; } } else { gpiobits = audioall; - for (i = 0; i < 5; i++) { + for (i = 0; i < 4; i++) { bttv_tvcards[btv->c.type].gpiomux[i] = audioall; } } diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index 16323a5d68ac..afcfe71e3792 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c @@ -233,7 +233,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, const struct bttv_format *fmt, struct bttv_overlay *ov, int skip_even, int skip_odd) { - int instructions,rc,line,maxy,start,end,skip,nskips; + int dwords,rc,line,maxy,start,end,skip,nskips; struct btcx_skiplist *skips; u32 *rp,ri,ra; u32 addr; @@ -242,12 +242,12 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL))) return -ENOMEM; - /* estimate risc mem: worst case is (clip+1) * lines instructions + /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions + sync + jump (all 2 dwords) */ - instructions = (ov->nclips + 1) * - ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height); - instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) { + dwords = (3 * ov->nclips + 2) * + ((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height); + dwords += 4; + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) { kfree(skips); return rc; } @@ -276,8 +276,6 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, if (line > maxy) btcx_calc_skips(line, ov->w.width, &maxy, skips, &nskips, ov->clips, ov->nclips); - else - nskips = 0; /* write out risc code */ for (start = 0, skip = 0; start < ov->w.width; start = end) { diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index f59ced181c55..1958d4016ea1 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -39,29 +39,12 @@ #define FWDEV(x) &((x)->adapter->dev) -static int fastfw = 1; static char *firmware = FWFILE; -module_param(fastfw, bool, 0444); module_param(firmware, charp, 0444); -MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]"); MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); -static void set_i2c_delay(struct i2c_client *client, int delay) -{ - struct i2c_algo_bit_data *algod = client->adapter->algo_data; - - /* We aren't guaranteed to be using algo_bit, - * so avoid the null pointer dereference - * and disable the 'fast firmware load' */ - if (algod) { - algod->udelay = delay; - } else { - fastfw = 0; - } -} - static void start_fw_load(struct i2c_client *client) { /* DL_ADDR_LB=0 DL_ADDR_HB=0 */ @@ -71,16 +54,10 @@ static void start_fw_load(struct i2c_client *client) cx25840_write(client, 0x803, 0x0b); /* AUTO_INC_DIS=1 */ cx25840_write(client, 0x000, 0x20); - - if (fastfw) - set_i2c_delay(client, 3); } static void end_fw_load(struct i2c_client *client) { - if (fastfw) - set_i2c_delay(client, 10); - /* AUTO_INC_DIS=0 */ cx25840_write(client, 0x000, 0x00); /* DL_ENABLE=0 */ @@ -107,30 +84,8 @@ static int fw_write(struct i2c_client *client, u8 * data, int size) int sent; if ((sent = i2c_master_send(client, data, size)) < size) { - - if (fastfw) { - v4l_err(client, "333MHz i2c firmware load failed\n"); - fastfw = 0; - set_i2c_delay(client, 10); - - if (sent > 2) { - u16 dl_addr = cx25840_read(client, 0x801) << 8; - dl_addr |= cx25840_read(client, 0x800); - dl_addr -= sent - 2; - cx25840_write(client, 0x801, dl_addr >> 8); - cx25840_write(client, 0x800, dl_addr & 0xff); - } - - if (i2c_master_send(client, data, size) < size) { - v4l_err(client, "100MHz i2c firmware load failed\n"); - return -ENOSYS; - } - - } else { - v4l_err(client, "firmware load i2c failure\n"); - return -ENOSYS; - } - + v4l_err(client, "firmware load i2c failure\n"); + return -ENOSYS; } return 0; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index c7042cf41231..f80154b87d22 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -564,7 +564,7 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_PCHDTV_HD3000] = { .name = "pcHDTV HD3000 HDTV", - .tuner_type = TUNER_THOMSON_DTT7610, + .tuner_type = TUNER_THOMSON_DTT761X, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 2c3d9f1999be..e1092d5d4628 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -146,9 +146,11 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, fields++; /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords) */ - instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields; - instructions += 3 + 4; + one write per scan line + syncs + jump (all 2 dwords). Padding + can cause next bpl to start close to a page border. First DMA + region may be smaller than PAGE_SIZE */ + instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); + instructions += 2; if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) return rc; @@ -176,9 +178,11 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, int rc; /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords) */ - instructions = (bpl * lines) / PAGE_SIZE + lines; - instructions += 3 + 4; + one write per scan line + syncs + jump (all 2 dwords). Here + there is no padding and no sync. First DMA region may be smaller + than PAGE_SIZE */ + instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; + instructions += 1; if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) return rc; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index f0ea9b5cdbc2..3619a449aefd 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -372,7 +372,7 @@ static int or51132_set_ts_param(struct dvb_frontend* fe, static struct or51132_config pchdtv_hd3000 = { .demod_address = 0x15, .pll_address = 0x61, - .pll_desc = &dvb_pll_thomson_dtt7610, + .pll_desc = &dvb_pll_thomson_dtt761x, .set_ts_params = or51132_set_ts_param, }; #endif diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 72a417b31745..694d1d80ff3f 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -35,8 +35,10 @@ #include "cx88.h" #include <media/v4l2-common.h> +#ifdef CONFIG_VIDEO_V4L1_COMPAT /* Include V4L1 specific functions. Should be removed soon */ #include <linux/videodev.h> +#endif MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 5a793ae7cc23..dfb15bfb83dc 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_EM28XX tristate "Empia EM2800/2820/2840 USB video capture support" - depends on VIDEO_DEV && USB && I2C + depends on VIDEO_V4L1 && USB && I2C select VIDEO_BUF select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index ddc92cbb5276..cf7cdf9ef617 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1576,8 +1576,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, errCode = em28xx_config(dev); if (errCode) { em28xx_errdev("error configuring device\n"); - kfree(dev); em28xx_devused&=~(1<<dev->devno); + kfree(dev); return -ENOMEM; } @@ -1603,8 +1603,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->vdev = video_device_alloc(); if (NULL == dev->vdev) { em28xx_errdev("cannot allocate video_device.\n"); - kfree(dev); em28xx_devused&=~(1<<dev->devno); + kfree(dev); return -ENOMEM; } @@ -1612,8 +1612,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (NULL == dev->vbi_dev) { em28xx_errdev("cannot allocate video_device.\n"); kfree(dev->vdev); - kfree(dev); em28xx_devused&=~(1<<dev->devno); + kfree(dev); return -ENOMEM; } @@ -1650,8 +1650,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vdev); - kfree(dev); em28xx_devused&=~(1<<dev->devno); + kfree(dev); return -ENODEV; } @@ -1662,8 +1662,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, list_del(&dev->devlist); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); - kfree(dev); em28xx_devused&=~(1<<dev->devno); + kfree(dev); return -ENODEV; } else { printk("registered VBI\n"); diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index 6c43a90c6569..c6bff705688d 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig @@ -1,6 +1,6 @@ config USB_ET61X251 tristate "USB ET61X[12]51 PC Camera Controller support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on Etoms ET61X151 or ET61X251 PC Camera Controllers. diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 86376556f108..53cbc950f95c 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig @@ -1,6 +1,6 @@ config USB_PWC tristate "USB Philips Cameras" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y or M here if you want to use one of these Philips & OEM webcams: diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile index 8326684f49f3..33d60126c024 100644 --- a/drivers/media/video/pwc/Makefile +++ b/drivers/media/video/pwc/Makefile @@ -1,20 +1,3 @@ -ifneq ($(KERNELRELEASE),) - pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o obj-$(CONFIG_USB_PWC) += pwc.o - -else - -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) - -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - -endif - -clean: - rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c - rm -rf .tmp_versions - diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 133f9e5252fe..c271e2e14105 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -142,6 +142,7 @@ struct i2c_reg_value { static const struct i2c_reg_value saa7129_init_config_extra[] = { { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 }, { SAA7127_REG_VTRIG, 0xfa }, + { 0, 0 } }; static const struct i2c_reg_value saa7127_init_config_common[] = { diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e666a4465ca4..86eae3528330 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3504,6 +3504,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000); + break; case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: /* this turns the remote control chip off to work around a bug in it */ saa_writeb(SAA7134_GPIO_GPMODE1, 0x80); diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 13de05532e0a..f0c2111f14ad 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -548,6 +548,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) if (report & SAA7134_IRQ_REPORT_GPIO16) { switch (dev->has_remote) { case SAA7134_REMOTE_GPIO: + if (!dev->remote) + break; if (dev->remote->mask_keydown & 0x10000) { saa7134_input_irq(dev); } @@ -564,6 +566,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) if (report & SAA7134_IRQ_REPORT_GPIO18) { switch (dev->has_remote) { case SAA7134_REMOTE_GPIO: + if (!dev->remote) + break; if ((dev->remote->mask_keydown & 0x40000) || (dev->remote->mask_keyup & 0x40000)) { saa7134_input_irq(dev); @@ -676,7 +680,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) SAA7134_IRQ2_INTE_PE | SAA7134_IRQ2_INTE_AR; - if (dev->has_remote == SAA7134_REMOTE_GPIO) { + if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) { if (dev->remote->mask_keydown & 0x10000) irq2_mask |= SAA7134_IRQ2_INTE_GPIO16; else if (dev->remote->mask_keydown & 0x40000) diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index aeef80f88a6b..e4156ec9c6d7 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -31,8 +31,10 @@ #include "saa7134.h" #include <media/v4l2-common.h> +#ifdef CONFIG_VIDEO_V4L1_COMPAT /* Include V4L1 specific functions. Should be removed soon */ #include <linux/videodev.h> +#endif /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig index 55f2bc11964b..cf552e6b8ecf 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/video/sn9c102/Kconfig @@ -1,6 +1,6 @@ config USB_SN9C102 tristate "USB SN9C10x PC Camera Controller support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on SONiX SN9C101, SN9C102 or SN9C103 PC Camera Controllers. diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 72e0f01db563..a1ae036b44ec 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -877,8 +877,8 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { /* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ static struct tuner_range tuner_tua6034_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01 }, - { 16 * 455.00 /*MHz*/, 0x8e, 0x02 }, + { 16 * 165.00 /*MHz*/, 0x8e, 0x01 }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x02 }, { 16 * 999.99 , 0x8e, 0x04 }, }; diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 431c3e2f6c42..b463e996961a 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -218,7 +218,7 @@ hauppauge_tuner[] = /* 110-119 */ { TUNER_ABSENT, "Thompson DTT75105"}, { TUNER_ABSENT, "Conexant_CX24109"}, - { TUNER_ABSENT, "TCL M2523_5N_E"}, + { TUNER_TCL_2002N, "TCL M2523_5N_E"}, { TUNER_ABSENT, "TCL M2523_3DB_E"}, { TUNER_ABSENT, "Philips 8275A"}, { TUNER_ABSENT, "Microtune MT2060"}, diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index 08a5d20bb2c0..39269a2c5635 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL + depends on USB && VIDEO_V4L1 && EXPERIMENTAL select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). @@ -13,7 +13,7 @@ config USB_VICAM config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -28,7 +28,7 @@ config USB_IBMCAM config USB_KONICAWC tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want support for webcams based on a Konica diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 5e813404d068..779db26771c0 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -26,6 +26,11 @@ #include <linux/random.h> #include <linux/version.h> #include <linux/videodev2.h> +#include <linux/dma-mapping.h> +#ifdef CONFIG_VIDEO_V4L1_COMPAT +/* Include V4L1 specific functions. Should be removed soon */ +#include <linux/videodev.h> +#endif #include <linux/interrupt.h> #include <media/video-buf.h> #include <media/v4l2-common.h> diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index c3bf886b80cd..115833e4f4dd 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig @@ -1,6 +1,6 @@ config USB_ZC0301 tristate "USB ZC0301 Image Processor and Control Chip support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on the ZC0301 Image Processor and Control Chip. diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 914d62b24064..5dc4bee7abeb 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -310,7 +310,7 @@ static void au1xmmc_data_complete(struct au1xmmc_host *host, u32 status) } else data->bytes_xfered = - (data->blocks * (1 << data->blksz_bits)) - + (data->blocks * data->blksz) - host->pio.len; } @@ -575,7 +575,7 @@ static int au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data) { - int datalen = data->blocks * (1 << data->blksz_bits); + int datalen = data->blocks * data->blksz; if (dma != 0) host->flags |= HOST_F_DMA; @@ -596,7 +596,7 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data) if (host->dma.len == 0) return MMC_ERR_TIMEOUT; - au_writel((1 << data->blksz_bits) - 1, HOST_BLKSIZE(host)); + au_writel(data->blksz - 1, HOST_BLKSIZE(host)); if (host->flags & HOST_F_DMA) { int i; diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index 79358e223f57..a4eb1d0e7a71 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c @@ -218,8 +218,10 @@ static int imxmci_busy_wait_for_status(struct imxmci_host *host, if(!loops) return 0; - dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n", - loops, where, *pstat, stat_mask); + /* The busy-wait is expected there for clock <8MHz due to SDHC hardware flaws */ + if(!(stat_mask & STATUS_END_CMD_RESP) || (host->mmc->ios.clock>=8000000)) + dev_info(mmc_dev(host->mmc), "busy wait for %d usec in %s, STATUS = 0x%x (0x%x)\n", + loops, where, *pstat, stat_mask); return loops; } @@ -333,6 +335,9 @@ static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, WARN_ON(host->cmd != NULL); host->cmd = cmd; + /* Ensure, that clock are stopped else command programming and start fails */ + imxmci_stop_clock(host); + if (cmd->flags & MMC_RSP_BUSY) cmdat |= CMD_DAT_CONT_BUSY; @@ -553,7 +558,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) int trans_done = 0; unsigned int stat = *pstat; - if(host->actual_bus_width == MMC_BUS_WIDTH_4) + if(host->actual_bus_width != MMC_BUS_WIDTH_4) burst_len = 16; else burst_len = 64; @@ -591,8 +596,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) stat = MMC_STATUS; /* Flush extra bytes from FIFO */ - while(flush_len >= 2){ - flush_len -= 2; + while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){ i = MMC_BUFFER_ACCESS; stat = MMC_STATUS; stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */ @@ -746,10 +750,6 @@ static void imxmci_tasklet_fnc(unsigned long data) data_dir_mask = STATUS_DATA_TRANS_DONE; } - imxmci_busy_wait_for_status(host, &stat, - data_dir_mask, - 50, "imxmci_tasklet_fnc data"); - if(stat & data_dir_mask) { clear_bit(IMXMCI_PEND_DMA_END_b, &host->pending_events); imxmci_data_done(host, stat); @@ -865,7 +865,11 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) imxmci_stop_clock(host); MMC_CLK_RATE = (prescaler<<3) | clk; - imxmci_start_clock(host); + /* + * Under my understanding, clock should not be started there, because it would + * initiate SDHC sequencer and send last or random command into card + */ + /*imxmci_start_clock(host);*/ dev_dbg(mmc_dev(host->mmc), "MMC_CLK_RATE: 0x%08x\n", MMC_CLK_RATE); } else { diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 1ca2c8b9c9b5..6201f3086a02 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -951,6 +951,7 @@ static void mmc_read_scrs(struct mmc_host *host) data.timeout_ns = card->csd.tacc_ns * 10; data.timeout_clks = card->csd.tacc_clks * 10; data.blksz_bits = 3; + data.blksz = 1 << 3; data.blocks = 1; data.flags = MMC_DATA_READ; data.sg = &sg; diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 06bd1f4cb9b1..e39cc05c64c2 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -175,6 +175,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.data.timeout_ns = card->csd.tacc_ns * 10; brq.data.timeout_clks = card->csd.tacc_clks * 10; brq.data.blksz_bits = md->block_bits; + brq.data.blksz = 1 << md->block_bits; brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); brq.stop.opcode = MMC_STOP_TRANSMISSION; brq.stop.arg = 0; diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index f97b472085cb..b49368fd96b8 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -119,7 +119,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) nob = 0xffff; writel(nob, host->base + MMC_NOB); - writel(1 << data->blksz_bits, host->base + MMC_BLKLEN); + writel(data->blksz, host->base + MMC_BLKLEN); clks = (unsigned long long)data->timeout_ns * CLOCKRATE; do_div(clks, 1000000000UL); @@ -283,7 +283,7 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) * data blocks as being in error. */ if (data->error == MMC_ERR_NONE) - data->bytes_xfered = data->blocks << data->blksz_bits; + data->bytes_xfered = data->blocks * data->blksz; else data->bytes_xfered = 0; diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 39b3d97f891e..8167332d4013 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -662,14 +662,14 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data) unsigned long dmaflags; DBGF("blksz %04x blks %04x flags %08x\n", - 1 << data->blksz_bits, data->blocks, data->flags); + data->blksz, data->blocks, data->flags); DBGF("tsac %d ms nsac %d clk\n", data->timeout_ns / 1000000, data->timeout_clks); /* * Calculate size. */ - host->size = data->blocks << data->blksz_bits; + host->size = data->blocks * data->blksz; /* * Check timeout values for overflow. @@ -696,12 +696,12 @@ static void wbsd_prepare_data(struct wbsd_host *host, struct mmc_data *data) * Two bytes are needed for each data line. */ if (host->bus_width == MMC_BUS_WIDTH_1) { - blksize = (1 << data->blksz_bits) + 2; + blksize = data->blksz + 2; wbsd_write_index(host, WBSD_IDX_PBSMSB, (blksize >> 4) & 0xF0); wbsd_write_index(host, WBSD_IDX_PBSLSB, blksize & 0xFF); } else if (host->bus_width == MMC_BUS_WIDTH_4) { - blksize = (1 << data->blksz_bits) + 2 * 4; + blksize = data->blksz + 2 * 4; wbsd_write_index(host, WBSD_IDX_PBSMSB, ((blksize >> 4) & 0xF0) | WBSD_DATA_WIDTH); diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index f7235c9bc421..705e1229d89d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2891,78 +2891,6 @@ static int nv_open(struct net_device *dev) goto out_drain; } - if (np->msi_flags & NV_MSI_X_CAPABLE) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { - np->msi_x_entry[i].entry = i; - } - if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { - np->msi_flags |= NV_MSI_X_ENABLED; - if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { - /* Request irq for rx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - /* Request irq for tx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - /* Request irq for link and timer handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - - /* map interrupts to their respective vector */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); - } else { - /* Request irq for all interrupts */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); - } - } - } - if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { - if ((ret = pci_enable_msi(np->pci_dev)) == 0) { - np->msi_flags |= NV_MSI_ENABLED; - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msi(np->pci_dev); - np->msi_flags &= ~NV_MSI_ENABLED; - goto out_drain; - } - - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIMap0); - writel(0, base + NvRegMSIMap1); - /* enable msi vector 0 */ - writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); - } - } - if (ret != 0) { - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) - goto out_drain; - } - /* ask for interrupts */ nv_enable_hw_interrupts(dev, np->irqmask); diff --git a/drivers/net/ixp2000/enp2611.c b/drivers/net/ixp2000/enp2611.c index 6f7dce8eba51..b67f586d7392 100644 --- a/drivers/net/ixp2000/enp2611.c +++ b/drivers/net/ixp2000/enp2611.c @@ -149,6 +149,8 @@ static void enp2611_check_link_status(unsigned long __dummy) int status; dev = nds[i]; + if (dev == NULL) + continue; status = pm3386_is_link_up(i); if (status && !netif_carrier_ok(dev)) { @@ -191,6 +193,7 @@ static void enp2611_set_port_admin_status(int port, int up) static int __init enp2611_init_module(void) { + int ports; int i; if (!machine_is_enp2611()) @@ -199,7 +202,8 @@ static int __init enp2611_init_module(void) caleb_reset(); pm3386_reset(); - for (i = 0; i < 3; i++) { + ports = pm3386_port_count(); + for (i = 0; i < ports; i++) { nds[i] = ixpdev_alloc(i, sizeof(struct enp2611_ixpdev_priv)); if (nds[i] == NULL) { while (--i >= 0) @@ -215,9 +219,10 @@ static int __init enp2611_init_module(void) ixp2400_msf_init(&enp2611_msf_parameters); - if (ixpdev_init(3, nds, enp2611_set_port_admin_status)) { - for (i = 0; i < 3; i++) - free_netdev(nds[i]); + if (ixpdev_init(ports, nds, enp2611_set_port_admin_status)) { + for (i = 0; i < ports; i++) + if (nds[i]) + free_netdev(nds[i]); return -EINVAL; } diff --git a/drivers/net/ixp2000/pm3386.c b/drivers/net/ixp2000/pm3386.c index 5c7ab7564053..5224651c9aac 100644 --- a/drivers/net/ixp2000/pm3386.c +++ b/drivers/net/ixp2000/pm3386.c @@ -86,40 +86,53 @@ static void pm3386_port_reg_write(int port, int _reg, int spacing, u16 value) pm3386_reg_write(port >> 1, reg, value); } +int pm3386_secondary_present(void) +{ + return pm3386_reg_read(1, 0) == 0x3386; +} void pm3386_reset(void) { u8 mac[3][6]; + int secondary; + + secondary = pm3386_secondary_present(); /* Save programmed MAC addresses. */ pm3386_get_mac(0, mac[0]); pm3386_get_mac(1, mac[1]); - pm3386_get_mac(2, mac[2]); + if (secondary) + pm3386_get_mac(2, mac[2]); /* Assert analog and digital reset. */ pm3386_reg_write(0, 0x002, 0x0060); - pm3386_reg_write(1, 0x002, 0x0060); + if (secondary) + pm3386_reg_write(1, 0x002, 0x0060); mdelay(1); /* Deassert analog reset. */ pm3386_reg_write(0, 0x002, 0x0062); - pm3386_reg_write(1, 0x002, 0x0062); + if (secondary) + pm3386_reg_write(1, 0x002, 0x0062); mdelay(10); /* Deassert digital reset. */ pm3386_reg_write(0, 0x002, 0x0063); - pm3386_reg_write(1, 0x002, 0x0063); + if (secondary) + pm3386_reg_write(1, 0x002, 0x0063); mdelay(10); /* Restore programmed MAC addresses. */ pm3386_set_mac(0, mac[0]); pm3386_set_mac(1, mac[1]); - pm3386_set_mac(2, mac[2]); + if (secondary) + pm3386_set_mac(2, mac[2]); /* Disable carrier on all ports. */ pm3386_set_carrier(0, 0); pm3386_set_carrier(1, 0); - pm3386_set_carrier(2, 0); + if (secondary) + pm3386_set_carrier(2, 0); } static u16 swaph(u16 x) @@ -127,6 +140,11 @@ static u16 swaph(u16 x) return ((x << 8) | (x >> 8)) & 0xffff; } +int pm3386_port_count(void) +{ + return 2 + pm3386_secondary_present(); +} + void pm3386_init_port(int port) { int pm = port >> 1; diff --git a/drivers/net/ixp2000/pm3386.h b/drivers/net/ixp2000/pm3386.h index fe92bb056ac4..cc4183dca911 100644 --- a/drivers/net/ixp2000/pm3386.h +++ b/drivers/net/ixp2000/pm3386.h @@ -13,6 +13,7 @@ #define __PM3386_H void pm3386_reset(void); +int pm3386_port_count(void); void pm3386_init_port(int port); void pm3386_get_mac(int port, u8 *mac); void pm3386_set_mac(int port, u8 *mac); diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 448a09488529..2ea66aca648b 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1691,17 +1691,6 @@ static void do_set_multicast_list(struct net_device *dev) memset(ei_local->mcfilter, 0xFF, 8); } - /* - * DP8390 manuals don't specify any magic sequence for altering - * the multicast regs on an already running card. To be safe, we - * ensure multicast mode is off prior to loading up the new hash - * table. If this proves to be not enough, we can always resort - * to stopping the NIC, loading the table and then restarting. - */ - - if (netif_running(dev)) - outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); - outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); for(i = 0; i < 8; i++) { @@ -1715,6 +1704,8 @@ static void do_set_multicast_list(struct net_device *dev) outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR); else outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); + + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); } /* diff --git a/drivers/net/skge.c b/drivers/net/skge.c index a70c2b0cc104..5ca5a1b546a1 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -78,8 +78,7 @@ static const struct pci_device_id skge_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* DGE-530T */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) }, @@ -402,7 +401,7 @@ static int skge_set_ring_param(struct net_device *dev, int err; if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || - p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE) + p->tx_pending < MAX_SKB_FRAGS+1 || p->tx_pending > MAX_TX_RING_SIZE) return -EINVAL; skge->rx_ring.count = p->rx_pending; @@ -2717,8 +2716,7 @@ static int skge_poll(struct net_device *dev, int *budget) if (control & BMU_OWN) break; - skb = skge_rx_get(skge, e, control, rd->status, - le16_to_cpu(rd->csum2)); + skb = skge_rx_get(skge, e, control, rd->status, rd->csum2); if (likely(skb)) { dev->last_rx = jiffies; netif_receive_skb(skb); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index ffd267fab21d..60779ebf2ff6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -51,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.3" +#define DRV_VERSION "1.4" #define PFX DRV_NAME " " /* @@ -105,6 +105,7 @@ MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms) static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, @@ -235,6 +236,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) } if (hw->chip_id == CHIP_ID_YUKON_EC_U) { + sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); sky2_pci_write32(hw, PCI_DEV_REG3, 0); reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); reg1 &= P_ASPM_CONTROL_MSK; @@ -306,7 +308,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) u16 ctrl, ct1000, adv, pg, ledctrl, ledover; if (sky2->autoneg == AUTONEG_ENABLE && - (hw->chip_id != CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { + !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | @@ -1020,7 +1022,25 @@ static int sky2_up(struct net_device *dev) struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; u32 ramsize, rxspace, imask; - int err = -ENOMEM; + int cap, err = -ENOMEM; + struct net_device *otherdev = hw->dev[sky2->port^1]; + + /* + * On dual port PCI-X card, there is an problem where status + * can be received out of order due to split transactions + */ + if (otherdev && netif_running(otherdev) && + (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { + struct sky2_port *osky2 = netdev_priv(otherdev); + u16 cmd; + + cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); + cmd &= ~PCI_X_CMD_MAX_SPLIT; + sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); + + sky2->rx_csum = 0; + osky2->rx_csum = 0; + } if (netif_msg_ifup(sky2)) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); @@ -1899,6 +1919,12 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } } +/* Is status ring empty or is there more to do? */ +static inline int sky2_more_work(const struct sky2_hw *hw) +{ + return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); +} + /* Process status response ring */ static int sky2_status_intr(struct sky2_hw *hw, int to_do) { @@ -2171,19 +2197,19 @@ static int sky2_poll(struct net_device *dev0, int *budget) if (status & Y2_IS_CHK_TXA2) sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); - if (status & Y2_IS_STAT_BMU) - sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); - work_done = sky2_status_intr(hw, work_limit); *budget -= work_done; dev0->quota -= work_done; - if (work_done >= work_limit) + if (status & Y2_IS_STAT_BMU) + sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + + if (sky2_more_work(hw)) return 1; netif_rx_complete(dev0); - status = sky2_read32(hw, B0_Y2_SP_LISR); + sky2_read32(hw, B0_Y2_SP_LISR); return 0; } @@ -3067,12 +3093,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->duplex = -1; sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); - - /* Receive checksum disabled for Yukon XL - * because of observed problems with incorrect - * values when multiple packets are received in one interrupt - */ - sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); + sky2->rx_csum = 1; spin_lock_init(&sky2->phy_lock); sky2->tx_pending = TX_DEF_PENDING; diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 8012994c9b93..8a0bc5525f0a 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -214,6 +214,8 @@ enum csr_regs { enum { Y2_VMAIN_AVAIL = 1<<17,/* VMAIN available (YUKON-2 only) */ Y2_VAUX_AVAIL = 1<<16,/* VAUX available (YUKON-2 only) */ + Y2_HW_WOL_ON = 1<<15,/* HW WOL On (Yukon-EC Ultra A1 only) */ + Y2_HW_WOL_OFF = 1<<14,/* HW WOL On (Yukon-EC Ultra A1 only) */ Y2_ASF_ENABLE = 1<<13,/* ASF Unit Enable (YUKON-2 only) */ Y2_ASF_DISABLE = 1<<12,/* ASF Unit Disable (YUKON-2 only) */ Y2_CLK_RUN_ENA = 1<<11,/* CLK_RUN Enable (YUKON-2 only) */ diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index ba05dedf29d3..136a70c4d5e4 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -850,7 +850,7 @@ static void init_rxtx_rings(struct net_device *dev) break; skb->dev = dev; /* Mark as being used by this device. */ np->rx_addr[i] = pci_map_single(np->pci_dev,skb->data, - skb->len,PCI_DMA_FROMDEVICE); + np->rx_buf_sz,PCI_DMA_FROMDEVICE); np->rx_ring[i].buffer1 = np->rx_addr[i]; np->rx_ring[i].status = DescOwn; @@ -1316,7 +1316,7 @@ static int netdev_rx(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ np->rx_addr[entry] = pci_map_single(np->pci_dev, skb->data, - skb->len, PCI_DMA_FROMDEVICE); + np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->rx_ring[entry].buffer1 = np->rx_addr[entry]; } wmb(); diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index a6dc53b4250d..fdc21037f6dc 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -491,8 +491,6 @@ struct rhine_private { u8 tx_thresh, rx_thresh; struct mii_if_info mii_if; - struct work_struct tx_timeout_task; - struct work_struct check_media_task; void __iomem *base; }; @@ -500,8 +498,6 @@ static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int rhine_open(struct net_device *dev); static void rhine_tx_timeout(struct net_device *dev); -static void rhine_tx_timeout_task(struct net_device *dev); -static void rhine_check_media_task(struct net_device *dev); static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static void rhine_tx(struct net_device *dev); @@ -856,12 +852,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, if (rp->quirks & rqRhineI) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; - INIT_WORK(&rp->tx_timeout_task, - (void (*)(void *))rhine_tx_timeout_task, dev); - - INIT_WORK(&rp->check_media_task, - (void (*)(void *))rhine_check_media_task, dev); - /* dev->name not defined before register_netdev()! */ rc = register_netdev(dev); if (rc) @@ -1108,11 +1098,6 @@ static void rhine_set_carrier(struct mii_if_info *mii) netif_carrier_ok(mii->dev)); } -static void rhine_check_media_task(struct net_device *dev) -{ - rhine_check_media(dev, 0); -} - static void init_registers(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); @@ -1166,8 +1151,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks) if (quirks & rqRhineI) { iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR - /* Do not call from ISR! */ - msleep(1); + /* Can be called from ISR. Evil. */ + mdelay(1); /* 0x80 must be set immediately before turning it off */ iowrite8(0x80, ioaddr + MIICmd); @@ -1257,16 +1242,6 @@ static int rhine_open(struct net_device *dev) static void rhine_tx_timeout(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); - - /* - * Move bulk of work outside of interrupt context - */ - schedule_work(&rp->tx_timeout_task); -} - -static void rhine_tx_timeout_task(struct net_device *dev) -{ - struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status " @@ -1677,7 +1652,7 @@ static void rhine_error(struct net_device *dev, int intr_status) spin_lock(&rp->lock); if (intr_status & IntrLinkChange) - schedule_work(&rp->check_media_task); + rhine_check_media(dev, 0); if (intr_status & IntrStatsMax) { rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); @@ -1927,9 +1902,6 @@ static int rhine_close(struct net_device *dev) spin_unlock_irq(&rp->lock); free_irq(rp->pdev->irq, dev); - - flush_scheduled_work(); - free_rbufs(dev); free_tbufs(dev); free_ring(dev); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 6917c6cb0912..c2ecae5ff0c1 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -33,13 +33,10 @@ acpi_query_osc ( acpi_status status; struct acpi_object_list input; union acpi_object in_params[4]; - struct acpi_buffer output; - union acpi_object out_obj; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *out_obj; u32 osc_dw0; - /* Setting up output buffer */ - output.length = sizeof(out_obj) + 3*sizeof(u32); - output.pointer = &out_obj; /* Setting up input parameters */ input.count = 4; @@ -61,12 +58,15 @@ acpi_query_osc ( "Evaluate _OSC Set fails. Status = 0x%04x\n", status); return status; } - if (out_obj.type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + + if (out_obj->type != ACPI_TYPE_BUFFER) { printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); - return AE_TYPE; + status = AE_TYPE; + goto query_osc_out; } - osc_dw0 = *((u32 *) out_obj.buffer.pointer); + osc_dw0 = *((u32 *) out_obj->buffer.pointer); if (osc_dw0) { if (osc_dw0 & OSC_REQUEST_ERROR) printk(KERN_DEBUG "_OSC request fails\n"); @@ -76,15 +76,21 @@ acpi_query_osc ( printk(KERN_DEBUG "_OSC invalid revision\n"); if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { /* Update Global Control Set */ - global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); - return AE_OK; + global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); + status = AE_OK; + goto query_osc_out; } - return AE_ERROR; + status = AE_ERROR; + goto query_osc_out; } /* Update Global Control Set */ - global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); - return AE_OK; + global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); + status = AE_OK; + +query_osc_out: + kfree(output.pointer); + return status; } @@ -96,14 +102,10 @@ acpi_run_osc ( acpi_status status; struct acpi_object_list input; union acpi_object in_params[4]; - struct acpi_buffer output; - union acpi_object out_obj; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *out_obj; u32 osc_dw0; - /* Setting up output buffer */ - output.length = sizeof(out_obj) + 3*sizeof(u32); - output.pointer = &out_obj; - /* Setting up input parameters */ input.count = 4; input.pointer = in_params; @@ -124,12 +126,14 @@ acpi_run_osc ( "Evaluate _OSC Set fails. Status = 0x%04x\n", status); return status; } - if (out_obj.type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); - return AE_TYPE; + status = AE_TYPE; + goto run_osc_out; } - osc_dw0 = *((u32 *) out_obj.buffer.pointer); + osc_dw0 = *((u32 *) out_obj->buffer.pointer); if (osc_dw0) { if (osc_dw0 & OSC_REQUEST_ERROR) printk(KERN_DEBUG "_OSC request fails\n"); @@ -139,11 +143,17 @@ acpi_run_osc ( printk(KERN_DEBUG "_OSC invalid revision\n"); if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { printk(KERN_DEBUG "_OSC FW not grant req. control\n"); - return AE_SUPPORT; + status = AE_SUPPORT; + goto run_osc_out; } - return AE_ERROR; + status = AE_ERROR; + goto run_osc_out; } - return AE_OK; + status = AE_OK; + +run_osc_out: + kfree(output.pointer); + return status; } /** diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 16d1ea7b0a18..247ab837f841 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -589,7 +589,7 @@ static int pd6729_check_irq(int irq, int flags) return 0; } -static u_int __init pd6729_isa_scan(void) +static u_int __devinit pd6729_isa_scan(void) { u_int mask0, mask = 0; int i; diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 6c9ad92747fd..2011567005f9 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -141,13 +141,13 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, /* try the driver's ioctl interface */ if (ops->ioctl) { err = ops->ioctl(class_dev->dev, cmd, arg); - if (err != -EINVAL) + if (err != -ENOIOCTLCMD) return err; } /* if the driver does not provide the ioctl interface * or if that particular ioctl was not implemented - * (-EINVAL), we will try to emulate here. + * (-ENOIOCTLCMD), we will try to emulate here. */ switch (cmd) { @@ -233,7 +233,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, break; default: - err = -EINVAL; + err = -ENOTTY; break; } diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 2bc8aad47219..a997529f8926 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -247,7 +247,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, rtc_freq = arg; return 0; } - return -EINVAL; + return -ENOIOCTLCMD; } static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index e1f7e8e86daf..e1fa5fe7901f 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -71,7 +71,7 @@ static int test_rtc_ioctl(struct device *dev, unsigned int cmd, return 0; default: - return -EINVAL; + return -ENOIOCTLCMD; } } diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 4d49fd501198..277596c302e3 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -270,7 +270,7 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long epoch = arg; break; default: - return -EINVAL; + return -ENOIOCTLCMD; } return 0; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index bd147207f25d..823dfa78c0ba 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -864,6 +864,9 @@ static unsigned int ata_id_xfermask(const u16 *id) /** * ata_port_queue_task - Queue port_task * @ap: The ata_port to queue port_task for + * @fn: workqueue function to be scheduled + * @data: data value to pass to workqueue function + * @delay: delay time for workqueue function * * Schedule @fn(@data) for execution after @delay jiffies using * port_task. There is one port_task per port and it's the @@ -2739,6 +2742,8 @@ static unsigned int ata_dev_set_xfermode(struct ata_port *ap, * ata_dev_init_params - Issue INIT DEV PARAMS command * @ap: Port associated with device @dev * @dev: Device to which command will be sent + * @heads: Number of heads (taskfile parameter) + * @sectors: Number of sectors (taskfile parameter) * * LOCKING: * Kernel thread context (may sleep) @@ -4302,6 +4307,7 @@ int ata_device_resume(struct ata_port *ap, struct ata_device *dev) * ata_device_suspend - prepare a device for suspend * @ap: port the device is connected to * @dev: the device to suspend + * @state: target power management state * * Flush the cache on the drive, if appropriate, then issue a * standbynow command. diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index d5fdcb9a8842..9b8bca1ac1f0 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -37,7 +37,7 @@ #include <asm/io.h> #define DRV_NAME "sata_mv" -#define DRV_VERSION "0.6" +#define DRV_VERSION "0.7" enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ @@ -50,6 +50,12 @@ enum { MV_PCI_REG_BASE = 0, MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ + MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08), + MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88), + MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c), + MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc), + MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0), + MV_SATAHC0_REG_BASE = 0x20000, MV_FLASH_CTL = 0x1046c, MV_GPIO_PORT_CTL = 0x104f0, @@ -302,9 +308,6 @@ struct mv_port_priv { dma_addr_t crpb_dma; struct mv_sg *sg_tbl; dma_addr_t sg_tbl_dma; - - unsigned req_producer; /* cp of req_in_ptr */ - unsigned rsp_consumer; /* cp of rsp_out_ptr */ u32 pp_flags; }; @@ -937,8 +940,6 @@ static int mv_port_start(struct ata_port *ap) writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); - pp->req_producer = pp->rsp_consumer = 0; - /* Don't turn on EDMA here...do it before DMA commands only. Else * we'll be unable to send non-data, PIO, etc due to restricted access * to shadow regs. @@ -1022,16 +1023,16 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) } } -static inline unsigned mv_inc_q_index(unsigned *index) +static inline unsigned mv_inc_q_index(unsigned index) { - *index = (*index + 1) & MV_MAX_Q_DEPTH_MASK; - return *index; + return (index + 1) & MV_MAX_Q_DEPTH_MASK; } static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last) { - *cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | + u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS | (last ? CRQB_CMD_LAST : 0); + *cmdw = cpu_to_le16(tmp); } /** @@ -1053,15 +1054,11 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) u16 *cw; struct ata_taskfile *tf; u16 flags = 0; + unsigned in_index; if (ATA_PROT_DMA != qc->tf.protocol) return; - /* the req producer index should be the same as we remember it */ - WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> - EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != - pp->req_producer); - /* Fill in command request block */ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) @@ -1069,13 +1066,17 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); flags |= qc->tag << CRQB_TAG_SHIFT; - pp->crqb[pp->req_producer].sg_addr = + /* get current queue index from hardware */ + in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS) + >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; + + pp->crqb[in_index].sg_addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); - pp->crqb[pp->req_producer].sg_addr_hi = + pp->crqb[in_index].sg_addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); - pp->crqb[pp->req_producer].ctrl_flags = cpu_to_le16(flags); + pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags); - cw = &pp->crqb[pp->req_producer].ata_cmd[0]; + cw = &pp->crqb[in_index].ata_cmd[0]; tf = &qc->tf; /* Sadly, the CRQB cannot accomodate all registers--there are @@ -1144,16 +1145,12 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) struct mv_port_priv *pp = ap->private_data; struct mv_crqb_iie *crqb; struct ata_taskfile *tf; + unsigned in_index; u32 flags = 0; if (ATA_PROT_DMA != qc->tf.protocol) return; - /* the req producer index should be the same as we remember it */ - WARN_ON(((readl(mv_ap_base(qc->ap) + EDMA_REQ_Q_IN_PTR_OFS) >> - EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != - pp->req_producer); - /* Fill in Gen IIE command request block */ if (!(qc->tf.flags & ATA_TFLAG_WRITE)) @@ -1162,7 +1159,11 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) WARN_ON(MV_MAX_Q_DEPTH <= qc->tag); flags |= qc->tag << CRQB_TAG_SHIFT; - crqb = (struct mv_crqb_iie *) &pp->crqb[pp->req_producer]; + /* get current queue index from hardware */ + in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS) + >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; + + crqb = (struct mv_crqb_iie *) &pp->crqb[in_index]; crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff); crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16); crqb->flags = cpu_to_le32(flags); @@ -1210,6 +1211,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) { void __iomem *port_mmio = mv_ap_base(qc->ap); struct mv_port_priv *pp = qc->ap->private_data; + unsigned in_index; u32 in_ptr; if (ATA_PROT_DMA != qc->tf.protocol) { @@ -1221,23 +1223,20 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) return ata_qc_issue_prot(qc); } - in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS); + in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS); + in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; - /* the req producer index should be the same as we remember it */ - WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != - pp->req_producer); /* until we do queuing, the queue should be empty at this point */ - WARN_ON(((in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != - ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) >> - EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); + WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS) + >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); - mv_inc_q_index(&pp->req_producer); /* now incr producer index */ + in_index = mv_inc_q_index(in_index); /* now incr producer index */ mv_start_dma(port_mmio, pp); /* and write the request in pointer to kick the EDMA to life */ in_ptr &= EDMA_REQ_Q_BASE_LO_MASK; - in_ptr |= pp->req_producer << EDMA_REQ_Q_PTR_SHIFT; + in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT; writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS); return 0; @@ -1260,28 +1259,26 @@ static u8 mv_get_crpb_status(struct ata_port *ap) { void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; + unsigned out_index; u32 out_ptr; u8 ata_status; - out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); + out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); + out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK; - /* the response consumer index should be the same as we remember it */ - WARN_ON(((out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != - pp->rsp_consumer); - - ata_status = pp->crpb[pp->rsp_consumer].flags >> CRPB_FLAG_STATUS_SHIFT; + ata_status = le16_to_cpu(pp->crpb[out_index].flags) + >> CRPB_FLAG_STATUS_SHIFT; /* increment our consumer index... */ - pp->rsp_consumer = mv_inc_q_index(&pp->rsp_consumer); + out_index = mv_inc_q_index(out_index); /* and, until we do NCQ, there should only be 1 CRPB waiting */ - WARN_ON(((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) >> - EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK) != - pp->rsp_consumer); + WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS) + >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK)); /* write out our inc'd consumer index so EDMA knows we're caught up */ out_ptr &= EDMA_RSP_Q_BASE_LO_MASK; - out_ptr |= pp->rsp_consumer << EDMA_RSP_Q_PTR_SHIFT; + out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT; writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); /* Return ATA status register for completed CRPB */ @@ -1291,6 +1288,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) /** * mv_err_intr - Handle error interrupts on the port * @ap: ATA channel to manipulate + * @reset_allowed: bool: 0 == don't trigger from reset here * * In most cases, just clear the interrupt and move on. However, * some cases require an eDMA reset, which is done right before @@ -1301,7 +1299,7 @@ static u8 mv_get_crpb_status(struct ata_port *ap) * LOCKING: * Inherited from caller. */ -static void mv_err_intr(struct ata_port *ap) +static void mv_err_intr(struct ata_port *ap, int reset_allowed) { void __iomem *port_mmio = mv_ap_base(ap); u32 edma_err_cause, serr = 0; @@ -1323,9 +1321,8 @@ static void mv_err_intr(struct ata_port *ap) writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); /* check for fatal here and recover if needed */ - if (EDMA_ERR_FATAL & edma_err_cause) { + if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause)) mv_stop_and_reset(ap); - } } /** @@ -1374,12 +1371,12 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, struct ata_port *ap = host_set->ports[port]; struct mv_port_priv *pp = ap->private_data; - hard_port = port & MV_PORT_MASK; /* range 0-3 */ + hard_port = mv_hardport_from_port(port); /* range 0..3 */ handled = 0; /* ensure ata_status is set if handled++ */ /* Note that DEV_IRQ might happen spuriously during EDMA, - * and should be ignored in such cases. We could mask it, - * but it's pretty rare and may not be worth the overhead. + * and should be ignored in such cases. + * The cause of this is still under investigation. */ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { /* EDMA: check for response queue interrupt */ @@ -1393,6 +1390,11 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, ata_status = readb((void __iomem *) ap->ioaddr.status_addr); handled = 1; + /* ignore spurious intr if drive still BUSY */ + if (ata_status & ATA_BUSY) { + ata_status = 0; + handled = 0; + } } } @@ -1406,7 +1408,7 @@ static void mv_host_intr(struct ata_host_set *host_set, u32 relevant, shift++; /* skip bit 8 in the HC Main IRQ reg */ } if ((PORT0_ERR << shift) & relevant) { - mv_err_intr(ap); + mv_err_intr(ap, 1); err_mask |= AC_ERR_OTHER; handled = 1; } @@ -1448,6 +1450,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, struct ata_host_set *host_set = dev_instance; unsigned int hc, handled = 0, n_hcs; void __iomem *mmio = host_set->mmio_base; + struct mv_host_priv *hpriv; u32 irq_stat; irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS); @@ -1469,6 +1472,17 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, handled++; } } + + hpriv = host_set->private_data; + if (IS_60XX(hpriv)) { + /* deal with the interrupt coalescing bits */ + if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) { + writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO); + writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI); + writelfl(0, mmio + MV_IRQ_COAL_CAUSE); + } + } + if (PCI_ERR & irq_stat) { printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n", readl(mmio + PCI_IRQ_CAUSE_OFS)); @@ -1867,7 +1881,8 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, if (IS_60XX(hpriv)) { u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); - ifctl |= (1 << 12) | (1 << 7); + ifctl |= (1 << 7); /* enable gen2i speed */ + ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); } @@ -2031,11 +2046,14 @@ static void mv_eng_timeout(struct ata_port *ap) ap->host_set->mmio_base, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd); - mv_err_intr(ap); + mv_err_intr(ap, 0); mv_stop_and_reset(ap); - qc->err_mask |= AC_ERR_TIMEOUT; - ata_eh_qc_complete(qc); + WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); + if (qc->flags & ATA_QCFLAG_ACTIVE) { + qc->err_mask |= AC_ERR_TIMEOUT; + ata_eh_qc_complete(qc); + } } /** @@ -2229,7 +2247,8 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent, void __iomem *port_mmio = mv_port_base(mmio, port); u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL); - ifctl |= (1 << 12); + ifctl |= (1 << 7); /* enable gen2i speed */ + ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */ writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL); } @@ -2330,6 +2349,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) { return rc; } + pci_set_master(pdev); rc = pci_request_regions(pdev, DRV_NAME); if (rc) { diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index d40e7c871c36..56cb49006116 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4054,7 +4054,7 @@ static int st_probe(struct device *dev) } sdev_printk(KERN_WARNING, SDp, - "Attached scsi tape %s", tape_name(tpnt)); + "Attached scsi tape %s\n", tape_name(tpnt)); printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", tape_name(tpnt), tpnt->try_dio ? "yes" : "no", queue_dma_alignment(SDp->request_queue) + 1); diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 1c4396c2962d..2b4f96541b8e 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1730,3 +1730,4 @@ static void __exit sunsu_exit(void) module_init(sunsu_probe); module_exit(sunsu_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9ce1d01469b1..23334c8bc4c7 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -75,6 +75,18 @@ config SPI_BUTTERFLY inexpensive battery powered microcontroller evaluation board. This same cable can be used to flash new firmware. +config SPI_MPC83xx + tristate "Freescale MPC83xx SPI controller" + depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL + select SPI_BITBANG + help + This enables using the Freescale MPC83xx SPI controller in master + mode. + + Note, this driver uniquely supports the SPI controller on the MPC83xx + family of PowerPC processors. The MPC83xx uses a simple set of shift + registers for data (opposed to the CPM based descriptor model). + config SPI_PXA2XX tristate "PXA2xx SSP SPI master" depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL @@ -83,11 +95,25 @@ config SPI_PXA2XX The driver can be configured to use any SSP port and additional documentation can be found a Documentation/spi/pxa2xx. +config SPI_S3C24XX_GPIO + tristate "Samsung S3C24XX series SPI by GPIO" + depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL + help + SPI driver for Samsung S3C24XX series ARM SoCs using + GPIO lines to provide the SPI bus. This can be used where + the inbuilt hardware cannot provide the transfer mode, or + where the board is using non hardware connected pins. # # Add new SPI master controllers in alphabetical order above this line # +config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL + help + SPI driver for Samsung S3C24XX series ARM SoCs + # # There are lots of SPI device types, with sensors and memory # being probably the most widely used ones. diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 1bca5f95de25..8f4cb67997b3 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -14,6 +14,9 @@ obj-$(CONFIG_SPI_MASTER) += spi.o obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_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 # ... add above this line ... # SPI protocol drivers (device/link on bus) diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 596bf820b70c..29aec77f98be 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -363,25 +363,30 @@ static void unmap_dma_buffers(struct driver_data *drv_data) } /* caller already set message->status; dma and pio irqs are blocked */ -static void giveback(struct spi_message *message, struct driver_data *drv_data) +static void giveback(struct driver_data *drv_data) { struct spi_transfer* last_transfer; + unsigned long flags; + struct spi_message *msg; - last_transfer = list_entry(message->transfers.prev, + spin_lock_irqsave(&drv_data->lock, flags); + msg = drv_data->cur_msg; + drv_data->cur_msg = NULL; + drv_data->cur_transfer = NULL; + drv_data->cur_chip = NULL; + queue_work(drv_data->workqueue, &drv_data->pump_messages); + spin_unlock_irqrestore(&drv_data->lock, flags); + + last_transfer = list_entry(msg->transfers.prev, struct spi_transfer, transfer_list); if (!last_transfer->cs_change) drv_data->cs_control(PXA2XX_CS_DEASSERT); - message->state = NULL; - if (message->complete) - message->complete(message->context); - - drv_data->cur_msg = NULL; - drv_data->cur_transfer = NULL; - drv_data->cur_chip = NULL; - queue_work(drv_data->workqueue, &drv_data->pump_messages); + msg->state = NULL; + if (msg->complete) + msg->complete(msg->context); } static int wait_ssp_rx_stall(void *ioaddr) @@ -415,10 +420,11 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs) if (irq_status & DCSR_BUSERR) { /* Disable interrupts, clear status and reset DMA */ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; @@ -454,8 +460,8 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs) "dma_handler: ssp rx stall failed\n"); /* Clear and disable interrupts on SSP and DMA channels*/ - write_SSSR(drv_data->clear_sr, reg); write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); + write_SSSR(drv_data->clear_sr, reg); DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; if (wait_dma_channel_stop(drv_data->rx_channel) == 0) @@ -497,10 +503,11 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) irq_status = read_SSSR(reg) & drv_data->mask_sr; if (irq_status & SSSR_ROR) { /* Clear and disable interrupts on SSP and DMA channels*/ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; unmap_dma_buffers(drv_data); @@ -526,10 +533,10 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { /* Clear and disable interrupts on SSP and DMA channels*/ + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; @@ -572,26 +579,30 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) static irqreturn_t interrupt_transfer(struct driver_data *drv_data) { - u32 irq_status; struct spi_message *msg = drv_data->cur_msg; void *reg = drv_data->ioaddr; - irqreturn_t handled = IRQ_NONE; unsigned long limit = loops_per_jiffy << 1; + u32 irq_status; + u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ? + drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS; - while ((irq_status = (read_SSSR(reg) & drv_data->mask_sr))) { + while ((irq_status = read_SSSR(reg) & irq_mask)) { if (irq_status & SSSR_ROR) { /* Clear and disable interrupts */ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); if (flush(drv_data) == 0) dev_err(&drv_data->pdev->dev, "interrupt_transfer: flush fail\n"); + /* Stop the SSP */ + dev_warn(&drv_data->pdev->dev, "interrupt_transfer: fifo overun\n"); @@ -613,6 +624,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) if (drv_data->tx == drv_data->tx_end) { /* Disable tx interrupt */ write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); + irq_mask = drv_data->mask_sr & ~SSSR_TFS; /* PXA25x_SSP has no timeout, read trailing bytes */ if (drv_data->ssp_type == PXA25x_SSP) { @@ -630,10 +642,10 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) || (drv_data->rx == drv_data->rx_end)) { /* Clear timeout */ + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); /* Update total byte transfered */ msg->actual_length += drv_data->len; @@ -648,24 +660,29 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) /* Schedule transfer tasklet */ tasklet_schedule(&drv_data->pump_transfers); - - return IRQ_HANDLED; } - - /* We did something */ - handled = IRQ_HANDLED; } - return handled; + /* We did something */ + return IRQ_HANDLED; } static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs) { struct driver_data *drv_data = (struct driver_data *)dev_id; + void *reg = drv_data->ioaddr; if (!drv_data->cur_msg) { + + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); + if (drv_data->ssp_type != PXA25x_SSP) + write_SSTO(0, reg); + write_SSSR(drv_data->clear_sr, reg); + dev_err(&drv_data->pdev->dev, "bad message state " - "in interrupt handler\n"); + "in interrupt handler"); + /* Never fail */ return IRQ_HANDLED; } @@ -694,14 +711,14 @@ static void pump_transfers(unsigned long data) /* Handle for abort */ if (message->state == ERROR_STATE) { message->status = -EIO; - giveback(message, drv_data); + giveback(drv_data); return; } /* Handle end of message */ if (message->state == DONE_STATE) { message->status = 0; - giveback(message, drv_data); + giveback(drv_data); return; } @@ -718,7 +735,7 @@ static void pump_transfers(unsigned long data) if (flush(drv_data) == 0) { dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); message->status = -EIO; - giveback(message, drv_data); + giveback(drv_data); return; } drv_data->n_bytes = chip->n_bytes; @@ -782,7 +799,7 @@ static void pump_transfers(unsigned long data) cr0 = clk_div | SSCR0_Motorola - | SSCR0_DataSize(bits & 0x0f) + | SSCR0_DataSize(bits > 16 ? bits - 16 : bits) | SSCR0_SSE | (bits > 16 ? SSCR0_EDSS : 0); @@ -890,8 +907,6 @@ static void pump_messages(void *data) drv_data->cur_msg = list_entry(drv_data->queue.next, struct spi_message, queue); list_del_init(&drv_data->cur_msg->queue); - drv_data->busy = 1; - spin_unlock_irqrestore(&drv_data->lock, flags); /* Initial message state*/ drv_data->cur_msg->state = START_STATE; @@ -905,6 +920,9 @@ static void pump_messages(void *data) /* Mark as busy and launch transfers */ tasklet_schedule(&drv_data->pump_transfers); + + drv_data->busy = 1; + spin_unlock_irqrestore(&drv_data->lock, flags); } static int transfer(struct spi_device *spi, struct spi_message *msg) @@ -958,7 +976,7 @@ static int setup(struct spi_device *spi) chip->cs_control = null_cs_control; chip->enable_dma = 0; - chip->timeout = 5; + chip->timeout = SSP_TIMEOUT(1000); chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); chip->dma_burst_size = drv_data->master_info->enable_dma ? DCMD_BURST8 : 0; @@ -971,7 +989,7 @@ static int setup(struct spi_device *spi) if (chip_info->cs_control) chip->cs_control = chip_info->cs_control; - chip->timeout = (chip_info->timeout_microsecs * 10000) / 2712; + chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs); chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold) | SSCR1_TxTresh(chip_info->tx_threshold); @@ -1013,7 +1031,8 @@ static int setup(struct spi_device *spi) chip->cr0 = clk_div | SSCR0_Motorola - | SSCR0_DataSize(spi->bits_per_word & 0x0f) + | SSCR0_DataSize(spi->bits_per_word > 16 ? + spi->bits_per_word - 16 : spi->bits_per_word) | SSCR0_SSE | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0); chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4) @@ -1196,7 +1215,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) goto out_error_master_alloc; } - drv_data->ioaddr = (void *)io_p2v(memory_resource->start); + drv_data->ioaddr = (void *)io_p2v((unsigned long)(memory_resource->start)); drv_data->ssdr_physical = memory_resource->start + 0x00000010; if (platform_info->ssp_type == PXA25x_SSP) { drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; @@ -1218,7 +1237,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) goto out_error_master_alloc; } - status = request_irq(irq, ssp_int, SA_INTERRUPT, dev->bus_id, drv_data); + status = request_irq(irq, ssp_int, 0, dev->bus_id, drv_data); if (status < 0) { dev_err(&pdev->dev, "can not get IRQ\n"); goto out_error_master_alloc; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7a3f733051e9..1cea4a6799fe 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -338,18 +338,18 @@ static struct class spi_master_class = { * spi_alloc_master - allocate SPI master controller * @dev: the controller, possibly using the platform_bus * @size: how much driver-private data to preallocate; the pointer to this - * memory is in the class_data field of the returned class_device, + * memory is in the class_data field of the returned class_device, * accessible with spi_master_get_devdata(). * * This call is used only by SPI master controller drivers, which are the * only ones directly touching chip registers. It's how they allocate - * an spi_master structure, prior to calling spi_add_master(). + * an spi_master structure, prior to calling spi_register_master(). * * This must be called from context that can sleep. It returns the SPI * master structure on success, else NULL. * * The caller is responsible for assigning the bus number and initializing - * the master's methods before calling spi_add_master(); and (after errors + * the master's methods before calling spi_register_master(); and (after errors * adding the device) calling spi_master_put() to prevent a memory leak. */ struct spi_master * __init_or_module diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c index ff9e5faa4dc9..a006a1ee27ac 100644 --- a/drivers/spi/spi_butterfly.c +++ b/drivers/spi/spi_butterfly.c @@ -321,6 +321,7 @@ static void butterfly_attach(struct parport *p) * (firmware resets at45, acts as spi slave) or neither (we ignore * both, AVR uses AT45). Here we expect firmware for the first option. */ + pp->info[0].max_speed_hz = 15 * 1000 * 1000; strcpy(pp->info[0].modalias, "mtd_dataflash"); pp->info[0].platform_data = &flash; diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c new file mode 100644 index 000000000000..5d92a7e5cb41 --- /dev/null +++ b/drivers/spi/spi_mpc83xx.c @@ -0,0 +1,483 @@ +/* + * MPC83xx SPI controller driver. + * + * Maintainer: Kumar Gala + * + * Copyright (C) 2006 Polycom, 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. + */ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/completion.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/device.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi_bitbang.h> +#include <linux/platform_device.h> +#include <linux/fsl_devices.h> + +#include <asm/irq.h> +#include <asm/io.h> + +/* SPI Controller registers */ +struct mpc83xx_spi_reg { + u8 res1[0x20]; + __be32 mode; + __be32 event; + __be32 mask; + __be32 command; + __be32 transmit; + __be32 receive; +}; + +/* SPI Controller mode register definitions */ +#define SPMODE_CI_INACTIVEHIGH (1 << 29) +#define SPMODE_CP_BEGIN_EDGECLK (1 << 28) +#define SPMODE_DIV16 (1 << 27) +#define SPMODE_REV (1 << 26) +#define SPMODE_MS (1 << 25) +#define SPMODE_ENABLE (1 << 24) +#define SPMODE_LEN(x) ((x) << 20) +#define SPMODE_PM(x) ((x) << 16) + +/* + * Default for SPI Mode: + * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk + */ +#define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \ + SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf)) + +/* SPIE register values */ +#define SPIE_NE 0x00000200 /* Not empty */ +#define SPIE_NF 0x00000100 /* Not full */ + +/* SPIM register values */ +#define SPIM_NE 0x00000200 /* Not empty */ +#define SPIM_NF 0x00000100 /* Not full */ + +/* SPI Controller driver's private data. */ +struct mpc83xx_spi { + /* bitbang has to be first */ + struct spi_bitbang bitbang; + struct completion done; + + struct mpc83xx_spi_reg __iomem *base; + + /* rx & tx bufs from the spi_transfer */ + const void *tx; + void *rx; + + /* functions to deal with different sized buffers */ + void (*get_rx) (u32 rx_data, struct mpc83xx_spi *); + u32(*get_tx) (struct mpc83xx_spi *); + + unsigned int count; + u32 irq; + + unsigned nsecs; /* (clock cycle time)/2 */ + + u32 sysclk; + void (*activate_cs) (u8 cs, u8 polarity); + void (*deactivate_cs) (u8 cs, u8 polarity); +}; + +static inline void mpc83xx_spi_write_reg(__be32 __iomem * reg, u32 val) +{ + out_be32(reg, val); +} + +static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg) +{ + return in_be32(reg); +} + +#define MPC83XX_SPI_RX_BUF(type) \ +void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ +{ \ + type * rx = mpc83xx_spi->rx; \ + *rx++ = (type)data; \ + mpc83xx_spi->rx = rx; \ +} + +#define MPC83XX_SPI_TX_BUF(type) \ +u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \ +{ \ + u32 data; \ + const type * tx = mpc83xx_spi->tx; \ + data = *tx++; \ + mpc83xx_spi->tx = tx; \ + return data; \ +} + +MPC83XX_SPI_RX_BUF(u8) +MPC83XX_SPI_RX_BUF(u16) +MPC83XX_SPI_RX_BUF(u32) +MPC83XX_SPI_TX_BUF(u8) +MPC83XX_SPI_TX_BUF(u16) +MPC83XX_SPI_TX_BUF(u32) + +static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) +{ + struct mpc83xx_spi *mpc83xx_spi; + u8 pol = spi->mode & SPI_CS_HIGH ? 1 : 0; + + mpc83xx_spi = spi_master_get_devdata(spi->master); + + if (value == BITBANG_CS_INACTIVE) { + if (mpc83xx_spi->deactivate_cs) + mpc83xx_spi->deactivate_cs(spi->chip_select, pol); + } + + if (value == BITBANG_CS_ACTIVE) { + u32 regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); + u32 len = spi->bits_per_word; + if (len == 32) + len = 0; + else + len = len - 1; + + /* mask out bits we are going to set */ + regval &= ~0x38ff0000; + + if (spi->mode & SPI_CPHA) + regval |= SPMODE_CP_BEGIN_EDGECLK; + if (spi->mode & SPI_CPOL) + regval |= SPMODE_CI_INACTIVEHIGH; + + regval |= SPMODE_LEN(len); + + if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) { + u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64); + regval |= SPMODE_PM(pm) | SPMODE_DIV16; + } else { + u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4); + regval |= SPMODE_PM(pm); + } + + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); + if (mpc83xx_spi->activate_cs) + mpc83xx_spi->activate_cs(spi->chip_select, pol); + } +} + +static +int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) +{ + struct mpc83xx_spi *mpc83xx_spi; + u32 regval; + u8 bits_per_word; + u32 hz; + + mpc83xx_spi = spi_master_get_devdata(spi->master); + + if (t) { + bits_per_word = t->bits_per_word; + hz = t->speed_hz; + } else { + bits_per_word = 0; + hz = 0; + } + + /* spi_transfer level calls that work per-word */ + if (!bits_per_word) + bits_per_word = spi->bits_per_word; + + /* Make sure its a bit width we support [4..16, 32] */ + if ((bits_per_word < 4) + || ((bits_per_word > 16) && (bits_per_word != 32))) + return -EINVAL; + + if (bits_per_word <= 8) { + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; + } else if (bits_per_word <= 16) { + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16; + } else if (bits_per_word <= 32) { + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32; + } else + return -EINVAL; + + /* nsecs = (clock period)/2 */ + if (!hz) + hz = spi->max_speed_hz; + mpc83xx_spi->nsecs = (1000000000 / 2) / hz; + if (mpc83xx_spi->nsecs > MAX_UDELAY_MS * 1000) + return -EINVAL; + + if (bits_per_word == 32) + bits_per_word = 0; + else + bits_per_word = bits_per_word - 1; + + regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); + + /* Mask out bits_per_wordgth */ + regval &= 0xff0fffff; + regval |= SPMODE_LEN(bits_per_word); + + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); + + return 0; +} + +static int mpc83xx_spi_setup(struct spi_device *spi) +{ + struct spi_bitbang *bitbang; + struct mpc83xx_spi *mpc83xx_spi; + int retval; + + if (!spi->max_speed_hz) + return -EINVAL; + + bitbang = spi_master_get_devdata(spi->master); + mpc83xx_spi = spi_master_get_devdata(spi->master); + + if (!spi->bits_per_word) + spi->bits_per_word = 8; + + retval = mpc83xx_spi_setup_transfer(spi, NULL); + if (retval < 0) + return retval; + + dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", + __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), + spi->bits_per_word, 2 * mpc83xx_spi->nsecs); + + /* NOTE we _need_ to call chipselect() early, ideally with adapter + * setup, unless the hardware defaults cooperate to avoid confusion + * between normal (active low) and inverted chipselects. + */ + + /* deselect chip (low or high) */ + spin_lock(&bitbang->lock); + if (!bitbang->busy) { + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(mpc83xx_spi->nsecs); + } + spin_unlock(&bitbang->lock); + + return 0; +} + +static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t) +{ + struct mpc83xx_spi *mpc83xx_spi; + u32 word; + + mpc83xx_spi = spi_master_get_devdata(spi->master); + + mpc83xx_spi->tx = t->tx_buf; + mpc83xx_spi->rx = t->rx_buf; + mpc83xx_spi->count = t->len; + INIT_COMPLETION(mpc83xx_spi->done); + + /* enable rx ints */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, SPIM_NE); + + /* transmit word */ + word = mpc83xx_spi->get_tx(mpc83xx_spi); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, word); + + wait_for_completion(&mpc83xx_spi->done); + + /* disable rx ints */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0); + + return t->len - mpc83xx_spi->count; +} + +irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data, + struct pt_regs * ptregs) +{ + struct mpc83xx_spi *mpc83xx_spi = context_data; + u32 event; + irqreturn_t ret = IRQ_NONE; + + /* Get interrupt events(tx/rx) */ + event = mpc83xx_spi_read_reg(&mpc83xx_spi->base->event); + + /* We need handle RX first */ + if (event & SPIE_NE) { + u32 rx_data = mpc83xx_spi_read_reg(&mpc83xx_spi->base->receive); + + if (mpc83xx_spi->rx) + mpc83xx_spi->get_rx(rx_data, mpc83xx_spi); + + ret = IRQ_HANDLED; + } + + if ((event & SPIE_NF) == 0) + /* spin until TX is done */ + while (((event = + mpc83xx_spi_read_reg(&mpc83xx_spi->base->event)) & + SPIE_NF) == 0) + cpu_relax(); + + mpc83xx_spi->count -= 1; + if (mpc83xx_spi->count) { + if (mpc83xx_spi->tx) { + u32 word = mpc83xx_spi->get_tx(mpc83xx_spi); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, + word); + } + } else { + complete(&mpc83xx_spi->done); + } + + /* Clear the events */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, event); + + return ret; +} + +static int __init mpc83xx_spi_probe(struct platform_device *dev) +{ + struct spi_master *master; + struct mpc83xx_spi *mpc83xx_spi; + struct fsl_spi_platform_data *pdata; + struct resource *r; + u32 regval; + int ret = 0; + + /* Get resources(memory, IRQ) associated with the device */ + master = spi_alloc_master(&dev->dev, sizeof(struct mpc83xx_spi)); + + if (master == NULL) { + ret = -ENOMEM; + goto err; + } + + platform_set_drvdata(dev, master); + pdata = dev->dev.platform_data; + + if (pdata == NULL) { + ret = -ENODEV; + goto free_master; + } + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (r == NULL) { + ret = -ENODEV; + goto free_master; + } + + mpc83xx_spi = spi_master_get_devdata(master); + mpc83xx_spi->bitbang.master = spi_master_get(master); + mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect; + mpc83xx_spi->bitbang.setup_transfer = mpc83xx_spi_setup_transfer; + mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs; + mpc83xx_spi->sysclk = pdata->sysclk; + mpc83xx_spi->activate_cs = pdata->activate_cs; + mpc83xx_spi->deactivate_cs = pdata->deactivate_cs; + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; + + mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup; + init_completion(&mpc83xx_spi->done); + + mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1); + if (mpc83xx_spi->base == NULL) { + ret = -ENOMEM; + goto put_master; + } + + mpc83xx_spi->irq = platform_get_irq(dev, 0); + + if (mpc83xx_spi->irq < 0) { + ret = -ENXIO; + goto unmap_io; + } + + /* Register for SPI Interrupt */ + ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq, + 0, "mpc83xx_spi", mpc83xx_spi); + + if (ret != 0) + goto unmap_io; + + master->bus_num = pdata->bus_num; + master->num_chipselect = pdata->max_chipselect; + + /* SPI controller initializations */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->command, 0); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, 0xffffffff); + + /* Enable SPI interface */ + regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); + + ret = spi_bitbang_start(&mpc83xx_spi->bitbang); + + if (ret != 0) + goto free_irq; + + printk(KERN_INFO + "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", + dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq); + + return ret; + +free_irq: + free_irq(mpc83xx_spi->irq, mpc83xx_spi); +unmap_io: + iounmap(mpc83xx_spi->base); +put_master: + spi_master_put(master); +free_master: + kfree(master); +err: + return ret; +} + +static int __devexit mpc83xx_spi_remove(struct platform_device *dev) +{ + struct mpc83xx_spi *mpc83xx_spi; + struct spi_master *master; + + master = platform_get_drvdata(dev); + mpc83xx_spi = spi_master_get_devdata(master); + + spi_bitbang_stop(&mpc83xx_spi->bitbang); + free_irq(mpc83xx_spi->irq, mpc83xx_spi); + iounmap(mpc83xx_spi->base); + spi_master_put(mpc83xx_spi->bitbang.master); + + return 0; +} + +static struct platform_driver mpc83xx_spi_driver = { + .probe = mpc83xx_spi_probe, + .remove = __devexit_p(mpc83xx_spi_remove), + .driver = { + .name = "mpc83xx_spi", + }, +}; + +static int __init mpc83xx_spi_init(void) +{ + return platform_driver_register(&mpc83xx_spi_driver); +} + +static void __exit mpc83xx_spi_exit(void) +{ + platform_driver_unregister(&mpc83xx_spi_driver); +} + +module_init(mpc83xx_spi_init); +module_exit(mpc83xx_spi_exit); + +MODULE_AUTHOR("Kumar Gala"); +MODULE_DESCRIPTION("Simple MPC83xx SPI Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c new file mode 100644 index 000000000000..9de4b5a04d70 --- /dev/null +++ b/drivers/spi/spi_s3c24xx.c @@ -0,0 +1,453 @@ +/* linux/drivers/spi/spi_s3c24xx.c + * + * Copyright (c) 2006 Ben Dooks + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * 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. + * +*/ + + +//#define DEBUG + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/platform_device.h> + +#include <linux/spi/spi.h> +#include <linux/spi/spi_bitbang.h> + +#include <asm/io.h> +#include <asm/dma.h> +#include <asm/hardware.h> + +#include <asm/arch/regs-gpio.h> +#include <asm/arch/regs-spi.h> +#include <asm/arch/spi.h> + +struct s3c24xx_spi { + /* bitbang has to be first */ + struct spi_bitbang bitbang; + struct completion done; + + void __iomem *regs; + int irq; + int len; + int count; + + /* data buffers */ + const unsigned char *tx; + unsigned char *rx; + + struct clk *clk; + struct resource *ioarea; + struct spi_master *master; + struct spi_device *curdev; + struct device *dev; + struct s3c2410_spi_info *pdata; +}; + +#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT) +#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP) + +static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev) +{ + return spi_master_get_devdata(sdev->master); +} + +static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) +{ + struct s3c24xx_spi *hw = to_hw(spi); + unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; + unsigned int spcon; + + switch (value) { + case BITBANG_CS_INACTIVE: + if (hw->pdata->set_cs) + hw->pdata->set_cs(hw->pdata, value, cspol); + else + s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1); + break; + + case BITBANG_CS_ACTIVE: + spcon = readb(hw->regs + S3C2410_SPCON); + + if (spi->mode & SPI_CPHA) + spcon |= S3C2410_SPCON_CPHA_FMTB; + else + spcon &= ~S3C2410_SPCON_CPHA_FMTB; + + if (spi->mode & SPI_CPOL) + spcon |= S3C2410_SPCON_CPOL_HIGH; + else + spcon &= ~S3C2410_SPCON_CPOL_HIGH; + + spcon |= S3C2410_SPCON_ENSCK; + + /* write new configration */ + + writeb(spcon, hw->regs + S3C2410_SPCON); + + if (hw->pdata->set_cs) + hw->pdata->set_cs(hw->pdata, value, cspol); + else + s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol); + + break; + + } +} + +static int s3c24xx_spi_setupxfer(struct spi_device *spi, + struct spi_transfer *t) +{ + struct s3c24xx_spi *hw = to_hw(spi); + unsigned int bpw; + unsigned int hz; + unsigned int div; + + bpw = t ? t->bits_per_word : spi->bits_per_word; + hz = t ? t->speed_hz : spi->max_speed_hz; + + if (bpw != 8) { + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); + return -EINVAL; + } + + div = clk_get_rate(hw->clk) / hz; + + /* is clk = pclk / (2 * (pre+1)), or is it + * clk = (pclk * 2) / ( pre + 1) */ + + div = (div / 2) - 1; + + if (div < 0) + div = 1; + + if (div > 255) + div = 255; + + dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz); + writeb(div, hw->regs + S3C2410_SPPRE); + + spin_lock(&hw->bitbang.lock); + if (!hw->bitbang.busy) { + hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); + /* need to ndelay for 0.5 clocktick ? */ + } + spin_unlock(&hw->bitbang.lock); + + return 0; +} + +static int s3c24xx_spi_setup(struct spi_device *spi) +{ + int ret; + + if (!spi->bits_per_word) + spi->bits_per_word = 8; + + if ((spi->mode & SPI_LSB_FIRST) != 0) + return -EINVAL; + + ret = s3c24xx_spi_setupxfer(spi, NULL); + if (ret < 0) { + dev_err(&spi->dev, "setupxfer returned %d\n", ret); + return ret; + } + + dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", + __FUNCTION__, spi->mode, spi->bits_per_word, + spi->max_speed_hz); + + return 0; +} + +static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count) +{ + return hw->tx ? hw->tx[count] : 0xff; +} + +static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t) +{ + struct s3c24xx_spi *hw = to_hw(spi); + + dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", + t->tx_buf, t->rx_buf, t->len); + + hw->tx = t->tx_buf; + hw->rx = t->rx_buf; + hw->len = t->len; + hw->count = 0; + + /* send the first byte */ + writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT); + wait_for_completion(&hw->done); + + return hw->count; +} + +static irqreturn_t s3c24xx_spi_irq(int irq, void *dev, struct pt_regs *regs) +{ + struct s3c24xx_spi *hw = dev; + unsigned int spsta = readb(hw->regs + S3C2410_SPSTA); + unsigned int count = hw->count; + + if (spsta & S3C2410_SPSTA_DCOL) { + dev_dbg(hw->dev, "data-collision\n"); + complete(&hw->done); + goto irq_done; + } + + if (!(spsta & S3C2410_SPSTA_READY)) { + dev_dbg(hw->dev, "spi not ready for tx?\n"); + complete(&hw->done); + goto irq_done; + } + + hw->count++; + + if (hw->rx) + hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT); + + count++; + + if (count < hw->len) + writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT); + else + complete(&hw->done); + + irq_done: + return IRQ_HANDLED; +} + +static int s3c24xx_spi_probe(struct platform_device *pdev) +{ + struct s3c24xx_spi *hw; + struct spi_master *master; + struct spi_board_info *bi; + struct resource *res; + int err = 0; + int i; + + master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); + if (master == NULL) { + dev_err(&pdev->dev, "No memory for spi_master\n"); + err = -ENOMEM; + goto err_nomem; + } + + hw = spi_master_get_devdata(master); + memset(hw, 0, sizeof(struct s3c24xx_spi)); + + hw->master = spi_master_get(master); + hw->pdata = pdev->dev.platform_data; + hw->dev = &pdev->dev; + + if (hw->pdata == NULL) { + dev_err(&pdev->dev, "No platform data supplied\n"); + err = -ENOENT; + goto err_no_pdata; + } + + platform_set_drvdata(pdev, hw); + init_completion(&hw->done); + + /* setup the state for the bitbang driver */ + + hw->bitbang.master = hw->master; + hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer; + hw->bitbang.chipselect = s3c24xx_spi_chipsel; + hw->bitbang.txrx_bufs = s3c24xx_spi_txrx; + hw->bitbang.master->setup = s3c24xx_spi_setup; + + dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); + + /* find and map our resources */ + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); + err = -ENOENT; + goto err_no_iores; + } + + hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1, + pdev->name); + + if (hw->ioarea == NULL) { + dev_err(&pdev->dev, "Cannot reserve region\n"); + err = -ENXIO; + goto err_no_iores; + } + + hw->regs = ioremap(res->start, (res->end - res->start)+1); + if (hw->regs == NULL) { + dev_err(&pdev->dev, "Cannot map IO\n"); + err = -ENXIO; + goto err_no_iomap; + } + + hw->irq = platform_get_irq(pdev, 0); + if (hw->irq < 0) { + dev_err(&pdev->dev, "No IRQ specified\n"); + err = -ENOENT; + goto err_no_irq; + } + + err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw); + if (err) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto err_no_irq; + } + + hw->clk = clk_get(&pdev->dev, "spi"); + if (IS_ERR(hw->clk)) { + dev_err(&pdev->dev, "No clock for device\n"); + err = PTR_ERR(hw->clk); + goto err_no_clk; + } + + /* for the moment, permanently enable the clock */ + + clk_enable(hw->clk); + + /* program defaults into the registers */ + + writeb(0xff, hw->regs + S3C2410_SPPRE); + writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); + writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); + + /* setup any gpio we can */ + + if (!hw->pdata->set_cs) { + s3c2410_gpio_setpin(hw->pdata->pin_cs, 1); + s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT); + } + + /* register our spi controller */ + + err = spi_bitbang_start(&hw->bitbang); + if (err) { + dev_err(&pdev->dev, "Failed to register SPI master\n"); + goto err_register; + } + + dev_dbg(hw->dev, "shutdown=%d\n", hw->bitbang.shutdown); + + /* register all the devices associated */ + + bi = &hw->pdata->board_info[0]; + for (i = 0; i < hw->pdata->board_size; i++, bi++) { + dev_info(hw->dev, "registering %s\n", bi->modalias); + + bi->controller_data = hw; + spi_new_device(master, bi); + } + + return 0; + + err_register: + clk_disable(hw->clk); + clk_put(hw->clk); + + err_no_clk: + free_irq(hw->irq, hw); + + err_no_irq: + iounmap(hw->regs); + + err_no_iomap: + release_resource(hw->ioarea); + kfree(hw->ioarea); + + err_no_iores: + err_no_pdata: + spi_master_put(hw->master);; + + err_nomem: + return err; +} + +static int s3c24xx_spi_remove(struct platform_device *dev) +{ + struct s3c24xx_spi *hw = platform_get_drvdata(dev); + + platform_set_drvdata(dev, NULL); + + spi_unregister_master(hw->master); + + clk_disable(hw->clk); + clk_put(hw->clk); + + free_irq(hw->irq, hw); + iounmap(hw->regs); + + release_resource(hw->ioarea); + kfree(hw->ioarea); + + spi_master_put(hw->master); + return 0; +} + + +#ifdef CONFIG_PM + +static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) +{ + struct s3c24xx_spi *hw = platform_get_drvdata(dev); + + clk_disable(hw->clk); + return 0; +} + +static int s3c24xx_spi_resume(struct platform_device *pdev) +{ + struct s3c24xx_spi *hw = platform_get_drvdata(dev); + + clk_enable(hw->clk); + return 0; +} + +#else +#define s3c24xx_spi_suspend NULL +#define s3c24xx_spi_resume NULL +#endif + +static struct platform_driver s3c24xx_spidrv = { + .probe = s3c24xx_spi_probe, + .remove = s3c24xx_spi_remove, + .suspend = s3c24xx_spi_suspend, + .resume = s3c24xx_spi_resume, + .driver = { + .name = "s3c2410-spi", + .owner = THIS_MODULE, + }, +}; + +static int __init s3c24xx_spi_init(void) +{ + return platform_driver_register(&s3c24xx_spidrv); +} + +static void __exit s3c24xx_spi_exit(void) +{ + platform_driver_unregister(&s3c24xx_spidrv); +} + +module_init(s3c24xx_spi_init); +module_exit(s3c24xx_spi_exit); + +MODULE_DESCRIPTION("S3C24XX SPI Driver"); +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c new file mode 100644 index 000000000000..aacdceb8f44b --- /dev/null +++ b/drivers/spi/spi_s3c24xx_gpio.c @@ -0,0 +1,188 @@ +/* linux/drivers/spi/spi_s3c24xx_gpio.c + * + * Copyright (c) 2006 Ben Dooks + * Copyright (c) 2006 Simtec Electronics + * + * S3C24XX GPIO based SPI driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/platform_device.h> + +#include <linux/spi/spi.h> +#include <linux/spi/spi_bitbang.h> + +#include <asm/arch/regs-gpio.h> +#include <asm/arch/spi-gpio.h> +#include <asm/arch/hardware.h> + +struct s3c2410_spigpio { + struct spi_bitbang bitbang; + + struct s3c2410_spigpio_info *info; + struct platform_device *dev; +}; + +static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi) +{ + return spi->controller_data; +} + +static inline void setsck(struct spi_device *dev, int on) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0); +} + +static inline void setmosi(struct spi_device *dev, int on) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0); +} + +static inline u32 getmiso(struct spi_device *dev) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0; +} + +#define spidelay(x) ndelay(x) + +#define EXPAND_BITBANG_TXRX +#include <linux/spi/spi_bitbang.h> + + +static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); +} + +static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); +} + +static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + + if (sg->info && sg->info->chip_select) + (sg->info->chip_select)(sg->info, value); +} + +static int s3c2410_spigpio_probe(struct platform_device *dev) +{ + struct spi_master *master; + struct s3c2410_spigpio *sp; + int ret; + int i; + + master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio)); + if (master == NULL) { + dev_err(&dev->dev, "failed to allocate spi master\n"); + ret = -ENOMEM; + goto err; + } + + sp = spi_master_get_devdata(master); + + platform_set_drvdata(dev, sp); + + /* copy in the plkatform data */ + sp->info = dev->dev.platform_data; + + /* setup spi bitbang adaptor */ + sp->bitbang.master = spi_master_get(master); + sp->bitbang.chipselect = s3c2410_spigpio_chipselect; + + sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0; + sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1; + + /* set state of spi pins */ + s3c2410_gpio_setpin(sp->info->pin_clk, 0); + s3c2410_gpio_setpin(sp->info->pin_mosi, 0); + + s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT); + + ret = spi_bitbang_start(&sp->bitbang); + if (ret) + goto err_no_bitbang; + + /* register the chips to go with the board */ + + for (i = 0; i < sp->info->board_size; i++) { + dev_info(&dev->dev, "registering %p: %s\n", + &sp->info->board_info[i], + sp->info->board_info[i].modalias); + + sp->info->board_info[i].controller_data = sp; + spi_new_device(master, sp->info->board_info + i); + } + + return 0; + + err_no_bitbang: + spi_master_put(sp->bitbang.master); + err: + return ret; + +} + +static int s3c2410_spigpio_remove(struct platform_device *dev) +{ + struct s3c2410_spigpio *sp = platform_get_drvdata(dev); + + spi_bitbang_stop(&sp->bitbang); + spi_master_put(sp->bitbang.master); + + return 0; +} + +/* all gpio should be held over suspend/resume, so we should + * not need to deal with this +*/ + +#define s3c2410_spigpio_suspend NULL +#define s3c2410_spigpio_resume NULL + + +static struct platform_driver s3c2410_spigpio_drv = { + .probe = s3c2410_spigpio_probe, + .remove = s3c2410_spigpio_remove, + .suspend = s3c2410_spigpio_suspend, + .resume = s3c2410_spigpio_resume, + .driver = { + .name = "s3c24xx-spi-gpio", + .owner = THIS_MODULE, + }, +}; + +static int __init s3c2410_spigpio_init(void) +{ + return platform_driver_register(&s3c2410_spigpio_drv); +} + +static void __exit s3c2410_spigpio_exit(void) +{ + platform_driver_unregister(&s3c2410_spigpio_drv); +} + +module_init(s3c2410_spigpio_init); +module_exit(s3c2410_spigpio_exit); + +MODULE_DESCRIPTION("S3C24XX SPI Driver"); +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 6dd666696178..c4670e1d4654 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -317,6 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun } schedule(); + set_current_state(TASK_INTERRUPTIBLE); } set_current_state(TASK_RUNNING); diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 788297e9d59e..44aa2ffff973 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -76,8 +76,8 @@ * * Experiment with v_offset to find out which works best for you. */ -static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */ -static u32 voffset __initdata = 0; +static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */ +static u32 voffset __devinitdata; static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor); static int __devinit i810fb_init_pci (struct pci_dev *dev, diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c index 8073a73f6f35..440272ad10e7 100644 --- a/drivers/video/matrox/g450_pll.c +++ b/drivers/video/matrox/g450_pll.c @@ -316,14 +316,24 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, case M_PIXEL_PLL_B: case M_PIXEL_PLL_C: { - u_int8_t tmp; + u_int8_t tmp, xpwrctrl; unsigned long flags; matroxfb_DAC_lock_irqsave(flags); + + xpwrctrl = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); + matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN); + mga_outb(M_SEQ_INDEX, M_SEQ1); + mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF); tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL); + tmp |= M1064_XPIXCLKCTRL_DIS; if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) { - matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp | M1064_XPIXCLKCTRL_PLL_UP); + tmp |= M1064_XPIXCLKCTRL_PLL_UP; } + matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp); + matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0); + matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl); + matroxfb_DAC_unlock_irqrestore(flags); } { @@ -418,6 +428,15 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, frequency to higher - with <= lowest wins, while with < highest one wins */ if (delta <= deltaarray[idx-1]) { + /* all else being equal except VCO, + * choose VCO not near (within 1/16th or so) VCOmin + * (freqs near VCOmin aren't as stable) + */ + if (delta == deltaarray[idx-1] + && vco != g450_mnp2vco(PMINFO mnparray[idx-1]) + && vco < (pi->vcomin * 17 / 16)) { + break; + } mnparray[idx] = mnparray[idx-1]; deltaarray[idx] = deltaarray[idx-1]; } else { diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h index 2e7238aa2432..56513a5d220b 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.h +++ b/drivers/video/matrox/matroxfb_DAC1064.h @@ -40,6 +40,7 @@ void DAC1064_global_restore(WPMINFO2); #define M1064_XCURCOL1RED 0x0C #define M1064_XCURCOL1GREEN 0x0D #define M1064_XCURCOL1BLUE 0x0E +#define M1064_XDVICLKCTRL 0x0F #define M1064_XCURCOL2RED 0x10 #define M1064_XCURCOL2GREEN 0x11 #define M1064_XCURCOL2BLUE 0x12 @@ -144,6 +145,7 @@ void DAC1064_global_restore(WPMINFO2); #define M1064_XVIDPLLN 0x8F #define M1064_XPWRCTRL 0xA0 +#define M1064_XPWRCTRL_PANELPDN 0x04 #define M1064_XPANMODE 0xA2 diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 3a3e1804c56a..b71737178d0d 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -672,6 +672,8 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv); #define M_SEQ_INDEX 0x1FC4 #define M_SEQ_DATA 0x1FC5 +#define M_SEQ1 0x01 +#define M_SEQ1_SCROFF 0x20 #define M_MISC_REG_READ 0x1FCC diff --git a/fs/Makefile b/fs/Makefile index 83bf478e786b..078d3d1191a5 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_DNOTIFY) += dnotify.o obj-$(CONFIG_PROC_FS) += proc/ obj-y += partitions/ obj-$(CONFIG_SYSFS) += sysfs/ +obj-$(CONFIG_CONFIGFS_FS) += configfs/ obj-y += devpts/ obj-$(CONFIG_PROFILING) += dcookies.o @@ -100,5 +101,4 @@ obj-$(CONFIG_BEFS_FS) += befs/ obj-$(CONFIG_HOSTFS) += hostfs/ obj-$(CONFIG_HPPFS) += hppfs/ obj-$(CONFIG_DEBUG_FS) += debugfs/ -obj-$(CONFIG_CONFIGFS_FS) += configfs/ obj-$(CONFIG_OCFS2_FS) += ocfs2/ diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 69f44dcdb0b4..b1c902e319c1 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -428,7 +428,6 @@ static int load_flat_file(struct linux_binprm * bprm, loff_t fpos; unsigned long start_code, end_code; int ret; - int exec_fileno; hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ inode = bprm->file->f_dentry->d_inode; @@ -502,21 +501,12 @@ static int load_flat_file(struct linux_binprm * bprm, goto err; } - /* check file descriptor */ - exec_fileno = get_unused_fd(); - if (exec_fileno < 0) { - ret = -EMFILE; - goto err; - } - get_file(bprm->file); - fd_install(exec_fileno, bprm->file); - /* Flush all traces of the currently running executable */ if (id == 0) { result = flush_old_exec(bprm); if (result) { ret = result; - goto err_close; + goto err; } /* OK, This is the point of no return */ @@ -548,7 +538,7 @@ static int load_flat_file(struct linux_binprm * bprm, textpos = (unsigned long) -ENOMEM; printk("Unable to mmap process text, errno %d\n", (int)-textpos); ret = textpos; - goto err_close; + goto err; } down_write(¤t->mm->mmap_sem); @@ -564,7 +554,7 @@ static int load_flat_file(struct linux_binprm * bprm, (int)-datapos); do_munmap(current->mm, textpos, text_len); ret = realdatastart; - goto err_close; + goto err; } datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); @@ -587,7 +577,7 @@ static int load_flat_file(struct linux_binprm * bprm, do_munmap(current->mm, textpos, text_len); do_munmap(current->mm, realdatastart, data_len + extra); ret = result; - goto err_close; + goto err; } reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); @@ -606,7 +596,7 @@ static int load_flat_file(struct linux_binprm * bprm, printk("Unable to allocate RAM for process text/data, errno %d\n", (int)-textpos); ret = textpos; - goto err_close; + goto err; } realdatastart = textpos + ntohl(hdr->data_start); @@ -652,7 +642,7 @@ static int load_flat_file(struct linux_binprm * bprm, do_munmap(current->mm, textpos, text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long)); ret = result; - goto err_close; + goto err; } } @@ -717,7 +707,7 @@ static int load_flat_file(struct linux_binprm * bprm, addr = calc_reloc(*rp, libinfo, id, 0); if (addr == RELOC_FAILED) { ret = -ENOEXEC; - goto err_close; + goto err; } *rp = addr; } @@ -747,7 +737,7 @@ static int load_flat_file(struct linux_binprm * bprm, rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); if (rp == (unsigned long *)RELOC_FAILED) { ret = -ENOEXEC; - goto err_close; + goto err; } /* Get the pointer's value. */ @@ -762,7 +752,7 @@ static int load_flat_file(struct linux_binprm * bprm, addr = calc_reloc(addr, libinfo, id, 0); if (addr == RELOC_FAILED) { ret = -ENOEXEC; - goto err_close; + goto err; } /* Write back the relocated pointer. */ @@ -783,8 +773,6 @@ static int load_flat_file(struct linux_binprm * bprm, stack_len); return 0; -err_close: - sys_close(exec_fileno); err: return ret; } diff --git a/fs/compat.c b/fs/compat.c index 01f39f87f372..b1f64786a613 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -2030,109 +2030,115 @@ union compat_nfsctl_res { struct knfsd_fh cr32_getfs; }; -static int compat_nfs_svc_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port); - err |= __get_user(karg->ca_svc.svc_nthreads, &arg->ca32_svc.svc32_nthreads); - return (err) ? -EFAULT : 0; +static int compat_nfs_svc_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) || + get_user(karg->ca_version, &arg->ca32_version) || + __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) || + __get_user(karg->ca_svc.svc_nthreads, + &arg->ca32_svc.svc32_nthreads)) + return -EFAULT; + return 0; } -static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_client, sizeof(arg->ca32_client)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_client.cl_ident[0], - &arg->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX); - err |= __get_user(karg->ca_client.cl_naddr, &arg->ca32_client.cl32_naddr); - err |= __copy_from_user(&karg->ca_client.cl_addrlist[0], - &arg->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); - err |= __get_user(karg->ca_client.cl_fhkeytype, - &arg->ca32_client.cl32_fhkeytype); - err |= __get_user(karg->ca_client.cl_fhkeylen, - &arg->ca32_client.cl32_fhkeylen); - err |= __copy_from_user(&karg->ca_client.cl_fhkey[0], - &arg->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX); +static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_client, + sizeof(arg->ca32_client)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_client.cl_ident[0], + &arg->ca32_client.cl32_ident[0], + NFSCLNT_IDMAX) || + __get_user(karg->ca_client.cl_naddr, + &arg->ca32_client.cl32_naddr) || + __copy_from_user(&karg->ca_client.cl_addrlist[0], + &arg->ca32_client.cl32_addrlist[0], + (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) || + __get_user(karg->ca_client.cl_fhkeytype, + &arg->ca32_client.cl32_fhkeytype) || + __get_user(karg->ca_client.cl_fhkeylen, + &arg->ca32_client.cl32_fhkeylen) || + __copy_from_user(&karg->ca_client.cl_fhkey[0], + &arg->ca32_client.cl32_fhkey[0], + NFSCLNT_KEYMAX)) + return -EFAULT; - return (err) ? -EFAULT : 0; + return 0; } -static int compat_nfs_exp_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_export, sizeof(arg->ca32_export)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_export.ex_client[0], - &arg->ca32_export.ex32_client[0], - NFSCLNT_IDMAX); - err |= __copy_from_user(&karg->ca_export.ex_path[0], - &arg->ca32_export.ex32_path[0], - NFS_MAXPATHLEN); - err |= __get_user(karg->ca_export.ex_dev, - &arg->ca32_export.ex32_dev); - err |= __get_user(karg->ca_export.ex_ino, - &arg->ca32_export.ex32_ino); - err |= __get_user(karg->ca_export.ex_flags, - &arg->ca32_export.ex32_flags); - err |= __get_user(karg->ca_export.ex_anon_uid, - &arg->ca32_export.ex32_anon_uid); - err |= __get_user(karg->ca_export.ex_anon_gid, - &arg->ca32_export.ex32_anon_gid); +static int compat_nfs_exp_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_export, + sizeof(arg->ca32_export)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_export.ex_client[0], + &arg->ca32_export.ex32_client[0], + NFSCLNT_IDMAX) || + __copy_from_user(&karg->ca_export.ex_path[0], + &arg->ca32_export.ex32_path[0], + NFS_MAXPATHLEN) || + __get_user(karg->ca_export.ex_dev, + &arg->ca32_export.ex32_dev) || + __get_user(karg->ca_export.ex_ino, + &arg->ca32_export.ex32_ino) || + __get_user(karg->ca_export.ex_flags, + &arg->ca32_export.ex32_flags) || + __get_user(karg->ca_export.ex_anon_uid, + &arg->ca32_export.ex32_anon_uid) || + __get_user(karg->ca_export.ex_anon_gid, + &arg->ca32_export.ex32_anon_gid)) + return -EFAULT; SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid); SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid); - return (err) ? -EFAULT : 0; + return 0; } -static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_getfd, sizeof(arg->ca32_getfd)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_getfd.gd_addr, - &arg->ca32_getfd.gd32_addr, - (sizeof(struct sockaddr))); - err |= __copy_from_user(&karg->ca_getfd.gd_path, - &arg->ca32_getfd.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfd.gd_version, - &arg->ca32_getfd.gd32_version); +static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_getfd, + sizeof(arg->ca32_getfd)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_getfd.gd_addr, + &arg->ca32_getfd.gd32_addr, + (sizeof(struct sockaddr))) || + __copy_from_user(&karg->ca_getfd.gd_path, + &arg->ca32_getfd.gd32_path, + (NFS_MAXPATHLEN+1)) || + __get_user(karg->ca_getfd.gd_version, + &arg->ca32_getfd.gd32_version)) + return -EFAULT; - return (err) ? -EFAULT : 0; + return 0; } -static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) +static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) { - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_getfs, sizeof(arg->ca32_getfs)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_getfs.gd_addr, - &arg->ca32_getfs.gd32_addr, - (sizeof(struct sockaddr))); - err |= __copy_from_user(&karg->ca_getfs.gd_path, - &arg->ca32_getfs.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfs.gd_maxlen, - &arg->ca32_getfs.gd32_maxlen); + if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_getfs.gd_addr, + &arg->ca32_getfs.gd32_addr, + (sizeof(struct sockaddr))) || + __copy_from_user(&karg->ca_getfs.gd_path, + &arg->ca32_getfs.gd32_path, + (NFS_MAXPATHLEN+1)) || + __get_user(karg->ca_getfs.gd_maxlen, + &arg->ca32_getfs.gd32_maxlen)) + return -EFAULT; - return (err) ? -EFAULT : 0; + return 0; } /* This really doesn't need translations, we are only passing * back a union which contains opaque nfs file handle data. */ -static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsctl_res __user *res) +static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, + union compat_nfsctl_res __user *res) { int err; @@ -2141,8 +2147,9 @@ static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsct return (err) ? -EFAULT : 0; } -asmlinkage long compat_sys_nfsservctl(int cmd, struct compat_nfsctl_arg __user *arg, - union compat_nfsctl_res __user *res) +asmlinkage long compat_sys_nfsservctl(int cmd, + struct compat_nfsctl_arg __user *arg, + union compat_nfsctl_res __user *res) { struct nfsctl_arg *karg; union nfsctl_res *kres; diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 5638c8f9362f..5f952187fc53 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -505,13 +505,15 @@ static int populate_groups(struct config_group *group) int i; if (group->default_groups) { - /* FYI, we're faking mkdir here + /* + * FYI, we're faking mkdir here * I'm not sure we need this semaphore, as we're called * from our parent's mkdir. That holds our parent's * i_mutex, so afaik lookup cannot continue through our * parent to find us, let alone mess with our tree. * That said, taking our i_mutex is closer to mkdir - * emulation, and shouldn't hurt. */ + * emulation, and shouldn't hurt. + */ mutex_lock(&dentry->d_inode->i_mutex); for (i = 0; group->default_groups[i]; i++) { @@ -546,20 +548,34 @@ static void unlink_obj(struct config_item *item) item->ci_group = NULL; item->ci_parent = NULL; + + /* Drop the reference for ci_entry */ config_item_put(item); + /* Drop the reference for ci_parent */ config_group_put(group); } } static void link_obj(struct config_item *parent_item, struct config_item *item) { - /* Parent seems redundant with group, but it makes certain - * traversals much nicer. */ + /* + * Parent seems redundant with group, but it makes certain + * traversals much nicer. + */ item->ci_parent = parent_item; + + /* + * We hold a reference on the parent for the child's ci_parent + * link. + */ item->ci_group = config_group_get(to_config_group(parent_item)); list_add_tail(&item->ci_entry, &item->ci_group->cg_children); + /* + * We hold a reference on the child for ci_entry on the parent's + * cg_children + */ config_item_get(item); } @@ -684,6 +700,10 @@ static void client_drop_item(struct config_item *parent_item, type = parent_item->ci_type; BUG_ON(!type); + /* + * If ->drop_item() exists, it is responsible for the + * config_item_put(). + */ if (type->ct_group_ops && type->ct_group_ops->drop_item) type->ct_group_ops->drop_item(to_config_group(parent_item), item); @@ -694,23 +714,28 @@ static void client_drop_item(struct config_item *parent_item, static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { - int ret; + int ret, module_got = 0; struct config_group *group; struct config_item *item; struct config_item *parent_item; struct configfs_subsystem *subsys; struct configfs_dirent *sd; struct config_item_type *type; - struct module *owner; + struct module *owner = NULL; char *name; - if (dentry->d_parent == configfs_sb->s_root) - return -EPERM; + if (dentry->d_parent == configfs_sb->s_root) { + ret = -EPERM; + goto out; + } sd = dentry->d_parent->d_fsdata; - if (!(sd->s_type & CONFIGFS_USET_DIR)) - return -EPERM; + if (!(sd->s_type & CONFIGFS_USET_DIR)) { + ret = -EPERM; + goto out; + } + /* Get a working ref for the duration of this function */ parent_item = configfs_get_config_item(dentry->d_parent); type = parent_item->ci_type; subsys = to_config_group(parent_item)->cg_subsys; @@ -719,15 +744,16 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) if (!type || !type->ct_group_ops || (!type->ct_group_ops->make_group && !type->ct_group_ops->make_item)) { - config_item_put(parent_item); - return -EPERM; /* What lack-of-mkdir returns */ + ret = -EPERM; /* Lack-of-mkdir returns -EPERM */ + goto out_put; } name = kmalloc(dentry->d_name.len + 1, GFP_KERNEL); if (!name) { - config_item_put(parent_item); - return -ENOMEM; + ret = -ENOMEM; + goto out_put; } + snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name); down(&subsys->su_sem); @@ -748,40 +774,67 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) kfree(name); if (!item) { - config_item_put(parent_item); - return -ENOMEM; + /* + * If item == NULL, then link_obj() was never called. + * There are no extra references to clean up. + */ + ret = -ENOMEM; + goto out_put; } - ret = -EINVAL; + /* + * link_obj() has been called (via link_group() for groups). + * From here on out, errors must clean that up. + */ + type = item->ci_type; - if (type) { - owner = type->ct_owner; - if (try_module_get(owner)) { - if (group) { - ret = configfs_attach_group(parent_item, - item, - dentry); - } else { - ret = configfs_attach_item(parent_item, - item, - dentry); - } + if (!type) { + ret = -EINVAL; + goto out_unlink; + } - if (ret) { - down(&subsys->su_sem); - if (group) - unlink_group(group); - else - unlink_obj(item); - client_drop_item(parent_item, item); - up(&subsys->su_sem); + owner = type->ct_owner; + if (!try_module_get(owner)) { + ret = -EINVAL; + goto out_unlink; + } - config_item_put(parent_item); - module_put(owner); - } - } + /* + * I hate doing it this way, but if there is + * an error, module_put() probably should + * happen after any cleanup. + */ + module_got = 1; + + if (group) + ret = configfs_attach_group(parent_item, item, dentry); + else + ret = configfs_attach_item(parent_item, item, dentry); + +out_unlink: + if (ret) { + /* Tear down everything we built up */ + down(&subsys->su_sem); + if (group) + unlink_group(group); + else + unlink_obj(item); + client_drop_item(parent_item, item); + up(&subsys->su_sem); + + if (module_got) + module_put(owner); } +out_put: + /* + * link_obj()/link_group() took a reference from child->parent, + * so the parent is safely pinned. We can drop our working + * reference. + */ + config_item_put(parent_item); + +out: return ret; } @@ -801,6 +854,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) if (sd->s_type & CONFIGFS_USET_DEFAULT) return -EPERM; + /* Get a working ref until we have the child */ parent_item = configfs_get_config_item(dentry->d_parent); subsys = to_config_group(parent_item)->cg_subsys; BUG_ON(!subsys); @@ -817,6 +871,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) return ret; } + /* Get a working ref for the duration of this function */ item = configfs_get_config_item(dentry); /* Drop reference from above, item already holds one. */ diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index b06b54f1bbbb..4c39009350f3 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -102,7 +102,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, if (acceptable(context, result)) return result; if (S_ISDIR(result->d_inode->i_mode)) { - /* there is no other dentry, so fail */ + err = -EACCES; goto err_result; } diff --git a/fs/inotify.c b/fs/inotify.c index 1f50302849c5..732ec4bd5774 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -848,7 +848,11 @@ static int inotify_release(struct inode *ignored, struct file *file) inode = watch->inode; mutex_lock(&inode->inotify_mutex); mutex_lock(&dev->mutex); - remove_watch_no_event(watch, dev); + + /* make sure we didn't race with another list removal */ + if (likely(idr_find(&dev->idr, watch->wd))) + remove_watch_no_event(watch, dev); + mutex_unlock(&dev->mutex); mutex_unlock(&inode->inotify_mutex); put_inotify_watch(watch); @@ -890,8 +894,7 @@ static int inotify_ignore(struct inotify_device *dev, s32 wd) mutex_lock(&dev->mutex); /* make sure that we did not race */ - watch = idr_find(&dev->idr, wd); - if (likely(watch)) + if (likely(idr_find(&dev->idr, wd) == watch)) remove_watch(watch, dev); mutex_unlock(&dev->mutex); diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6aa92d0e6876..1d65f13f458c 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1922,11 +1922,10 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl) value = kmalloc(size, GFP_KERNEL); if (!value) return -ENOMEM; - size = posix_acl_to_xattr(acl, value, size); - if (size < 0) { - error = size; + error = posix_acl_to_xattr(acl, value, size); + if (error < 0) goto getout; - } + size = error; } else size = 0; diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 0d858d0b25be..47152bf9a7f2 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -276,13 +276,29 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) return ret; } +/* This can also be called from ocfs2_write_zero_page() which has done + * it's own cluster locking. */ +int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page, + unsigned from, unsigned to) +{ + int ret; + + down_read(&OCFS2_I(inode)->ip_alloc_sem); + + ret = block_prepare_write(page, from, to, ocfs2_get_block); + + up_read(&OCFS2_I(inode)->ip_alloc_sem); + + return ret; +} + /* * ocfs2_prepare_write() can be an outer-most ocfs2 call when it is called * from loopback. It must be able to perform its own locking around * ocfs2_get_block(). */ -int ocfs2_prepare_write(struct file *file, struct page *page, - unsigned from, unsigned to) +static int ocfs2_prepare_write(struct file *file, struct page *page, + unsigned from, unsigned to) { struct inode *inode = page->mapping->host; int ret; @@ -295,11 +311,7 @@ int ocfs2_prepare_write(struct file *file, struct page *page, goto out; } - down_read(&OCFS2_I(inode)->ip_alloc_sem); - - ret = block_prepare_write(page, from, to, ocfs2_get_block); - - up_read(&OCFS2_I(inode)->ip_alloc_sem); + ret = ocfs2_prepare_write_nolock(inode, page, from, to); ocfs2_meta_unlock(inode, 0); out: @@ -625,11 +637,31 @@ static ssize_t ocfs2_direct_IO(int rw, int ret; mlog_entry_void(); + + /* + * We get PR data locks even for O_DIRECT. This allows + * concurrent O_DIRECT I/O but doesn't let O_DIRECT with + * extending and buffered zeroing writes race. If they did + * race then the buffered zeroing could be written back after + * the O_DIRECT I/O. It's one thing to tell people not to mix + * buffered and O_DIRECT writes, but expecting them to + * understand that file extension is also an implicit buffered + * write is too much. By getting the PR we force writeback of + * the buffered zeroing before proceeding. + */ + ret = ocfs2_data_lock(inode, 0); + if (ret < 0) { + mlog_errno(ret); + goto out; + } + ocfs2_data_unlock(inode, 0); + ret = blockdev_direct_IO_no_locking(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, ocfs2_direct_IO_get_blocks, ocfs2_dio_end_io); +out: mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index d40456d509a0..e88c3f0b8fa9 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h @@ -22,8 +22,8 @@ #ifndef OCFS2_AOPS_H #define OCFS2_AOPS_H -int ocfs2_prepare_write(struct file *file, struct page *page, - unsigned from, unsigned to); +int ocfs2_prepare_write_nolock(struct inode *inode, struct page *page, + unsigned from, unsigned to); struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode, struct page *page, diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 4601fc256f11..1a5c69071df6 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -569,7 +569,7 @@ static int ocfs2_extent_map_insert(struct inode *inode, ret = -ENOMEM; ctxt.new_ent = kmem_cache_alloc(ocfs2_em_ent_cachep, - GFP_KERNEL); + GFP_NOFS); if (!ctxt.new_ent) { mlog_errno(ret); return ret; @@ -583,14 +583,14 @@ static int ocfs2_extent_map_insert(struct inode *inode, if (ctxt.need_left && !ctxt.left_ent) { ctxt.left_ent = kmem_cache_alloc(ocfs2_em_ent_cachep, - GFP_KERNEL); + GFP_NOFS); if (!ctxt.left_ent) break; } if (ctxt.need_right && !ctxt.right_ent) { ctxt.right_ent = kmem_cache_alloc(ocfs2_em_ent_cachep, - GFP_KERNEL); + GFP_NOFS); if (!ctxt.right_ent) break; } diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 581eb451a41a..a9559c874530 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -613,7 +613,8 @@ leave: /* Some parts of this taken from generic_cont_expand, which turned out * to be too fragile to do exactly what we need without us having to - * worry about recursive locking in ->commit_write(). */ + * worry about recursive locking in ->prepare_write() and + * ->commit_write(). */ static int ocfs2_write_zero_page(struct inode *inode, u64 size) { @@ -641,7 +642,7 @@ static int ocfs2_write_zero_page(struct inode *inode, goto out; } - ret = ocfs2_prepare_write(NULL, page, offset, offset); + ret = ocfs2_prepare_write_nolock(inode, page, offset, offset); if (ret < 0) { mlog_errno(ret); goto out_unlock; @@ -695,13 +696,26 @@ out: return ret; } +/* + * A tail_to_skip value > 0 indicates that we're being called from + * ocfs2_file_aio_write(). This has the following implications: + * + * - we don't want to update i_size + * - di_bh will be NULL, which is fine because it's only used in the + * case where we want to update i_size. + * - ocfs2_zero_extend() will then only be filling the hole created + * between i_size and the start of the write. + */ static int ocfs2_extend_file(struct inode *inode, struct buffer_head *di_bh, - u64 new_i_size) + u64 new_i_size, + size_t tail_to_skip) { int ret = 0; u32 clusters_to_add; + BUG_ON(!tail_to_skip && !di_bh); + /* setattr sometimes calls us like this. */ if (new_i_size == 0) goto out; @@ -714,27 +728,44 @@ static int ocfs2_extend_file(struct inode *inode, OCFS2_I(inode)->ip_clusters; if (clusters_to_add) { - ret = ocfs2_extend_allocation(inode, clusters_to_add); + /* + * protect the pages that ocfs2_zero_extend is going to + * be pulling into the page cache.. we do this before the + * metadata extend so that we don't get into the situation + * where we've extended the metadata but can't get the data + * lock to zero. + */ + ret = ocfs2_data_lock(inode, 1); if (ret < 0) { mlog_errno(ret); goto out; } - ret = ocfs2_zero_extend(inode, new_i_size); + ret = ocfs2_extend_allocation(inode, clusters_to_add); if (ret < 0) { mlog_errno(ret); - goto out; + goto out_unlock; } - } - /* No allocation required, we just use this helper to - * do a trivial update of i_size. */ - ret = ocfs2_simple_size_update(inode, di_bh, new_i_size); - if (ret < 0) { - mlog_errno(ret); - goto out; + ret = ocfs2_zero_extend(inode, (u64)new_i_size - tail_to_skip); + if (ret < 0) { + mlog_errno(ret); + goto out_unlock; + } + } + + if (!tail_to_skip) { + /* We're being called from ocfs2_setattr() which wants + * us to update i_size */ + ret = ocfs2_simple_size_update(inode, di_bh, new_i_size); + if (ret < 0) + mlog_errno(ret); } +out_unlock: + if (clusters_to_add) /* this is the only case in which we lock */ + ocfs2_data_unlock(inode, 1); + out: return ret; } @@ -793,7 +824,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) if (i_size_read(inode) > attr->ia_size) status = ocfs2_truncate_file(inode, bh, attr->ia_size); else - status = ocfs2_extend_file(inode, bh, attr->ia_size); + status = ocfs2_extend_file(inode, bh, attr->ia_size, 0); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); @@ -1049,21 +1080,12 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, if (!clusters) break; - ret = ocfs2_extend_allocation(inode, clusters); + ret = ocfs2_extend_file(inode, NULL, newsize, count); if (ret < 0) { if (ret != -ENOSPC) mlog_errno(ret); goto out; } - - /* Fill any holes which would've been created by this - * write. If we're O_APPEND, this will wind up - * (correctly) being a noop. */ - ret = ocfs2_zero_extend(inode, (u64) newsize - count); - if (ret < 0) { - mlog_errno(ret); - goto out; - } break; } @@ -1146,6 +1168,22 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, ocfs2_iocb_set_rw_locked(iocb); } + /* + * We're fine letting folks race truncates and extending + * writes with read across the cluster, just like they can + * locally. Hence no rw_lock during read. + * + * Take and drop the meta data lock to update inode fields + * like i_size. This allows the checks down below + * generic_file_aio_read() a chance of actually working. + */ + ret = ocfs2_meta_lock(inode, NULL, NULL, 0); + if (ret < 0) { + mlog_errno(ret); + goto bail; + } + ocfs2_meta_unlock(inode, 0); + ret = generic_file_aio_read(iocb, buf, count, iocb->ki_pos); if (ret == -EINVAL) mlog(ML_ERROR, "generic_file_aio_read returned -EINVAL\n"); diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 6a610ae53583..eebc3cfa6be8 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -117,7 +117,7 @@ struct ocfs2_journal_handle *ocfs2_alloc_handle(struct ocfs2_super *osb) { struct ocfs2_journal_handle *retval = NULL; - retval = kcalloc(1, sizeof(*retval), GFP_KERNEL); + retval = kcalloc(1, sizeof(*retval), GFP_NOFS); if (!retval) { mlog(ML_ERROR, "Failed to allocate memory for journal " "handle!\n"); @@ -870,9 +870,11 @@ static int ocfs2_force_read_journal(struct inode *inode) if (p_blocks > CONCURRENT_JOURNAL_FILL) p_blocks = CONCURRENT_JOURNAL_FILL; + /* We are reading journal data which should not + * be put in the uptodate cache */ status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb), p_blkno, p_blocks, bhs, 0, - inode); + NULL); if (status < 0) { mlog_errno(status); goto bail; @@ -982,7 +984,7 @@ static void ocfs2_queue_recovery_completion(struct ocfs2_journal *journal, { struct ocfs2_la_recovery_item *item; - item = kmalloc(sizeof(struct ocfs2_la_recovery_item), GFP_KERNEL); + item = kmalloc(sizeof(struct ocfs2_la_recovery_item), GFP_NOFS); if (!item) { /* Though we wish to avoid it, we are in fact safe in * skipping local alloc cleanup as fsck.ocfs2 is more diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index 04a684dfdd96..b8a00a793326 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c @@ -337,7 +337,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, (unsigned long long)oi->ip_blkno, (unsigned long long)block, expand_tree); - new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_KERNEL); + new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS); if (!new) { mlog_errno(-ENOMEM); return; @@ -349,7 +349,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, * has no way of tracking that. */ for(i = 0; i < OCFS2_INODE_MAX_CACHE_ARRAY; i++) { tree[i] = kmem_cache_alloc(ocfs2_uptodate_cachep, - GFP_KERNEL); + GFP_NOFS); if (!tree[i]) { mlog_errno(-ENOMEM); goto out_free; diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c index 53049a204197..ee42765a8553 100644 --- a/fs/ocfs2/vote.c +++ b/fs/ocfs2/vote.c @@ -586,7 +586,7 @@ static struct ocfs2_net_wait_ctxt *ocfs2_new_net_wait_ctxt(unsigned int response { struct ocfs2_net_wait_ctxt *w; - w = kcalloc(1, sizeof(*w), GFP_KERNEL); + w = kcalloc(1, sizeof(*w), GFP_NOFS); if (!w) { mlog_errno(-ENOMEM); goto bail; @@ -749,7 +749,7 @@ static struct ocfs2_vote_msg * ocfs2_new_vote_request(struct ocfs2_super *osb, BUG_ON(!ocfs2_is_valid_vote_request(type)); - request = kcalloc(1, sizeof(*request), GFP_KERNEL); + request = kcalloc(1, sizeof(*request), GFP_NOFS); if (!request) { mlog_errno(-ENOMEM); } else { @@ -1129,7 +1129,7 @@ static int ocfs2_handle_vote_message(struct o2net_msg *msg, struct ocfs2_super *osb = data; struct ocfs2_vote_work *work; - work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_KERNEL); + work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_NOFS); if (!work) { status = -ENOMEM; mlog_errno(status); diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h index 1e70908b816f..915590c391c8 100644 --- a/include/asm-arm/arch-pxa/pxa2xx_spi.h +++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h @@ -27,13 +27,16 @@ #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00) #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) +#define SSP_TIMEOUT_SCALE (2712) #elif defined(CONFIG_PXA27x) #define CLOCK_SPEED_HZ 13000000 #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) +#define SSP_TIMEOUT_SCALE (769) #endif +#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE) #define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1))))) #define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2))))) #define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3))))) diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h new file mode 100644 index 000000000000..258c00bca270 --- /dev/null +++ b/include/asm-arm/arch-s3c2410/spi-gpio.h @@ -0,0 +1,31 @@ +/* linux/include/asm-arm/arch-s3c2410/spi.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2410 - SPI Controller platfrom_device info + * + * 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. +*/ + +#ifndef __ASM_ARCH_SPIGPIO_H +#define __ASM_ARCH_SPIGPIO_H __FILE__ + +struct s3c2410_spigpio_info; +struct spi_board_info; + +struct s3c2410_spigpio_info { + unsigned long pin_clk; + unsigned long pin_mosi; + unsigned long pin_miso; + + unsigned long board_size; + struct spi_board_info *board_info; + + void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs); +}; + + +#endif /* __ASM_ARCH_SPIGPIO_H */ diff --git a/include/asm-arm/arch-s3c2410/spi.h b/include/asm-arm/arch-s3c2410/spi.h new file mode 100644 index 000000000000..4029a1a1ab40 --- /dev/null +++ b/include/asm-arm/arch-s3c2410/spi.h @@ -0,0 +1,29 @@ +/* linux/include/asm-arm/arch-s3c2410/spi.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2410 - SPI Controller platform_device info + * + * 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. +*/ + +#ifndef __ASM_ARCH_SPI_H +#define __ASM_ARCH_SPI_H __FILE__ + +struct s3c2410_spi_info; +struct spi_board_info; + +struct s3c2410_spi_info { + unsigned long pin_cs; /* simple gpio cs */ + + unsigned long board_size; + struct spi_board_info *board_info; + + void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol); +}; + + +#endif /* __ASM_ARCH_SPI_H */ diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h index 43ad4e55878c..406ca97a8ab2 100644 --- a/include/asm-arm/spinlock.h +++ b/include/asm-arm/spinlock.h @@ -142,6 +142,9 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) : "cc"); } +/* write_can_lock - would write_trylock() succeed? */ +#define __raw_write_can_lock(x) ((x)->lock == 0x80000000) + /* * Read locks are a bit more hairy: * - Exclusively load the lock value. @@ -198,4 +201,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw) #define __raw_read_trylock(lock) generic__raw_read_trylock(lock) +/* read_can_lock - would read_trylock() succeed? */ +#define __raw_read_can_lock(x) ((x)->lock < 0x80000000) + #endif /* __ASM_SPINLOCK_H */ diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index f5611a721fbd..45a576507785 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -316,11 +316,13 @@ #define __NR_pselect6 297 #define __NR_ppoll 298 #define __NR_unshare 299 +#define __NR_set_robust_list 300 +#define __NR_get_robust_list 301 -/* WARNING: You MAY NOT add syscall numbers larger than 299, since +/* WARNING: You MAY NOT add syscall numbers larger than 301, since * all of the syscall tables in the Sparc kernel are - * sized to have 299 entries (starting at zero). Therefore - * find a free slot in the 0-299 range. + * sized to have 301 entries (starting at zero). Therefore + * find a free slot in the 0-301 range. */ #define _syscall0(type,name) \ diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index 68705748bec0..998ef4ab0e06 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -318,11 +318,13 @@ #define __NR_pselect6 297 #define __NR_ppoll 298 #define __NR_unshare 299 +#define __NR_set_robust_list 300 +#define __NR_get_robust_list 301 -/* WARNING: You MAY NOT add syscall numbers larger than 299, since +/* WARNING: You MAY NOT add syscall numbers larger than 301, since * all of the syscall tables in the Sparc kernel are - * sized to have 299 entries (starting at zero). Therefore - * find a free slot in the 0-299 range. + * sized to have 301 entries (starting at zero). Therefore + * find a free slot in the 0-301 range. */ #define _syscall0(type,name) \ diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 2d716080be4a..33d8f2087b6e 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -19,5 +19,4 @@ int request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context)); void release_firmware(const struct firmware *fw); -void register_firmware(const char *name, const u8 *data, size_t size); #endif diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index a3a0e078f79d..16fbe59edeb1 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -110,5 +110,16 @@ struct fsl_usb2_platform_data { #define FSL_USB2_PORT0_ENABLED 0x00000001 #define FSL_USB2_PORT1_ENABLED 0x00000002 +struct fsl_spi_platform_data { + u32 initial_spmode; /* initial SPMODE value */ + u16 bus_num; + + /* board specific information */ + u16 max_chipselect; + void (*activate_cs)(u8 cs, u8 polarity); + void (*deactivate_cs)(u8 cs, u8 polarity); + u32 sysclk; +}; + #endif /* _FSL_DEVICE_H_ */ #endif /* __KERNEL__ */ diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index bdc556d88498..03a14a30c46a 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -69,6 +69,7 @@ struct mmc_data { unsigned int timeout_ns; /* data timeout (in ns, max 80ms) */ unsigned int timeout_clks; /* data timeout (in clocks) */ unsigned int blksz_bits; /* data block size */ + unsigned int blksz; /* data block size */ unsigned int blocks; /* number of blocks */ unsigned int error; /* data error */ unsigned int flags; diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b5c21122c299..36740354d4db 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -22,6 +22,7 @@ #else #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER #endif +#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1)) struct free_area { struct list_head free_list; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index d7670ec1ec1e..ad7fa9c86c10 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1141,8 +1141,13 @@ extern char *v4l2_type_names[]; /* Compatibility layer interface -- v4l1-compat module */ typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, unsigned int cmd, void *arg); + +#ifdef CONFIG_VIDEO_V4L1_COMPAT int v4l_compat_translate_ioctl(struct inode *inode, struct file *file, int cmd, void *arg, v4l2_kioctl driver_ioctl); +#else +#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL +#endif /* 32 Bits compatibility layer for 64 bits processors */ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 34a1a09e5aef..807d6f1ef4b5 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -99,6 +99,7 @@ typedef enum { SCTP_CMD_DEL_NON_PRIMARY, /* Removes non-primary peer transports. */ SCTP_CMD_T3_RTX_TIMERS_STOP, /* Stops T3-rtx pending timers */ SCTP_CMD_FORCE_PRIM_RETRAN, /* Forces retrans. over primary path. */ + SCTP_CMD_SET_SK_ERR, /* Set sk_err */ SCTP_CMD_LAST } sctp_verb_t; diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index e673b2c984e9..aa6033ca7cd8 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -461,12 +461,12 @@ static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu) * there is room for a param header too. */ #define sctp_walk_params(pos, chunk, member)\ -_sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)), member) +_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) #define _sctp_walk_params(pos, chunk, end, member)\ for (pos.v = chunk->member;\ pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\ - pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)) &&\ + pos.v <= (void *)chunk + end - ntohs(pos.p->length) &&\ ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\ pos.v += WORD_ROUND(ntohs(pos.p->length))) @@ -477,7 +477,7 @@ _sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ sizeof(sctp_chunkhdr_t));\ (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\ - (void *)err <= (void *)chunk_hdr + end - WORD_ROUND(ntohs(err->length)) &&\ + (void *)err <= (void *)chunk_hdr + end - ntohs(err->length) &&\ ntohs(err->length) >= sizeof(sctp_errhdr_t); \ err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length)))) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 72248d1b9e3f..ab81fdd4572b 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2231,19 +2231,25 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs) * So only GFP_KERNEL allocations, if all nodes in the cpuset are * short of memory, might require taking the callback_mutex mutex. * - * The first loop over the zonelist in mm/page_alloc.c:__alloc_pages() - * calls here with __GFP_HARDWALL always set in gfp_mask, enforcing - * hardwall cpusets - no allocation on a node outside the cpuset is - * allowed (unless in interrupt, of course). - * - * The second loop doesn't even call here for GFP_ATOMIC requests - * (if the __alloc_pages() local variable 'wait' is set). That check - * and the checks below have the combined affect in the second loop of - * the __alloc_pages() routine that: + * The first call here from mm/page_alloc:get_page_from_freelist() + * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets, so + * no allocation on a node outside the cpuset is allowed (unless in + * interrupt, of course). + * + * The second pass through get_page_from_freelist() doesn't even call + * here for GFP_ATOMIC calls. For those calls, the __alloc_pages() + * variable 'wait' is not set, and the bit ALLOC_CPUSET is not set + * in alloc_flags. That logic and the checks below have the combined + * affect that: * in_interrupt - any node ok (current task context irrelevant) * GFP_ATOMIC - any node ok * GFP_KERNEL - any node in enclosing mem_exclusive cpuset ok * GFP_USER - only nodes in current tasks mems allowed ok. + * + * Rule: + * Don't call cpuset_zone_allowed() if you can't sleep, unless you + * pass in the __GFP_HARDWALL flag set in gfp_flag, which disables + * the code that might scan up ancestor cpusets and sleep. **/ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) @@ -2255,6 +2261,7 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) if (in_interrupt()) return 1; node = z->zone_pgdat->node_id; + might_sleep_if(!(gfp_mask & __GFP_HARDWALL)); if (node_isset(node, current->mems_allowed)) return 1; if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */ diff --git a/kernel/sched.c b/kernel/sched.c index 4c64f85698ae..c13f1bd2df7d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -665,55 +665,13 @@ static int effective_prio(task_t *p) } /* - * We place interactive tasks back into the active array, if possible. - * - * To guarantee that this does not starve expired tasks we ignore the - * interactivity of a task if the first expired task had to wait more - * than a 'reasonable' amount of time. This deadline timeout is - * load-dependent, as the frequency of array switched decreases with - * increasing number of running tasks. We also ignore the interactivity - * if a better static_prio task has expired, and switch periodically - * regardless, to ensure that highly interactive tasks do not starve - * the less fortunate for unreasonably long periods. - */ -static inline int expired_starving(runqueue_t *rq) -{ - int limit; - - /* - * Arrays were recently switched, all is well - */ - if (!rq->expired_timestamp) - return 0; - - limit = STARVATION_LIMIT * rq->nr_running; - - /* - * It's time to switch arrays - */ - if (jiffies - rq->expired_timestamp >= limit) - return 1; - - /* - * There's a better selection in the expired array - */ - if (rq->curr->static_prio > rq->best_expired_prio) - return 1; - - /* - * All is well - */ - return 0; -} - -/* * __activate_task - move a task to the runqueue. */ static void __activate_task(task_t *p, runqueue_t *rq) { prio_array_t *target = rq->active; - if (unlikely(batch_task(p) || (expired_starving(rq) && !rt_task(p)))) + if (batch_task(p)) target = rq->expired; enqueue_task(p, target); rq->nr_running++; @@ -2532,6 +2490,22 @@ unsigned long long current_sched_time(const task_t *tsk) } /* + * We place interactive tasks back into the active array, if possible. + * + * To guarantee that this does not starve expired tasks we ignore the + * interactivity of a task if the first expired task had to wait more + * than a 'reasonable' amount of time. This deadline timeout is + * load-dependent, as the frequency of array switched decreases with + * increasing number of running tasks. We also ignore the interactivity + * if a better static_prio task has expired: + */ +#define EXPIRED_STARVING(rq) \ + ((STARVATION_LIMIT && ((rq)->expired_timestamp && \ + (jiffies - (rq)->expired_timestamp >= \ + STARVATION_LIMIT * ((rq)->nr_running) + 1))) || \ + ((rq)->curr->static_prio > (rq)->best_expired_prio)) + +/* * Account user cpu time to a process. * @p: the process that the cpu time gets accounted to * @hardirq_offset: the offset to subtract from hardirq_count() @@ -2666,7 +2640,7 @@ void scheduler_tick(void) if (!rq->expired_timestamp) rq->expired_timestamp = jiffies; - if (!TASK_INTERACTIVE(p) || expired_starving(rq)) { + if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) { enqueue_task(p, rq->expired); if (p->static_prio < rq->best_expired_prio) rq->best_expired_prio = p->static_prio; diff --git a/kernel/timer.c b/kernel/timer.c index 67eaf0f54096..9e49deed468c 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -541,6 +541,22 @@ found: } spin_unlock(&base->lock); + /* + * It can happen that other CPUs service timer IRQs and increment + * jiffies, but we have not yet got a local timer tick to process + * the timer wheels. In that case, the expiry time can be before + * jiffies, but since the high-resolution timer here is relative to + * jiffies, the default expression when high-resolution timers are + * not active, + * + * time_before(MAX_JIFFY_OFFSET + jiffies, expires) + * + * would falsely evaluate to true. If that is the case, just + * return jiffies so that we can immediately fire the local timer + */ + if (time_before(expires, jiffies)) + return jiffies; + if (time_before(hr_expires, expires)) return hr_expires; diff --git a/lib/kobject.c b/lib/kobject.c index b46350c27837..687ab418d292 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -198,14 +198,14 @@ int kobject_add(struct kobject * kobj) /* be noisy on error issues */ if (error == -EEXIST) - printk("kobject_add failed for %s with -EEXIST, " + pr_debug("kobject_add failed for %s with -EEXIST, " "don't try to register things with the " "same name in the same directory.\n", kobject_name(kobj)); else - printk("kobject_add failed for %s (%d)\n", + pr_debug("kobject_add failed for %s (%d)\n", kobject_name(kobj), error); - dump_stack(); + /* dump_stack(); */ } return error; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 813b4ec1298a..253a450c400d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -951,7 +951,7 @@ restart: goto got_pg; do { - if (cpuset_zone_allowed(*z, gfp_mask)) + if (cpuset_zone_allowed(*z, gfp_mask|__GFP_HARDWALL)) wakeup_kswapd(*z, order); } while (*(++z)); @@ -970,7 +970,8 @@ restart: alloc_flags |= ALLOC_HARDER; if (gfp_mask & __GFP_HIGH) alloc_flags |= ALLOC_HIGH; - alloc_flags |= ALLOC_CPUSET; + if (wait) + alloc_flags |= ALLOC_CPUSET; /* * Go through the zonelist again. Let __GFP_HIGH and allocations @@ -2124,14 +2125,22 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat) #ifdef CONFIG_FLAT_NODE_MEM_MAP /* ia64 gets its own node_mem_map, before this, without bootmem */ if (!pgdat->node_mem_map) { - unsigned long size; + unsigned long size, start, end; struct page *map; - size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); + /* + * The zone's endpoints aren't required to be MAX_ORDER + * aligned but the node_mem_map endpoints must be in order + * for the buddy allocator to function correctly. + */ + start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1); + end = pgdat->node_start_pfn + pgdat->node_spanned_pages; + end = ALIGN(end, MAX_ORDER_NR_PAGES); + size = (end - start) * sizeof(struct page); map = alloc_remap(pgdat->node_id, size); if (!map) map = alloc_bootmem_node(pgdat, size); - pgdat->node_mem_map = map; + pgdat->node_mem_map = map + (pgdat->node_start_pfn - start); } #ifdef CONFIG_FLATMEM /* diff --git a/mm/sparse.c b/mm/sparse.c index c5e89eb9ac8f..100040c0dfb6 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -87,11 +87,8 @@ int __section_nr(struct mem_section* ms) unsigned long root_nr; struct mem_section* root; - for (root_nr = 0; - root_nr < NR_MEM_SECTIONS; - root_nr += SECTIONS_PER_ROOT) { - root = __nr_to_section(root_nr); - + for (root_nr = 0; root_nr < NR_SECTION_ROOTS; root_nr++) { + root = __nr_to_section(root_nr * SECTIONS_PER_ROOT); if (!root) continue; diff --git a/net/802/tr.c b/net/802/tr.c index afd8385c0c9c..e9dc803f2fe0 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -643,6 +643,5 @@ static int __init rif_init(void) module_init(rif_init); -EXPORT_SYMBOL(tr_source_route); EXPORT_SYMBOL(tr_type_trans); EXPORT_SYMBOL(alloc_trdev); diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index d159c92cca84..466ed3440b74 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -168,7 +168,7 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, if (info->bitmask & EBT_LOG_NFLOG) nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, - info->prefix); + "%s", info->prefix); else ebt_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, info->prefix); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index c2d92f99a2b8..d0d19192026d 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -948,7 +948,7 @@ static int do_add_counters(void __user *user, unsigned int len) write_lock_bh(&t->lock); private = t->private; - if (private->number != paddc->num_counters) { + if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; } diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c index 6c4899d8046a..96ceabaec402 100644 --- a/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c @@ -49,15 +49,15 @@ gre_in_range(const struct ip_conntrack_tuple *tuple, const union ip_conntrack_manip_proto *min, const union ip_conntrack_manip_proto *max) { - u_int32_t key; + __be16 key; if (maniptype == IP_NAT_MANIP_SRC) key = tuple->src.u.gre.key; else key = tuple->dst.u.gre.key; - return ntohl(key) >= ntohl(min->gre.key) - && ntohl(key) <= ntohl(max->gre.key); + return ntohs(key) >= ntohs(min->gre.key) + && ntohs(key) <= ntohs(max->gre.key); } /* generate unique tuple ... */ @@ -81,14 +81,14 @@ gre_unique_tuple(struct ip_conntrack_tuple *tuple, min = 1; range_size = 0xffff; } else { - min = ntohl(range->min.gre.key); - range_size = ntohl(range->max.gre.key) - min + 1; + min = ntohs(range->min.gre.key); + range_size = ntohs(range->max.gre.key) - min + 1; } DEBUGP("min = %u, range_size = %u\n", min, range_size); for (i = 0; i < range_size; i++, key++) { - *keyptr = htonl(min + key % range_size); + *keyptr = htons(min + key % range_size); if (!ip_nat_used_tuple(tuple, conntrack)) return 1; } diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 39fd4c2a2386..b98f7b08b084 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -428,7 +428,7 @@ ipt_log_target(struct sk_buff **pskb, if (loginfo->logflags & IPT_LOG_NFLOG) nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, - loginfo->prefix); + "%s", loginfo->prefix); else ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, loginfo->prefix); diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 143843285702..b847ee409efb 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c @@ -821,6 +821,7 @@ checkentry(const char *tablename, /* Create our proc 'status' entry. */ curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent); if (!curr_table->status_proc) { + vfree(hold); printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n"); /* Destroy the created table */ spin_lock_bh(&recent_lock); @@ -845,7 +846,6 @@ checkentry(const char *tablename, spin_unlock_bh(&recent_lock); vfree(curr_table->time_info); vfree(curr_table->hash_table); - vfree(hold); vfree(curr_table->table); vfree(curr_table); return 0; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9f0cca4c4fae..4a538bc1683d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1662,6 +1662,8 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_sock *tp) if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) { TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; tp->lost_out += tcp_skb_pcount(skb); + if (IsReno(tp)) + tcp_remove_reno_sacks(sk, tp, tcp_skb_pcount(skb) + 1); /* clear xmit_retrans hint */ if (tp->retransmit_skb_hint && diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 0a673038344f..2e72f89a7019 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1103,7 +1103,7 @@ do_add_counters(void __user *user, unsigned int len) write_lock_bh(&t->lock); private = t->private; - if (private->number != paddc->num_counters) { + if (private->number != tmp.num_counters) { ret = -EINVAL; goto unlock_up_free; } diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index a96c0de14b00..73c6300109d6 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -439,7 +439,7 @@ ip6t_log_target(struct sk_buff **pskb, if (loginfo->logflags & IP6T_LOG_NFLOG) nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, - loginfo->prefix); + "%s", loginfo->prefix); else ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, loginfo->prefix); diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 94dbdb8b458d..4f6b84c8f4ab 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c @@ -40,7 +40,7 @@ match(const struct sk_buff *skb, memset(eui64, 0, sizeof(eui64)); - if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) { + if (eth_hdr(skb)->h_proto == htons(ETH_P_IPV6)) { if (skb->nh.ipv6h->version == 0x6) { memcpy(eui64, eth_hdr(skb)->h_source, 3); memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 2dbf134d5266..811d998725bc 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -944,9 +944,9 @@ out: return rc; } -static int ipx_map_frame_type(unsigned char type) +static __be16 ipx_map_frame_type(unsigned char type) { - int rc = 0; + __be16 rc = 0; switch (type) { case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX); break; diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c index 67774448efd9..a394c6fe19a2 100644 --- a/net/ipx/ipx_route.c +++ b/net/ipx/ipx_route.c @@ -119,7 +119,7 @@ out: return rc; } -static int ipxrtr_delete(long net) +static int ipxrtr_delete(__u32 net) { struct ipx_route *r, *tmp; int rc; diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index c60273cad778..61cdda4e5d3b 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -321,7 +321,7 @@ static int nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags) { spin_lock_bh(&inst->lock); - inst->flags = ntohs(flags); + inst->flags = flags; spin_unlock_bh(&inst->lock); return 0; @@ -902,7 +902,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, if (nfula[NFULA_CFG_FLAGS-1]) { u_int16_t flags = *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]); - nfulnl_set_flags(inst, ntohl(flags)); + nfulnl_set_flags(inst, ntohs(flags)); } out_put: diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 31eb83717c26..138ea92ed268 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -193,8 +193,10 @@ static void dev_watchdog(unsigned long arg) netif_running(dev) && netif_carrier_ok(dev)) { if (netif_queue_stopped(dev) && - (jiffies - dev->trans_start) > dev->watchdog_timeo) { - printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n", dev->name); + time_after(jiffies, dev->trans_start + dev->watchdog_timeo)) { + + printk(KERN_INFO "NETDEV WATCHDOG: %s: transmit timed out\n", + dev->name); dev->tx_timeout(dev); } if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo)) diff --git a/net/sctp/input.c b/net/sctp/input.c index d117ebc75cf8..1662f9cc869e 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -73,6 +73,8 @@ static struct sctp_association *__sctp_lookup_association( const union sctp_addr *peer, struct sctp_transport **pt); +static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); + /* Calculate the SCTP checksum of an SCTP packet. */ static inline int sctp_rcv_checksum(struct sk_buff *skb) @@ -186,7 +188,6 @@ int sctp_rcv(struct sk_buff *skb) */ if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) { - sock_put(sk); if (asoc) { sctp_association_put(asoc); asoc = NULL; @@ -197,7 +198,6 @@ int sctp_rcv(struct sk_buff *skb) sk = sctp_get_ctl_sock(); ep = sctp_sk(sk)->ep; sctp_endpoint_hold(ep); - sock_hold(sk); rcvr = &ep->base; } @@ -253,25 +253,18 @@ int sctp_rcv(struct sk_buff *skb) */ sctp_bh_lock_sock(sk); - /* It is possible that the association could have moved to a different - * socket if it is peeled off. If so, update the sk. - */ - if (sk != rcvr->sk) { - sctp_bh_lock_sock(rcvr->sk); - sctp_bh_unlock_sock(sk); - sk = rcvr->sk; - } - if (sock_owned_by_user(sk)) - sk_add_backlog(sk, skb); + sctp_add_backlog(sk, skb); else - sctp_backlog_rcv(sk, skb); + sctp_inq_push(&chunk->rcvr->inqueue, chunk); - /* Release the sock and the sock ref we took in the lookup calls. - * The asoc/ep ref will be released in sctp_backlog_rcv. - */ sctp_bh_unlock_sock(sk); - sock_put(sk); + + /* Release the asoc/ep ref we took in the lookup calls. */ + if (asoc) + sctp_association_put(asoc); + else + sctp_endpoint_put(ep); return 0; @@ -280,8 +273,7 @@ discard_it: return 0; discard_release: - /* Release any structures we may be holding. */ - sock_put(sk); + /* Release the asoc/ep ref we took in the lookup calls. */ if (asoc) sctp_association_put(asoc); else @@ -290,56 +282,87 @@ discard_release: goto discard_it; } -/* Handle second half of inbound skb processing. If the sock was busy, - * we may have need to delay processing until later when the sock is - * released (on the backlog). If not busy, we call this routine - * directly from the bottom half. +/* Process the backlog queue of the socket. Every skb on + * the backlog holds a ref on an association or endpoint. + * We hold this ref throughout the state machine to make + * sure that the structure we need is still around. */ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) { struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; - struct sctp_inq *inqueue = NULL; + struct sctp_inq *inqueue = &chunk->rcvr->inqueue; struct sctp_ep_common *rcvr = NULL; + int backloged = 0; rcvr = chunk->rcvr; - BUG_TRAP(rcvr->sk == sk); - - if (rcvr->dead) { - sctp_chunk_free(chunk); - } else { - inqueue = &chunk->rcvr->inqueue; - sctp_inq_push(inqueue, chunk); - } - - /* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */ - if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) - sctp_association_put(sctp_assoc(rcvr)); - else - sctp_endpoint_put(sctp_ep(rcvr)); - + /* If the rcvr is dead then the association or endpoint + * has been deleted and we can safely drop the chunk + * and refs that we are holding. + */ + if (rcvr->dead) { + sctp_chunk_free(chunk); + goto done; + } + + if (unlikely(rcvr->sk != sk)) { + /* In this case, the association moved from one socket to + * another. We are currently sitting on the backlog of the + * old socket, so we need to move. + * However, since we are here in the process context we + * need to take make sure that the user doesn't own + * the new socket when we process the packet. + * If the new socket is user-owned, queue the chunk to the + * backlog of the new socket without dropping any refs. + * Otherwise, we can safely push the chunk on the inqueue. + */ + + sk = rcvr->sk; + sctp_bh_lock_sock(sk); + + if (sock_owned_by_user(sk)) { + sk_add_backlog(sk, skb); + backloged = 1; + } else + sctp_inq_push(inqueue, chunk); + + sctp_bh_unlock_sock(sk); + + /* If the chunk was backloged again, don't drop refs */ + if (backloged) + return 0; + } else { + sctp_inq_push(inqueue, chunk); + } + +done: + /* Release the refs we took in sctp_add_backlog */ + if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) + sctp_association_put(sctp_assoc(rcvr)); + else if (SCTP_EP_TYPE_SOCKET == rcvr->type) + sctp_endpoint_put(sctp_ep(rcvr)); + else + BUG(); + return 0; } -void sctp_backlog_migrate(struct sctp_association *assoc, - struct sock *oldsk, struct sock *newsk) +static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) { - struct sk_buff *skb; - struct sctp_chunk *chunk; + struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; + struct sctp_ep_common *rcvr = chunk->rcvr; - skb = oldsk->sk_backlog.head; - oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL; - while (skb != NULL) { - struct sk_buff *next = skb->next; - - chunk = SCTP_INPUT_CB(skb)->chunk; - skb->next = NULL; - if (&assoc->base == chunk->rcvr) - sk_add_backlog(newsk, skb); - else - sk_add_backlog(oldsk, skb); - skb = next; - } + /* Hold the assoc/ep while hanging on the backlog queue. + * This way, we know structures we need will not disappear from us + */ + if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) + sctp_association_hold(sctp_assoc(rcvr)); + else if (SCTP_EP_TYPE_SOCKET == rcvr->type) + sctp_endpoint_hold(sctp_ep(rcvr)); + else + BUG(); + + sk_add_backlog(sk, skb); } /* Handle icmp frag needed error. */ @@ -412,7 +435,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, union sctp_addr daddr; struct sctp_af *af; struct sock *sk = NULL; - struct sctp_association *asoc = NULL; + struct sctp_association *asoc; struct sctp_transport *transport = NULL; *app = NULL; *tpp = NULL; @@ -453,7 +476,6 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, return sk; out: - sock_put(sk); if (asoc) sctp_association_put(asoc); return NULL; @@ -463,7 +485,6 @@ out: void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) { sctp_bh_unlock_sock(sk); - sock_put(sk); if (asoc) sctp_association_put(asoc); } @@ -490,7 +511,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) int type = skb->h.icmph->type; int code = skb->h.icmph->code; struct sock *sk; - struct sctp_association *asoc; + struct sctp_association *asoc = NULL; struct sctp_transport *transport; struct inet_sock *inet; char *saveip, *savesctp; @@ -716,7 +737,6 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l hit: sctp_endpoint_hold(ep); - sock_hold(epb->sk); read_unlock(&head->lock); return ep; } @@ -818,7 +838,6 @@ static struct sctp_association *__sctp_lookup_association( hit: *pt = transport; sctp_association_hold(asoc); - sock_hold(epb->sk); read_unlock(&head->lock); return asoc; } @@ -846,7 +865,6 @@ int sctp_has_association(const union sctp_addr *laddr, struct sctp_transport *transport; if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) { - sock_put(asoc->base.sk); sctp_association_put(asoc); return 1; } diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 8d1dc24bab4c..c5beb2ad7ef7 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -498,10 +498,6 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_CLOSED)); - /* Set sk_err to ECONNRESET on a 1-1 style socket. */ - if (!sctp_style(asoc->base.sk, UDP)) - asoc->base.sk->sk_err = ECONNRESET; - /* SEND_FAILED sent later when cleaning up the association. */ asoc->outqueue.error = error; sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); @@ -838,6 +834,15 @@ static void sctp_cmd_del_non_primary(struct sctp_association *asoc) return; } +/* Helper function to set sk_err on a 1-1 style socket. */ +static void sctp_cmd_set_sk_err(struct sctp_association *asoc, int error) +{ + struct sock *sk = asoc->base.sk; + + if (!sctp_style(sk, UDP)) + sk->sk_err = error; +} + /* These three macros allow us to pull the debugging code out of the * main flow of sctp_do_sm() to keep attention focused on the real * functionality there. @@ -1458,6 +1463,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, local_cork = 0; asoc->peer.retran_path = t; break; + case SCTP_CMD_SET_SK_ERR: + sctp_cmd_set_sk_err(asoc, cmd->obj.error); + break; default: printk(KERN_WARNING "Impossible command: %u, %p\n", cmd->verb, cmd->obj.ptr); diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8cdba51ec076..8bc279219a72 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -93,7 +93,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, - __u16 error, + __u16 error, int sk_err, const struct sctp_association *asoc, struct sctp_transport *transport); @@ -448,7 +448,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, __u32 init_tag; struct sctp_chunk *err_chunk; struct sctp_packet *packet; - sctp_disposition_t ret; + __u16 error; if (!sctp_vtag_verify(chunk, asoc)) return sctp_sf_pdiscard(ep, asoc, type, arg, commands); @@ -480,11 +480,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, goto nomem; sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, - SCTP_STATE(SCTP_STATE_CLOSED)); - SCTP_INC_STATS(SCTP_MIB_ABORTEDS); - sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); - return SCTP_DISPOSITION_DELETE_TCB; + return sctp_stop_t1_and_abort(commands, SCTP_ERROR_INV_PARAM, + ECONNREFUSED, asoc, + chunk->transport); } /* Verify the INIT chunk before processing it. */ @@ -511,27 +509,16 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(packet)); SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, - SCTP_STATE(SCTP_STATE_CLOSED)); - sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, - SCTP_NULL()); - return SCTP_DISPOSITION_CONSUME; + error = SCTP_ERROR_INV_PARAM; } else { - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, - SCTP_STATE(SCTP_STATE_CLOSED)); - sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, - SCTP_NULL()); - return SCTP_DISPOSITION_NOMEM; + error = SCTP_ERROR_NO_RESOURCE; } } else { - ret = sctp_sf_tabort_8_4_8(ep, asoc, type, arg, - commands); - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, - SCTP_STATE(SCTP_STATE_CLOSED)); - sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, - SCTP_NULL()); - return ret; + sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); + error = SCTP_ERROR_INV_PARAM; } + return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, + asoc, chunk->transport); } /* Tag the variable length parameters. Note that we never @@ -886,6 +873,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, struct sctp_transport *transport = (struct sctp_transport *) arg; if (asoc->overall_error_count >= asoc->max_retrans) { + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -1030,6 +1019,12 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, commands); hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; + /* Make sure that the length of the parameter is what we expect */ + if (ntohs(hbinfo->param_hdr.length) != + sizeof(sctp_sender_hb_info_t)) { + return SCTP_DISPOSITION_DISCARD; + } + from_addr = hbinfo->daddr; link = sctp_assoc_lookup_paddr(asoc, &from_addr); @@ -2126,6 +2121,8 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, int attempts = asoc->init_err_counter + 1; if (attempts > asoc->max_init_attempts) { + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(SCTP_ERROR_STALE_COOKIE)); return SCTP_DISPOSITION_DELETE_TCB; @@ -2262,6 +2259,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) error = ((sctp_errhdr_t *)chunk->skb->data)->cause; + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); /* ASSOC_FAILED will DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); @@ -2306,7 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) error = ((sctp_errhdr_t *)chunk->skb->data)->cause; - return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport); + return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc, + chunk->transport); } /* @@ -2318,7 +2317,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep void *arg, sctp_cmd_seq_t *commands) { - return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc, + return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, + ENOPROTOOPT, asoc, (struct sctp_transport *)arg); } @@ -2343,7 +2343,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, * This is common code called by several sctp_sf_*_abort() functions above. */ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, - __u16 error, + __u16 error, int sk_err, const struct sctp_association *asoc, struct sctp_transport *transport) { @@ -2353,6 +2353,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, SCTP_INC_STATS(SCTP_MIB_ABORTEDS); sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); /* CMD_INIT_FAILED will DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(error)); @@ -3336,6 +3337,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_ASCONF_ACK)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); @@ -3362,6 +3365,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, * processing the rest of the chunks in the packet. */ sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_ASCONF_ACK)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); @@ -3714,9 +3719,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen( if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNREFUSED)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); } else { + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_PROTO_VIOLATION)); SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); @@ -4034,6 +4043,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( * TCB. This is a departure from our typical NOMEM handling. */ + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNABORTED)); /* Delete the established association. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_USER_ABORT)); @@ -4175,6 +4186,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( * TCB. This is a departure from our typical NOMEM handling. */ + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNREFUSED)); /* Delete the established association. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(SCTP_ERROR_USER_ABORT)); @@ -4543,6 +4556,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, struct sctp_transport *transport = arg; if (asoc->overall_error_count >= asoc->max_retrans) { + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -4662,6 +4677,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" " max_init_attempts: %d\n", attempts, asoc->max_init_attempts); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); return SCTP_DISPOSITION_DELETE_TCB; @@ -4711,6 +4728,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); } else { + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); return SCTP_DISPOSITION_DELETE_TCB; @@ -4742,6 +4761,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); if (asoc->overall_error_count >= asoc->max_retrans) { + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -4817,6 +4838,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire( if (asoc->overall_error_count >= asoc->max_retrans) { sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO)); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); @@ -4870,6 +4893,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, goto nomem; sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ETIMEDOUT)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -5309,6 +5334,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, * processing the rest of the chunks in the packet. */ sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET,SCTP_NULL()); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, + SCTP_ERROR(ECONNABORTED)); sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_DATA)); SCTP_INC_STATS(SCTP_MIB_ABORTEDS); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b6e4b89539b3..174d4d35e951 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1057,6 +1057,7 @@ static int __sctp_connect(struct sock* sk, inet_sk(sk)->dport = htons(asoc->peer.port); af = sctp_get_af_specific(to.sa.sa_family); af->to_sk_daddr(&to, sk); + sk->sk_err = 0; timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); err = sctp_wait_for_connect(asoc, &timeo); @@ -1228,7 +1229,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) ep = sctp_sk(sk)->ep; - /* Walk all associations on a socket, not on an endpoint. */ + /* Walk all associations on an endpoint. */ list_for_each_safe(pos, temp, &ep->asocs) { asoc = list_entry(pos, struct sctp_association, asocs); @@ -1241,13 +1242,13 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) if (sctp_state(asoc, CLOSED)) { sctp_unhash_established(asoc); sctp_association_free(asoc); + continue; + } + } - } else if (sock_flag(sk, SOCK_LINGER) && - !sk->sk_lingertime) - sctp_primitive_ABORT(asoc, NULL); - else - sctp_primitive_SHUTDOWN(asoc, NULL); - } else + if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) + sctp_primitive_ABORT(asoc, NULL); + else sctp_primitive_SHUTDOWN(asoc, NULL); } @@ -5317,6 +5318,7 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p, */ sctp_release_sock(sk); current_timeo = schedule_timeout(current_timeo); + BUG_ON(sk != asoc->base.sk); sctp_lock_sock(sk); *timeo_p = current_timeo; @@ -5604,12 +5606,14 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, */ newsp->type = type; - spin_lock_bh(&oldsk->sk_lock.slock); - /* Migrate the backlog from oldsk to newsk. */ - sctp_backlog_migrate(assoc, oldsk, newsk); - /* Migrate the association to the new socket. */ + /* Mark the new socket "in-use" by the user so that any packets + * that may arrive on the association after we've moved it are + * queued to the backlog. This prevents a potential race between + * backlog processing on the old socket and new-packet processing + * on the new socket. + */ + sctp_lock_sock(newsk); sctp_assoc_migrate(assoc, newsk); - spin_unlock_bh(&oldsk->sk_lock.slock); /* If the association on the newsk is already closed before accept() * is called, set RCV_SHUTDOWN flag. @@ -5618,6 +5622,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, newsk->sk_shutdown |= RCV_SHUTDOWN; newsk->sk_state = SCTP_SS_ESTABLISHED; + sctp_release_sock(newsk); } /* This proto struct describes the ULP interface for SCTP. */ diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 6d04504b2fc1..d0f86ed43f7a 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -697,29 +697,79 @@ static void check_sec_ref(struct module *mod, const char *modname, /* Walk through all sections */ for (i = 0; i < hdr->e_shnum; i++) { - Elf_Rela *rela; - Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; - Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; - const char *name = secstrings + sechdrs[i].sh_name + - strlen(".rela"); + const char *name = secstrings + sechdrs[i].sh_name; + const char *secname; + Elf_Rela r; + unsigned int r_sym; /* We want to process only relocation sections and not .init */ - if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA)) - continue; + if (sechdrs[i].sh_type == SHT_RELA) { + Elf_Rela *rela; + Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; + Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; + name += strlen(".rela"); + if (section_ref_ok(name)) + continue; - for (rela = start; rela < stop; rela++) { - Elf_Rela r; - const char *secname; - r.r_offset = TO_NATIVE(rela->r_offset); - r.r_info = TO_NATIVE(rela->r_info); - r.r_addend = TO_NATIVE(rela->r_addend); - sym = elf->symtab_start + ELF_R_SYM(r.r_info); - /* Skip special sections */ - if (sym->st_shndx >= SHN_LORESERVE) + for (rela = start; rela < stop; rela++) { + r.r_offset = TO_NATIVE(rela->r_offset); +#if KERNEL_ELFCLASS == ELFCLASS64 + if (hdr->e_machine == EM_MIPS) { + r_sym = ELF64_MIPS_R_SYM(rela->r_info); + r_sym = TO_NATIVE(r_sym); + } else { + r.r_info = TO_NATIVE(rela->r_info); + r_sym = ELF_R_SYM(r.r_info); + } +#else + r.r_info = TO_NATIVE(rela->r_info); + r_sym = ELF_R_SYM(r.r_info); +#endif + r.r_addend = TO_NATIVE(rela->r_addend); + sym = elf->symtab_start + r_sym; + /* Skip special sections */ + if (sym->st_shndx >= SHN_LORESERVE) + continue; + + secname = secstrings + + sechdrs[sym->st_shndx].sh_name; + if (section(secname)) + warn_sec_mismatch(modname, name, + elf, sym, r); + } + } else if (sechdrs[i].sh_type == SHT_REL) { + Elf_Rel *rel; + Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset; + Elf_Rel *stop = (void*)start + sechdrs[i].sh_size; + name += strlen(".rel"); + if (section_ref_ok(name)) continue; - secname = secstrings + sechdrs[sym->st_shndx].sh_name; - if (section(secname)) - warn_sec_mismatch(modname, name, elf, sym, r); + for (rel = start; rel < stop; rel++) { + r.r_offset = TO_NATIVE(rel->r_offset); +#if KERNEL_ELFCLASS == ELFCLASS64 + if (hdr->e_machine == EM_MIPS) { + r_sym = ELF64_MIPS_R_SYM(rel->r_info); + r_sym = TO_NATIVE(r_sym); + } else { + r.r_info = TO_NATIVE(rel->r_info); + r_sym = ELF_R_SYM(r.r_info); + } +#else + r.r_info = TO_NATIVE(rel->r_info); + r_sym = ELF_R_SYM(r.r_info); +#endif + r.r_addend = 0; + sym = elf->symtab_start + r_sym; + /* Skip special sections */ + if (sym->st_shndx >= SHN_LORESERVE) + continue; + + secname = secstrings + + sechdrs[sym->st_shndx].sh_name; + if (section(secname)) + warn_sec_mismatch(modname, name, + elf, sym, r); + } } } } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index b14255c72a37..861d866fcd83 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -21,6 +21,7 @@ #define ELF_ST_BIND ELF32_ST_BIND #define ELF_ST_TYPE ELF32_ST_TYPE +#define Elf_Rel Elf32_Rel #define Elf_Rela Elf32_Rela #define ELF_R_SYM ELF32_R_SYM #define ELF_R_TYPE ELF32_R_TYPE @@ -34,11 +35,31 @@ #define ELF_ST_BIND ELF64_ST_BIND #define ELF_ST_TYPE ELF64_ST_TYPE +#define Elf_Rel Elf64_Rel #define Elf_Rela Elf64_Rela #define ELF_R_SYM ELF64_R_SYM #define ELF_R_TYPE ELF64_R_TYPE #endif +/* The 64-bit MIPS ELF ABI uses an unusual reloc format. */ +typedef struct +{ + Elf32_Word r_sym; /* Symbol index */ + unsigned char r_ssym; /* Special symbol for 2nd relocation */ + unsigned char r_type3; /* 3rd relocation type */ + unsigned char r_type2; /* 2nd relocation type */ + unsigned char r_type1; /* 1st relocation type */ +} _Elf64_Mips_R_Info; + +typedef union +{ + Elf64_Xword r_info_number; + _Elf64_Mips_R_Info r_info_fields; +} _Elf64_Mips_R_Info_union; + +#define ELF64_MIPS_R_SYM(i) \ + ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) + #if KERNEL_ELFDATA != HOST_ELFDATA static inline void __endian(const void *src, void *dest, unsigned int size) @@ -48,8 +69,6 @@ static inline void __endian(const void *src, void *dest, unsigned int size) ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; } - - #define TO_NATIVE(x) \ ({ \ typeof(x) __x; \ diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d987048d3f33..21dad415b896 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3231,7 +3231,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) goto out; /* Handle mapped IPv4 packets arriving via IPv6 sockets */ - if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP)) + if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) family = PF_INET; read_lock_bh(&sk->sk_callback_lock); diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index da7ef26995c3..77b06009735d 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -151,7 +151,7 @@ static struct pnp_device_id snd_mpu401_pnpids[] = { MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); -static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device, +static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device, const struct pnp_device_id *id) { if (!pnp_port_valid(device, 0) || diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index a36ec1daa5cb..e6945db8ed1b 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -85,6 +85,8 @@ #include <linux/pnp.h> #include <linux/isapnp.h> #include <linux/moduleparam.h> +#include <linux/delay.h> + #include <asm/io.h> #include <asm/dma.h> #include <sound/core.h> diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 49796be955f3..e04fa49b0dc8 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c @@ -2026,7 +2026,8 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback, if (irq > 0) { devc->dev_no = my_dev; - if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) + if (request_irq(devc->irq, adintr, 0, devc->name, + (void *)(long)my_dev) < 0) { printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); /* Don't free it either then.. */ @@ -2175,7 +2176,7 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int if (!share_dma) { if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */ - free_irq(devc->irq, (void *)devc->dev_no); + free_irq(devc->irq, (void *)(long)devc->dev_no); sound_free_dma(dma_playback); @@ -2204,7 +2205,7 @@ irqreturn_t adintr(int irq, void *dev_id, struct pt_regs *dummy) unsigned char c930_stat = 0; int cnt = 0; - dev = (int)dev_id; + dev = (long)dev_id; devc = (ad1848_info *) audio_devs[dev]->devc; interrupt_again: /* Jump back here if int status doesn't reset */ @@ -2900,7 +2901,8 @@ static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev return(dev); } -static struct pnp_dev *ad1848_init_generic(struct pnp_card *bus, struct address_info *hw_config, int slot) +static struct pnp_dev __init *ad1848_init_generic(struct pnp_card *bus, + struct address_info *hw_config, int slot) { /* Configure Audio device */ diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c index 7de079b202f2..6e662ac009ae 100644 --- a/sound/oss/nm256_audio.c +++ b/sound/oss/nm256_audio.c @@ -960,7 +960,7 @@ static struct ac97_mixer_value_list mixer_defaults[] = { /* Installs the AC97 mixer into CARD. */ -static int __init +static int __devinit nm256_install_mixer (struct nm256_info *card) { int mixer; @@ -995,7 +995,7 @@ nm256_install_mixer (struct nm256_info *card) * RAM. */ -static void __init +static void __devinit nm256_peek_for_sig (struct nm256_info *card) { u32 port1offset @@ -1056,7 +1056,7 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) card->playing = 0; card->recording = 0; card->rev = rev; - spin_lock_init(&card->lock); + spin_lock_init(&card->lock); /* Init the memory port info. */ for (x = 0; x < 2; x++) { |