diff --git a/CREDITS b/CREDITS index 6957ef4efab3..64511e2abc8e 100644 --- a/CREDITS +++ b/CREDITS @@ -3643,11 +3643,9 @@ S: Cambridge. CB1 7EG S: England N: Chris Wright -E: chrisw@osdl.org +E: chrisw@sous-sol.org D: hacking on LSM framework and security modules. -S: c/o OSDL -S: 12725 SW Millikan Way, Suite 400 -S: Beaverton, OR 97005 +S: Portland, OR S: USA N: Michal Wronski diff --git a/Documentation/dvb/bt8xx.txt b/Documentation/dvb/bt8xx.txt index df6c05453cb5..52ed462061df 100644 --- a/Documentation/dvb/bt8xx.txt +++ b/Documentation/dvb/bt8xx.txt @@ -111,4 +111,8 @@ source: linux/Documentation/video4linux/CARDLIST.bttv If you have problems with this please do ask on the mailing list. -- -Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham +Authors: Richard Walker, + Jamie Honan, + Michael Hunold, + Manu Abraham, + Michael Krufky diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index be5ae600f533..81bc51369f59 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -180,3 +180,12 @@ Why: These events are not correct, and do not properly let userspace know when a file system has been mounted or unmounted. Userspace should poll the /proc/mounts file instead to detect this properly. Who: Greg Kroah-Hartman + +--------------------------- + +What: Support for NEC DDB5074 and DDB5476 evaluation boards. +When: June 2006 +Why: Board specific code doesn't build anymore since ~2.6.0 and no + users have complained indicating there is no more need for these + boards. This should really be considered a last call. +Who: Ralf Baechle diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 75205391b335..fc99075e0af4 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -335,6 +335,12 @@ running once the system is up. timesource is not avalible, it defaults to PIT. Format: { pit | tsc | cyclone | pmtmr } + disable_8254_timer + enable_8254_timer + [IA32/X86_64] Disable/Enable interrupt 0 timer routing + over the 8254 in addition to over the IO-APIC. The + kernel tries to set a sensible default. + hpet= [IA-32,HPET] option to disable HPET and use PIT. Format: disable @@ -1284,6 +1290,19 @@ running once the system is up. New name for the ramdisk parameter. See Documentation/ramdisk.txt. + rcu.blimit= [KNL,BOOT] Set maximum number of finished + RCU callbacks to process in one batch. + + rcu.qhimark= [KNL,BOOT] Set threshold of queued + RCU callbacks over which batch limiting is disabled. + + rcu.qlowmark= [KNL,BOOT] Set threshold of queued + RCU callbacks below which batch limiting is re-enabled. + + rcu.rsinterval= [KNL,BOOT,SMP] Set the number of additional + RCU callbacks to queued before forcing reschedule + on all cpus. + rdinit= [KNL] Format: Run specified binary instead of /init from the ramdisk, diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 8a352597830f..da4fb890165f 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -13,7 +13,7 @@ 12 -> Medion 7134 [16be:0003] 13 -> Typhoon TV+Radio 90031 14 -> ELSA EX-VISION 300TV [1048:226b] - 15 -> ELSA EX-VISION 500TV [1048:226b] + 15 -> ELSA EX-VISION 500TV [1048:226a] 16 -> ASUS TV-FM 7134 [1043:4842,1043:4830,1043:4840] 17 -> AOPEN VA1000 POWER [1131:7133] 18 -> BMK MPEX No Tuner @@ -75,7 +75,7 @@ 74 -> LifeView FlyTV Platinum Mini2 [14c0:1212] 75 -> AVerMedia AVerTVHD MCE A180 [1461:1044] 76 -> SKNet MonsterTV Mobile [1131:4ee9] - 77 -> Pinnacle PCTV 110i (saa7133) [11bd:002e] + 77 -> Pinnacle PCTV 40i/50i/110i (saa7133) [11bd:002e] 78 -> ASUSTeK P7131 Dual [1043:4862] 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B) 80 -> ASUS Digimatrix TV [1043:0210] diff --git a/MAINTAINERS b/MAINTAINERS index 9c592aa0280c..3d7d30dc5439 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -838,7 +838,6 @@ S: Maintained DVB SUBSYSTEM AND DRIVERS P: LinuxTV.org Project -M: mchehab@infradead.org M: v4l-dvb-maintainer@linuxtv.org L: linux-dvb@linuxtv.org (subscription required) W: http://linuxtv.org/ @@ -1632,8 +1631,8 @@ S: Supported LINUX SECURITY MODULE (LSM) FRAMEWORK P: Chris Wright -M: chrisw@osdl.org -L: linux-security-module@wirex.com +M: chrisw@sous-sol.org +L: linux-security-module@vger.kernel.org W: http://lsm.immunix.org T: git kernel.org:/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git S: Supported diff --git a/Makefile b/Makefile index 46eea76bc570..65a0337bebe0 100644 --- a/Makefile +++ b/Makefile @@ -905,7 +905,7 @@ define filechk_version.h ) endef -include/linux/version.h: $(srctree)/Makefile .config FORCE +include/linux/version.h: $(srctree)/Makefile .config .kernelrelease FORCE $(call filechk,version.h) # --------------------------------------------------------------------------- diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c index 9006063e7369..da677f829f76 100644 --- a/arch/alpha/kernel/irq.c +++ b/arch/alpha/kernel/irq.c @@ -151,8 +151,13 @@ handle_irq(int irq, struct pt_regs * regs) } irq_enter(); + /* + * __do_IRQ() must be called with IPL_MAX. Note that we do not + * explicitly enable interrupts afterwards - some MILO PALcode + * (namely LX164 one) seems to have severe problems with RTI + * at IPL 0. + */ local_irq_disable(); __do_IRQ(irq, regs); - local_irq_enable(); irq_exit(); } diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 15dc1a0dffbb..9f80fa502f8f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -78,7 +78,7 @@ menu "System Type" choice prompt "ARM system type" - default ARCH_RPC + default ARCH_VERSATILE config ARCH_CLPS7500 bool "Cirrus-CL-PS7500FE" diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index d7d932c02866..d6bd435a6857 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -422,12 +422,14 @@ static int timer_dyn_tick_disable(void) void timer_dyn_reprogram(void) { struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; + unsigned long next, seq; - if (dyn_tick) { - write_seqlock(&xtime_lock); - if (dyn_tick->state & DYN_TICK_ENABLED) + if (dyn_tick && (dyn_tick->state & DYN_TICK_ENABLED)) { + next = next_timer_interrupt(); + do { + seq = read_seqbegin(&xtime_lock); dyn_tick->reprogram(next_timer_interrupt() - jiffies); - write_sequnlock(&xtime_lock); + } while (read_seqretry(&xtime_lock, seq)); } } diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c index 2bec69bfa715..99d333d7ebdd 100644 --- a/arch/arm/mach-ixp4xx/nas100d-power.c +++ b/arch/arm/mach-ixp4xx/nas100d-power.c @@ -56,6 +56,9 @@ static int __init nas100d_power_init(void) static void __exit nas100d_power_exit(void) { + if (!(machine_is_nas100d())) + return; + free_irq(NAS100D_RB_IRQ, NULL); } diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S index 6f76b89ef46e..fd6adde39091 100644 --- a/arch/arm/mm/tlb-v6.S +++ b/arch/arm/mm/tlb-v6.S @@ -80,6 +80,7 @@ ENTRY(v6wbi_flush_kern_tlb_range) add r0, r0, #PAGE_SZ cmp r0, r1 blo 1b + mcr p15, 0, r2, c7, c10, 4 @ data synchronization barrier mov pc, lr .section ".text.init", #alloc, #execinstr diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index ed79ae20e88d..dd344f112cfe 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -45,6 +45,9 @@ #include #include +void (*pm_power_off)(void) = NULL; +EXPORT_SYMBOL(pm_power_off); + asmlinkage void ret_from_fork(void); /* diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 53bb9a79e274..65656c033d70 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -11,7 +11,7 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ obj-y += cpu/ obj-y += timers/ -obj-$(CONFIG_ACPI) += acpi/ +obj-y += acpi/ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o obj-$(CONFIG_MCA) += mca.o obj-$(CONFIG_X86_MSR) += msr.o diff --git a/arch/i386/kernel/acpi/Makefile b/arch/i386/kernel/acpi/Makefile index d51c7313cae8..7e9ac99354f4 100644 --- a/arch/i386/kernel/acpi/Makefile +++ b/arch/i386/kernel/acpi/Makefile @@ -1,4 +1,4 @@ -obj-y := boot.o +obj-$(CONFIG_ACPI) += boot.o obj-$(CONFIG_X86_IO_APIC) += earlyquirk.o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup.o diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 79577f0ace98..f1a21945963d 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c @@ -1111,9 +1111,6 @@ int __init acpi_boot_table_init(void) disable_acpi(); return error; } -#ifdef __i386__ - check_acpi_pci(); -#endif acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c index f1b9d2a46dab..2e3b643a4dc4 100644 --- a/arch/i386/kernel/acpi/earlyquirk.c +++ b/arch/i386/kernel/acpi/earlyquirk.c @@ -7,14 +7,22 @@ #include #include #include +#include static int __init check_bridge(int vendor, int device) { +#ifdef CONFIG_ACPI /* According to Nvidia all timer overrides are bogus. Just ignore them all. */ if (vendor == PCI_VENDOR_ID_NVIDIA) { acpi_skip_timer_override = 1; } +#endif + if (vendor == PCI_VENDOR_ID_ATI && timer_over_8254 == 1) { + timer_over_8254 = 0; + printk(KERN_INFO "ATI board detected. Disabling timer routing " + "over 8254.\n"); + } return 0; } diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 4ecd4b326ded..e6bd095ae108 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -278,10 +278,10 @@ void __devinit generic_identify(struct cpuinfo_x86 * c) c->x86_capability[4] = excap; c->x86 = (tfms >> 8) & 15; c->x86_model = (tfms >> 4) & 15; - if (c->x86 == 0xf) { + if (c->x86 == 0xf) c->x86 += (tfms >> 20) & 0xff; + if (c->x86 >= 0x6) c->x86_model += ((tfms >> 16) & 0xF) << 4; - } c->x86_mask = tfms & 15; } else { /* Have CPUID level 0 only - unheard of */ diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index e3e42fd62401..c9cad7ba0d2d 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c @@ -70,10 +70,13 @@ static void efi_call_phys_prelog(void) { unsigned long cr4; unsigned long temp; + struct Xgt_desc_struct *cpu_gdt_descr; spin_lock(&efi_rt_lock); local_irq_save(efi_rt_eflags); + cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0); + /* * If I don't have PSE, I should just duplicate two entries in page * directory. If I have PSE, I just need to duplicate one entry in @@ -103,18 +106,17 @@ static void efi_call_phys_prelog(void) */ local_flush_tlb(); - per_cpu(cpu_gdt_descr, 0).address = - __pa(per_cpu(cpu_gdt_descr, 0).address); - load_gdt((struct Xgt_desc_struct *)__pa(&per_cpu(cpu_gdt_descr, 0))); + cpu_gdt_descr->address = __pa(cpu_gdt_descr->address); + load_gdt(cpu_gdt_descr); } static void efi_call_phys_epilog(void) { unsigned long cr4; + struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0); - per_cpu(cpu_gdt_descr, 0).address = - (unsigned long)__va(per_cpu(cpu_gdt_descr, 0).address); - load_gdt((struct Xgt_desc_struct *)__va(&per_cpu(cpu_gdt_descr, 0))); + cpu_gdt_descr->address = __va(cpu_gdt_descr->address); + load_gdt(cpu_gdt_descr); cr4 = read_cr4(); diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 235822b3f41b..39d9a5fa907e 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -51,6 +51,8 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; static DEFINE_SPINLOCK(ioapic_lock); +int timer_over_8254 __initdata = 1; + /* * Is the SiS APIC rmw bug present ? * -1 = don't know, 0 = no, 1 = yes @@ -2267,7 +2269,8 @@ static inline void check_timer(void) apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); timer_ack = 1; - enable_8259A_irq(0); + if (timer_over_8254 > 0) + enable_8259A_irq(0); pin1 = find_isa_irq_pin(0, mp_INT); apic1 = find_isa_irq_apic(0, mp_INT); @@ -2392,6 +2395,20 @@ void __init setup_IO_APIC(void) print_IO_APIC(); } +static int __init setup_disable_8254_timer(char *s) +{ + timer_over_8254 = -1; + return 1; +} +static int __init setup_enable_8254_timer(char *s) +{ + timer_over_8254 = 2; + return 1; +} + +__setup("disable_8254_timer", setup_disable_8254_timer); +__setup("enable_8254_timer", setup_enable_8254_timer); + /* * Called after all the initialization is done. If we didnt find any * APIC bugs then we can allow the modify fast path diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c index a912fed48482..f73d7374a2ba 100644 --- a/arch/i386/kernel/machine_kexec.c +++ b/arch/i386/kernel/machine_kexec.c @@ -116,13 +116,13 @@ static void load_segments(void) __asm__ __volatile__ ( "\tljmp $"STR(__KERNEL_CS)",$1f\n" "\t1:\n" - "\tmovl $"STR(__KERNEL_DS)",%eax\n" - "\tmovl %eax,%ds\n" - "\tmovl %eax,%es\n" - "\tmovl %eax,%fs\n" - "\tmovl %eax,%gs\n" - "\tmovl %eax,%ss\n" - ); + "\tmovl $"STR(__KERNEL_DS)",%%eax\n" + "\tmovl %%eax,%%ds\n" + "\tmovl %%eax,%%es\n" + "\tmovl %%eax,%%fs\n" + "\tmovl %%eax,%%gs\n" + "\tmovl %%eax,%%ss\n" + ::: "eax", "memory"); #undef STR #undef __STR } diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 63f39a7e2c96..be87c5e2ee95 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -357,7 +357,7 @@ static void clear_msr_range(unsigned int base, unsigned int n) wrmsr(base+i, 0, 0); } -static inline void write_watchdog_counter(const char *descr) +static void write_watchdog_counter(const char *descr) { u64 count = (u64)cpu_khz * 1000; @@ -544,7 +544,7 @@ void nmi_watchdog_tick (struct pt_regs * regs) * die_nmi will return ONLY if NOTIFY_STOP happens.. */ die_nmi(regs, "NMI Watchdog detected LOCKUP"); - + } else { last_irq_sums[cpu] = sum; alert_counter[cpu] = 0; } diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 51e513b4f72d..ab62a9f4701e 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -1599,6 +1599,10 @@ void __init setup_arch(char **cmdline_p) if (efi_enabled) efi_map_memmap(); +#ifdef CONFIG_X86_IO_APIC + check_acpi_pci(); /* Checks more than just ACPI actually */ +#endif + #ifdef CONFIG_ACPI /* * Parse the ACPI tables for possible boot-time SMP configuration. diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index a14d594bfbeb..9d3074759856 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -412,9 +412,9 @@ static int timer_resume(struct sys_device *dev) write_seqlock_irqsave(&xtime_lock, flags); xtime.tv_sec = sec; xtime.tv_nsec = 0; - write_sequnlock_irqrestore(&xtime_lock, flags); - jiffies += sleep_length; + jiffies_64 += sleep_length; wall_jiffies += sleep_length; + write_sequnlock_irqrestore(&xtime_lock, flags); if (last_timer->resume) last_timer->resume(); cur_timer = last_timer; diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index 184678fe7832..744fd2f79f61 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.16-rc5 -# Mon Feb 27 16:15:43 2006 +# Thu Mar 2 16:39:10 2006 # # @@ -312,7 +312,13 @@ CONFIG_FW_LOADER=m # # Plug and Play support # -# CONFIG_PNP is not set +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y # # Block devices @@ -357,6 +363,7 @@ CONFIG_BLK_DEV_IDESCSI=m # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEPNP is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set @@ -525,6 +532,7 @@ CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set # # ARCnet devices diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c index 6ade3790ce07..e00b21514f7c 100644 --- a/arch/ia64/kernel/cyclone.c +++ b/arch/ia64/kernel/cyclone.c @@ -36,7 +36,7 @@ int __init init_cyclone_clock(void) u32* volatile cyclone_timer; /* Cyclone MPMC0 register */ if (!use_cyclone) - return -ENODEV; + return 0; printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index 9f80569a32b0..dcd906fe5749 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -561,11 +561,12 @@ ENTRY(dirty_bit) ;; // avoid RAW on r18 mov ar.ccv=r18 // set compare value for cmpxchg or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits + tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit ;; - cmpxchg8.acq r26=[r17],r25,ar.ccv +(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present mov r24=PAGE_SHIFT<<2 ;; - cmp.eq p6,p7=r26,r18 +(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present ;; (p6) itc.d r25 // install updated PTE ;; @@ -626,11 +627,12 @@ ENTRY(iaccess_bit) ;; mov ar.ccv=r18 // set compare value for cmpxchg or r25=_PAGE_A,r18 // set the accessed bit + tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit ;; - cmpxchg8.acq r26=[r17],r25,ar.ccv +(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present mov r24=PAGE_SHIFT<<2 ;; - cmp.eq p6,p7=r26,r18 +(p6) cmp.eq p6,p7=r26,r18 // Only if page present ;; (p6) itc.i r25 // install updated PTE ;; @@ -680,11 +682,12 @@ ENTRY(daccess_bit) ;; // avoid RAW on r18 mov ar.ccv=r18 // set compare value for cmpxchg or r25=_PAGE_A,r18 // set the dirty bit + tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit ;; - cmpxchg8.acq r26=[r17],r25,ar.ccv +(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present mov r24=PAGE_SHIFT<<2 ;; - cmp.eq p6,p7=r26,r18 +(p6) cmp.eq p6,p7=r26,r18 // Only if page is present ;; (p6) itc.d r25 // install updated PTE /* diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 8fd93afa75a7..e883d85906db 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -123,8 +123,9 @@ mca_page_isolate(unsigned long paddr) void mca_handler_bh(unsigned long paddr) { - printk(KERN_DEBUG "OS_MCA: process [pid: %d](%s) encounters MCA.\n", - current->pid, current->comm); + printk(KERN_ERR + "OS_MCA: process [pid: %d](%s) encounters MCA (paddr=%lx)\n", + current->pid, current->comm, paddr); spin_lock(&mca_bh_lock); switch (mca_page_isolate(paddr)) { @@ -132,7 +133,7 @@ mca_handler_bh(unsigned long paddr) printk(KERN_DEBUG "Page isolation: ( %lx ) success.\n", paddr); break; case ISOLATE_NG: - printk(KERN_DEBUG "Page isolation: ( %lx ) failure.\n", paddr); + printk(KERN_CRIT "Page isolation: ( %lx ) failure.\n", paddr); break; default: break; @@ -567,10 +568,15 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, return 0; /* - * If there is no bus error, record is weird but we need not to recover. + * The cache check and bus check bits have four possible states + * cc bc + * 0 0 Weird record, not recovered + * 1 0 Cache error, not recovered + * 0 1 I/O error, attempt recovery + * 1 1 Memory error, attempt recovery */ if (psp->bc == 0 || pbci == NULL) - return 1; + return 0; /* * Sorry, we cannot handle so many. diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 24eefb2fc55f..b2e1e746b47f 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -446,7 +446,7 @@ static struct proc_dir_entry *proc_sn2_ptc; static int __init sn2_ptc_init(void) { if (!ia64_platform_is("sn2")) - return -ENOSYS; + return 0; if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 8a56f8b5ffa2..99cb28e74295 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -484,7 +484,7 @@ static int __init tiocx_init(void) int found_tiocx_device = 0; if (!ia64_platform_is("sn2")) - return -ENODEV; + return 0; bus_register(&tiocx_bus_type); diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 767de847b4ab..3a0f89d2c8dc 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1053,6 +1053,7 @@ config CPU_MIPS32_R1 depends on SYS_HAS_CPU_MIPS32_R1 select CPU_HAS_PREFETCH select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM help Choose this option to build a kernel for release 1 or later of the MIPS32 architecture. Most modern embedded systems with a 32-bit @@ -1069,6 +1070,7 @@ config CPU_MIPS32_R2 depends on SYS_HAS_CPU_MIPS32_R2 select CPU_HAS_PREFETCH select CPU_SUPPORTS_32BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM help Choose this option to build a kernel for release 2 or later of the MIPS32 architecture. Most modern embedded systems with a 32-bit @@ -1082,6 +1084,7 @@ config CPU_MIPS64_R1 select CPU_HAS_PREFETCH select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM help Choose this option to build a kernel for release 1 or later of the MIPS64 architecture. Many modern embedded systems with a 64-bit @@ -1099,6 +1102,7 @@ config CPU_MIPS64_R2 select CPU_HAS_PREFETCH select CPU_SUPPORTS_32BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL + select CPU_SUPPORTS_HIGHMEM help Choose this option to build a kernel for release 2 or later of the MIPS64 architecture. Many modern embedded systems with a 64-bit diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 38c0f3360d51..fe9da16f3a40 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -95,6 +95,7 @@ endif # crossformat linking we rely on the elf2ecoff tool for format conversion. # cflags-y += -G 0 -mno-abicalls -fno-pic -pipe +cflags-y += -msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib MODFLAGS += -mlong-calls diff --git a/arch/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c index 51785a6a7328..bc32fe64f42a 100644 --- a/arch/mips/arc/arc_con.c +++ b/arch/mips/arc/arc_con.c @@ -24,7 +24,7 @@ static void prom_console_write(struct console *co, const char *s, } } -static int __init prom_console_setup(struct console *co, char *options) +static int prom_console_setup(struct console *co, char *options) { return !(prom_flags & PROM_FLAG_USE_AS_CONSOLE); } diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c index 0ac067f45cf5..0613f1f36b1b 100644 --- a/arch/mips/kernel/irq-mv6434x.c +++ b/arch/mips/kernel/irq-mv6434x.c @@ -11,12 +11,14 @@ #include #include #include -#include -#include #include +#include +#include + +#include #include #include -#include +#include static unsigned int irq_base; diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 7050b4ffffcd..42c94c771afb 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c @@ -163,7 +163,7 @@ void do_gettimeofday(struct timeval *tv) unsigned long seq; unsigned long lost; unsigned long usec, sec; - unsigned long max_ntp_tick = tick_usec - tickadj; + unsigned long max_ntp_tick; do { seq = read_seqbegin(&xtime_lock); @@ -178,12 +178,13 @@ void do_gettimeofday(struct timeval *tv) * Better to lose some accuracy than have time go backwards.. */ if (unlikely(time_adjust < 0)) { + max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj; usec = min(usec, max_ntp_tick); if (lost) usec += lost * max_ntp_tick; } else if (unlikely(lost)) - usec += lost * tick_usec; + usec += lost * (USEC_PER_SEC / HZ); sec = xtime.tv_sec; usec += (xtime.tv_nsec / 1000); diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index ff699dbb99f7..2ad0cedf29fe 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -106,6 +106,9 @@ SECTIONS .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; SECURITY_INIT + /* .exit.text is discarded at runtime, not link time, to deal with + references from .rodata */ + .exit.text : { *(.exit.text) } . = ALIGN(_PAGE_SIZE); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } @@ -133,7 +136,6 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { - *(.exit.text) *(.exit.data) *(.exitcall.exit) diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 0f9485806bac..ac4f4bfaae50 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -280,69 +280,69 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...) } #define I_u1u2u3(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ unsigned int b, unsigned int c) \ { \ build_insn(buf, insn##op, a, b, c); \ } #define I_u2u1u3(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ unsigned int b, unsigned int c) \ { \ build_insn(buf, insn##op, b, a, c); \ } #define I_u3u1u2(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ unsigned int b, unsigned int c) \ { \ build_insn(buf, insn##op, b, c, a); \ } #define I_u1u2s3(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ unsigned int b, signed int c) \ { \ build_insn(buf, insn##op, a, b, c); \ } #define I_u2s3u1(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ signed int b, unsigned int c) \ { \ build_insn(buf, insn##op, c, a, b); \ } #define I_u2u1s3(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ unsigned int b, signed int c) \ { \ build_insn(buf, insn##op, b, a, c); \ } #define I_u1u2(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ unsigned int b) \ { \ build_insn(buf, insn##op, a, b); \ } #define I_u1s2(op) \ - static inline void i##op(u32 **buf, unsigned int a, \ + static inline void __init i##op(u32 **buf, unsigned int a, \ signed int b) \ { \ build_insn(buf, insn##op, a, b); \ } #define I_u1(op) \ - static inline void i##op(u32 **buf, unsigned int a) \ + static inline void __init i##op(u32 **buf, unsigned int a) \ { \ build_insn(buf, insn##op, a); \ } #define I_0(op) \ - static inline void i##op(u32 **buf) \ + static inline void __init i##op(u32 **buf) \ { \ build_insn(buf, insn##op); \ } @@ -623,42 +623,42 @@ static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel, } /* convenience functions for labeled branches */ -static void __attribute__((unused)) il_bltz(u32 **p, struct reloc **r, - unsigned int reg, enum label_id l) +static void __init __attribute__((unused)) + il_bltz(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); i_bltz(p, reg, 0); } -static void __attribute__((unused)) il_b(u32 **p, struct reloc **r, +static void __init __attribute__((unused)) il_b(u32 **p, struct reloc **r, enum label_id l) { r_mips_pc16(r, *p, l); i_b(p, 0); } -static void il_beqz(u32 **p, struct reloc **r, unsigned int reg, +static void __init il_beqz(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); i_beqz(p, reg, 0); } -static void __attribute__((unused)) +static void __init __attribute__((unused)) il_beqzl(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); i_beqzl(p, reg, 0); } -static void il_bnez(u32 **p, struct reloc **r, unsigned int reg, +static void __init il_bnez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); i_bnez(p, reg, 0); } -static void il_bgezl(u32 **p, struct reloc **r, unsigned int reg, +static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) { r_mips_pc16(r, *p, l); diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c index aae7a802767a..1cadaa92946a 100644 --- a/arch/mips/momentum/jaguar_atx/prom.c +++ b/arch/mips/momentum/jaguar_atx/prom.c @@ -21,10 +21,10 @@ #include #include #include +#include #include #include -#include #include #include "jaguar_atx_fpga.h" diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index 301d67226d72..2699917b640a 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c @@ -2,7 +2,7 @@ * BRIEF MODULE DESCRIPTION * Momentum Computer Jaguar-ATX board dependent boot routines * - * Copyright (C) 1996, 1997, 2001, 2004 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 1996, 1997, 2001, 04, 06 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2000 RidgeRun, Inc. * Copyright (C) 2001 Red Hat, Inc. * Copyright (C) 2002 Momentum Computer @@ -55,6 +55,8 @@ #include #include #include +#include + #include #include #include @@ -64,7 +66,6 @@ #include #include #include -#include #include "jaguar_atx_fpga.h" diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c index 300fe8e4fbe8..a5764bc20e36 100644 --- a/arch/mips/momentum/ocelot_c/irq.c +++ b/arch/mips/momentum/ocelot_c/irq.c @@ -41,11 +41,11 @@ #include #include #include +#include #include #include #include #include -#include #include extern asmlinkage void ocelot_handle_int(void); diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c index 5b6809724b15..e92364482c7b 100644 --- a/arch/mips/momentum/ocelot_c/prom.c +++ b/arch/mips/momentum/ocelot_c/prom.c @@ -19,10 +19,10 @@ #include #include #include +#include #include #include -#include #include #include "ocelot_c_fpga.h" diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index 15998d8a9341..bd02e60d037a 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -64,9 +65,9 @@ #include #include #include +#include #include #include -#include #include "ocelot_c_fpga.h" unsigned long marvell_base; @@ -252,22 +253,22 @@ void __init plat_setup(void) /* shut down ethernet ports, just to be sure our memory doesn't get * corrupted by random ethernet traffic. */ - MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); - MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); - MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); - MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); + MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); + MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); + MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); + MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); do {} - while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); + while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); do {} - while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); + while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); do {} - while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); + while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); do {} - while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); - MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0), - MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); - MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1), - MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); + while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); + MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0), + MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); + MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1), + MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); /* Turn off the Bit-Error LED */ OCELOT_FPGA_WRITE(0x80, CLR); diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c index 1d84d36e034d..027759f7c904 100644 --- a/arch/mips/pci/pci-ocelot-c.c +++ b/arch/mips/pci/pci-ocelot-c.c @@ -3,15 +3,17 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2004, 06 by Ralf Baechle (ralf@linux-mips.org) */ #include #include -#include +#include #include +#include + /* * We assume the address ranges have already been setup appropriately by * the firmware. PMON in case of the Ocelot C does that. diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 840aad43a98b..c9a660e4c2db 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -92,7 +92,6 @@ int main(void) DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame)); DEFINE(TI_TASK, offsetof(struct thread_info, task)); #ifdef CONFIG_PPC32 DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 10696456a4c6..e4e81374cb9a 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -53,8 +53,10 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); PPC_FEATURE_HAS_MMU) #define COMMON_USER_PPC64 (COMMON_USER | PPC_FEATURE_64) #define COMMON_USER_POWER4 (COMMON_USER_PPC64 | PPC_FEATURE_POWER4) -#define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5) -#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS) +#define COMMON_USER_POWER5 (COMMON_USER_PPC64 | PPC_FEATURE_POWER5 |\ + PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) +#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\ + PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ PPC_FEATURE_BOOKE) @@ -267,7 +269,8 @@ struct cpu_spec cpu_specs[] = { .cpu_name = "Cell Broadband Engine", .cpu_features = CPU_FTRS_CELL, .cpu_user_features = COMMON_USER_PPC64 | - PPC_FEATURE_CELL | PPC_FEATURE_HAS_ALTIVEC_COMP, + PPC_FEATURE_CELL | PPC_FEATURE_HAS_ALTIVEC_COMP | + PPC_FEATURE_SMT, .icache_bsize = 128, .dcache_bsize = 128, .cpu_setup = __setup_cpu_be, diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index f20a67261ec7..4827ca1ec89b 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -227,7 +227,7 @@ ret_from_syscall: MTMSRD(r10) lwz r9,TI_FLAGS(r12) li r8,-_LAST_ERRNO - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK) bne- syscall_exit_work cmplw 0,r3,r8 blt+ syscall_exit_cont @@ -287,8 +287,10 @@ syscall_dotrace: syscall_exit_work: andi. r0,r9,_TIF_RESTOREALL - bne- 2f - cmplw 0,r3,r8 + beq+ 0f + REST_NVGPRS(r1) + b 2f +0: cmplw 0,r3,r8 blt+ 1f andi. r0,r9,_TIF_NOERROR bne- 1f @@ -302,9 +304,7 @@ syscall_exit_work: 2: andi. r0,r9,(_TIF_PERSYSCALL_MASK) beq 4f - /* Clear per-syscall TIF flags if any are set, but _leave_ - _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that - yet. */ + /* Clear per-syscall TIF flags if any are set. */ li r11,_TIF_PERSYSCALL_MASK addi r12,r12,TI_FLAGS @@ -318,8 +318,13 @@ syscall_exit_work: subi r12,r12,TI_FLAGS 4: /* Anything which requires enabling interrupts? */ - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS) - beq 7f + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) + beq ret_from_except + + /* Re-enable interrupts */ + ori r10,r10,MSR_EE + SYNC + MTMSRD(r10) /* Save NVGPRS if they're not saved already */ lwz r4,_TRAP(r1) @@ -328,71 +333,11 @@ syscall_exit_work: SAVE_NVGPRS(r1) li r4,0xc00 stw r4,_TRAP(r1) - - /* Re-enable interrupts */ -5: ori r10,r10,MSR_EE - SYNC - MTMSRD(r10) - - andi. r0,r9,_TIF_SAVE_NVGPRS - bne save_user_nvgprs - -save_user_nvgprs_cont: - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) - beq 7f - +5: addi r3,r1,STACK_FRAME_OVERHEAD bl do_syscall_trace_leave - REST_NVGPRS(r1) + b ret_from_except_full -6: lwz r3,GPR3(r1) - LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ - SYNC - MTMSRD(r10) /* disable interrupts again */ - rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ - lwz r9,TI_FLAGS(r12) -7: - andi. r0,r9,_TIF_NEED_RESCHED - bne 8f - lwz r5,_MSR(r1) - andi. r5,r5,MSR_PR - beq ret_from_except - andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK - beq ret_from_except - b do_user_signal -8: - ori r10,r10,MSR_EE - SYNC - MTMSRD(r10) /* re-enable interrupts */ - bl schedule - b 6b - -save_user_nvgprs: - lwz r8,TI_SIGFRAME(r12) - -.macro savewords start, end - 1: stw \start,4*(\start)(r8) - .section __ex_table,"a" - .align 2 - .long 1b,save_user_nvgprs_fault - .previous - .if \end - \start - savewords "(\start+1)",\end - .endif -.endm - savewords 14,31 - b save_user_nvgprs_cont - - -save_user_nvgprs_fault: - li r3,11 /* SIGSEGV */ - lwz r4,TI_TASK(r12) - bl force_sigsegv - - rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ - lwz r9,TI_FLAGS(r12) - b save_user_nvgprs_cont - #ifdef SHOW_SYSCALLS do_show_syscall: #ifdef SHOW_SYSCALLS_TASK @@ -490,6 +435,14 @@ ppc_clone: stw r0,_TRAP(r1) /* register set saved */ b sys_clone + .globl ppc_swapcontext +ppc_swapcontext: + SAVE_NVGPRS(r1) + lwz r0,_TRAP(r1) + rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */ + stw r0,_TRAP(r1) /* register set saved */ + b sys_swapcontext + /* * Top-level page fault handling. * This is in assembler because if do_page_fault tells us that @@ -683,7 +636,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ /* Check current_thread_info()->flags */ rlwinm r9,r1,0,0,(31-THREAD_SHIFT) lwz r9,TI_FLAGS(r9) - andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) + andi. r0,r9,(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NEED_RESCHED) bne do_work restore_user: diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 388f861b8ed1..24be0cf86d7f 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -160,7 +160,7 @@ syscall_exit: mtmsrd r10,1 ld r9,TI_FLAGS(r12) li r11,-_LAST_ERRNO - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK) bne- syscall_exit_work cmpld r3,r11 ld r5,_CCR(r1) @@ -216,8 +216,10 @@ syscall_exit_work: If TIF_NOERROR is set, just save r3 as it is. */ andi. r0,r9,_TIF_RESTOREALL - bne- 2f - cmpld r3,r11 /* r10 is -LAST_ERRNO */ + beq+ 0f + REST_NVGPRS(r1) + b 2f +0: cmpld r3,r11 /* r10 is -LAST_ERRNO */ blt+ 1f andi. r0,r9,_TIF_NOERROR bne- 1f @@ -229,9 +231,7 @@ syscall_exit_work: 2: andi. r0,r9,(_TIF_PERSYSCALL_MASK) beq 4f - /* Clear per-syscall TIF flags if any are set, but _leave_ - _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that - yet. */ + /* Clear per-syscall TIF flags if any are set. */ li r11,_TIF_PERSYSCALL_MASK addi r12,r12,TI_FLAGS @@ -240,10 +240,9 @@ syscall_exit_work: stdcx. r10,0,r12 bne- 3b subi r12,r12,TI_FLAGS - -4: bl .save_nvgprs - /* Anything else left to do? */ - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS) + +4: /* Anything else left to do? */ + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) beq .ret_from_except_lite /* Re-enable interrupts */ @@ -251,26 +250,10 @@ syscall_exit_work: ori r10,r10,MSR_EE mtmsrd r10,1 - andi. r0,r9,_TIF_SAVE_NVGPRS - bne save_user_nvgprs - - /* If tracing, re-enable interrupts and do it */ -save_user_nvgprs_cont: - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) - beq 5f - + bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD bl .do_syscall_trace_leave - REST_NVGPRS(r1) - clrrdi r12,r1,THREAD_SHIFT - - /* Disable interrupts again and handle other work if any */ -5: mfmsr r10 - rldicl r10,r10,48,1 - rotldi r10,r10,16 - mtmsrd r10,1 - - b .ret_from_except_lite + b .ret_from_except /* Save non-volatile GPRs, if not already saved. */ _GLOBAL(save_nvgprs) @@ -282,51 +265,6 @@ _GLOBAL(save_nvgprs) std r0,_TRAP(r1) blr - -save_user_nvgprs: - ld r10,TI_SIGFRAME(r12) - andi. r0,r9,_TIF_32BIT - beq- save_user_nvgprs_64 - - /* 32-bit save to userspace */ - -.macro savewords start, end - 1: stw \start,4*(\start)(r10) - .section __ex_table,"a" - .align 3 - .llong 1b,save_user_nvgprs_fault - .previous - .if \end - \start - savewords "(\start+1)",\end - .endif -.endm - savewords 14,31 - b save_user_nvgprs_cont - -save_user_nvgprs_64: - /* 64-bit save to userspace */ - -.macro savelongs start, end - 1: std \start,8*(\start)(r10) - .section __ex_table,"a" - .align 3 - .llong 1b,save_user_nvgprs_fault - .previous - .if \end - \start - savelongs "(\start+1)",\end - .endif -.endm - savelongs 14,31 - b save_user_nvgprs_cont - -save_user_nvgprs_fault: - li r3,11 /* SIGSEGV */ - ld r4,TI_TASK(r12) - bl .force_sigsegv - - clrrdi r12,r1,THREAD_SHIFT - ld r9,TI_FLAGS(r12) - b save_user_nvgprs_cont /* * The sigsuspend and rt_sigsuspend system calls can call do_signal @@ -352,6 +290,16 @@ _GLOBAL(ppc_clone) bl .sys_clone b syscall_exit +_GLOBAL(ppc32_swapcontext) + bl .save_nvgprs + bl .compat_sys_swapcontext + b syscall_exit + +_GLOBAL(ppc64_swapcontext) + bl .save_nvgprs + bl .sys_swapcontext + b syscall_exit + _GLOBAL(ret_from_fork) bl .schedule_tail REST_NVGPRS(r1) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 11f2cd5af7dc..9b65029dd2a3 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -1537,6 +1537,9 @@ _STATIC(__boot_from_prom) mr r28,r6 mr r27,r7 + /* Align the stack to 16-byte boundary for broken yaboot */ + rldicr r1,r1,0,59 + /* Make sure we are running in 64 bits mode */ bl .enable_64b_mode diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index d34fe537400e..813c2cd194c2 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -978,7 +978,7 @@ static void __init prom_init_mem(void) if (size == 0) continue; prom_debug(" %x %x\n", base, size); - if (base == 0) + if (base == 0 && (RELOC(of_platform) & PLATFORM_LPAR)) RELOC(rmo_top) = size; if ((base + size) > RELOC(ram_top)) RELOC(ram_top) = base + size; diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 400793c71304..bcb83574335b 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -561,10 +561,7 @@ void do_syscall_trace_leave(struct pt_regs *regs) regs->result); if ((test_thread_flag(TIF_SYSCALL_TRACE) -#ifdef CONFIG_PPC64 - || test_thread_flag(TIF_SINGLESTEP) -#endif - ) + || test_thread_flag(TIF_SINGLESTEP)) && (current->ptrace & PT_PTRACED)) do_syscall_trace(); } diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index bd837b5dbf06..d7a4e814974d 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -151,10 +151,7 @@ static inline int save_general_regs(struct pt_regs *regs, elf_greg_t64 *gregs = (elf_greg_t64 *)regs; int i; - if (!FULL_REGS(regs)) { - set_thread_flag(TIF_SAVE_NVGPRS); - current_thread_info()->nvgprs_frame = frame->mc_gregs; - } + WARN_ON(!FULL_REGS(regs)); for (i = 0; i <= PT_RESULT; i ++) { if (i == 14 && !FULL_REGS(regs)) @@ -215,15 +212,7 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka, static inline int save_general_regs(struct pt_regs *regs, struct mcontext __user *frame) { - if (!FULL_REGS(regs)) { - /* Zero out the unsaved GPRs to avoid information - leak, and set TIF_SAVE_NVGPRS to ensure that the - registers do actually get saved later. */ - memset(®s->gpr[14], 0, 18 * sizeof(unsigned long)); - current_thread_info()->nvgprs_frame = &frame->mc_gregs; - set_thread_flag(TIF_SAVE_NVGPRS); - } - + WARN_ON(!FULL_REGS(regs)); return __copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE); } @@ -826,8 +815,8 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int } long sys_swapcontext(struct ucontext __user *old_ctx, - struct ucontext __user *new_ctx, - int ctx_size, int r6, int r7, int r8, struct pt_regs *regs) + struct ucontext __user *new_ctx, + int ctx_size, int r6, int r7, int r8, struct pt_regs *regs) { unsigned char tmp; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 497a5d3df359..4324f8a8ba24 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -118,14 +118,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, err |= __put_user(0, &sc->v_regs); #endif /* CONFIG_ALTIVEC */ err |= __put_user(&sc->gp_regs, &sc->regs); - if (!FULL_REGS(regs)) { - /* Zero out the unsaved GPRs to avoid information - leak, and set TIF_SAVE_NVGPRS to ensure that the - registers do actually get saved later. */ - memset(®s->gpr[14], 0, 18 * sizeof(unsigned long)); - set_thread_flag(TIF_SAVE_NVGPRS); - current_thread_info()->nvgprs_frame = &sc->gp_regs; - } + WARN_ON(!FULL_REGS(regs)); err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); err |= __put_user(signr, &sc->signal); diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 8a9f994ed917..1ad55f0466fd 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -288,7 +288,7 @@ COMPAT_SYS(clock_settime) COMPAT_SYS(clock_gettime) COMPAT_SYS(clock_getres) COMPAT_SYS(clock_nanosleep) -COMPAT_SYS(swapcontext) +SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext) COMPAT_SYS(tgkill) COMPAT_SYS(utimes) COMPAT_SYS(statfs64) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 7509aa6474f2..98660aedeeb7 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -814,6 +814,8 @@ void __kprobes program_check_exception(struct pt_regs *regs) return; } + local_irq_enable(); + /* Try to emulate it if we should. */ if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { switch (emulate_instruction(regs)) { diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index 4ffd2a9832a0..9b7150f10414 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c @@ -9,7 +9,12 @@ #include #include +#undef DEBUG +#ifdef DEBUG #define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif static irqreturn_t macio_gpio_irq(int irq, void *data, struct pt_regs *regs) { diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index 356a739e52b2..4baa75b1d36f 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -20,7 +20,13 @@ #define LOG_PARSE(fmt...) #define LOG_ERROR(fmt...) printk(fmt) #define LOG_BLOB(t,b,c) + +#undef DEBUG +#ifdef DEBUG #define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif /* Command numbers */ #define PMF_CMD_LIST 0 diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 0df2cdcd805c..6d64a9bf3474 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -435,7 +435,7 @@ struct smp_ops_t psurge_smp_ops = { */ static void (*pmac_tb_freeze)(int freeze); -static unsigned long timebase; +static u64 timebase; static int tb_req; static void smp_core99_give_timebase(void) diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index 7964bf660e92..77e4dc780f8c 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -131,7 +131,6 @@ main(void) DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); - DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame)); DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index a48b950722a1..3a2815978488 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -227,7 +227,7 @@ ret_from_syscall: MTMSRD(r10) lwz r9,TI_FLAGS(r12) li r8,-_LAST_ERRNO - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK) bne- syscall_exit_work cmplw 0,r3,r8 blt+ syscall_exit_cont @@ -287,8 +287,10 @@ syscall_dotrace: syscall_exit_work: andi. r0,r9,_TIF_RESTOREALL - bne- 2f - cmplw 0,r3,r8 + beq+ 0f + REST_NVGPRS(r1) + b 2f +0: cmplw 0,r3,r8 blt+ 1f andi. r0,r9,_TIF_NOERROR bne- 1f @@ -302,9 +304,7 @@ syscall_exit_work: 2: andi. r0,r9,(_TIF_PERSYSCALL_MASK) beq 4f - /* Clear per-syscall TIF flags if any are set, but _leave_ - _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that - yet. */ + /* Clear per-syscall TIF flags if any are set. */ li r11,_TIF_PERSYSCALL_MASK addi r12,r12,TI_FLAGS @@ -318,8 +318,13 @@ syscall_exit_work: subi r12,r12,TI_FLAGS 4: /* Anything which requires enabling interrupts? */ - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS) - beq 7f + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) + beq ret_from_except + + /* Re-enable interrupts */ + ori r10,r10,MSR_EE + SYNC + MTMSRD(r10) /* Save NVGPRS if they're not saved already */ lwz r4,TRAP(r1) @@ -328,71 +333,11 @@ syscall_exit_work: SAVE_NVGPRS(r1) li r4,0xc00 stw r4,TRAP(r1) - - /* Re-enable interrupts */ -5: ori r10,r10,MSR_EE - SYNC - MTMSRD(r10) - - andi. r0,r9,_TIF_SAVE_NVGPRS - bne save_user_nvgprs - -save_user_nvgprs_cont: - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) - beq 7f - +5: addi r3,r1,STACK_FRAME_OVERHEAD bl do_syscall_trace_leave - REST_NVGPRS(r1) + b ret_from_except_full -6: lwz r3,GPR3(r1) - LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ - SYNC - MTMSRD(r10) /* disable interrupts again */ - rlwinm r12,r1,0,0,18 /* current_thread_info() */ - lwz r9,TI_FLAGS(r12) -7: - andi. r0,r9,_TIF_NEED_RESCHED - bne 8f - lwz r5,_MSR(r1) - andi. r5,r5,MSR_PR - beq ret_from_except - andi. r0,r9,_TIF_SIGPENDING - beq ret_from_except - b do_user_signal -8: - ori r10,r10,MSR_EE - SYNC - MTMSRD(r10) /* re-enable interrupts */ - bl schedule - b 6b - -save_user_nvgprs: - lwz r8,TI_SIGFRAME(r12) - -.macro savewords start, end - 1: stw \start,4*(\start)(r8) - .section __ex_table,"a" - .align 2 - .long 1b,save_user_nvgprs_fault - .previous - .if \end - \start - savewords "(\start+1)",\end - .endif -.endm - savewords 14,31 - b save_user_nvgprs_cont - - -save_user_nvgprs_fault: - li r3,11 /* SIGSEGV */ - lwz r4,TI_TASK(r12) - bl force_sigsegv - - rlwinm r12,r1,0,0,18 /* current_thread_info() */ - lwz r9,TI_FLAGS(r12) - b save_user_nvgprs_cont - #ifdef SHOW_SYSCALLS do_show_syscall: #ifdef SHOW_SYSCALLS_TASK @@ -490,6 +435,14 @@ ppc_clone: stw r0,TRAP(r1) /* register set saved */ b sys_clone + .globl ppc_swapcontext +ppc_swapcontext: + SAVE_NVGPRS(r1) + lwz r0,TRAP(r1) + rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */ + stw r0,TRAP(r1) /* register set saved */ + b sys_swapcontext + /* * Top-level page fault handling. * This is in assembler because if do_page_fault tells us that @@ -683,7 +636,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ /* Check current_thread_info()->flags */ rlwinm r9,r1,0,0,18 lwz r9,TI_FLAGS(r9) - andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) + andi. r0,r9,(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NEED_RESCHED) bne do_work restore_user: diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c index 60f80a4eed4e..b9b7958a226a 100644 --- a/arch/s390/lib/spinlock.c +++ b/arch/s390/lib/spinlock.c @@ -2,8 +2,7 @@ * arch/s390/lib/spinlock.c * Out of line spinlock code. * - * S390 version - * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 2004, 2006 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) */ @@ -44,6 +43,8 @@ _raw_spin_lock_wait(raw_spinlock_t *lp, unsigned int pc) _diag44(); count = spin_retry; } + if (__raw_spin_is_locked(lp)) + continue; if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) return; } @@ -56,6 +57,8 @@ _raw_spin_trylock_retry(raw_spinlock_t *lp, unsigned int pc) int count = spin_retry; while (count-- > 0) { + if (__raw_spin_is_locked(lp)) + continue; if (_raw_compare_and_swap(&lp->lock, 0, pc) == 0) return 1; } @@ -74,6 +77,8 @@ _raw_read_lock_wait(raw_rwlock_t *rw) _diag44(); count = spin_retry; } + if (!__raw_read_can_lock(rw)) + continue; old = rw->lock & 0x7fffffffU; if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) return; @@ -88,6 +93,8 @@ _raw_read_trylock_retry(raw_rwlock_t *rw) int count = spin_retry; while (count-- > 0) { + if (!__raw_read_can_lock(rw)) + continue; old = rw->lock & 0x7fffffffU; if (_raw_compare_and_swap(&rw->lock, old, old + 1) == old) return 1; @@ -106,6 +113,8 @@ _raw_write_lock_wait(raw_rwlock_t *rw) _diag44(); count = spin_retry; } + if (!__raw_write_can_lock(rw)) + continue; if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) return; } @@ -118,6 +127,8 @@ _raw_write_trylock_retry(raw_rwlock_t *rw) int count = spin_retry; while (count-- > 0) { + if (!__raw_write_can_lock(rw)) + continue; if (_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0) return 1; } diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S index 88fc94fe6488..5d59e2625048 100644 --- a/arch/s390/lib/uaccess.S +++ b/arch/s390/lib/uaccess.S @@ -198,12 +198,12 @@ __strnlen_user_asm: 0: srst %r2,%r1 jo 0b sacf 0 - jh 1f # \0 found in string ? ahi %r2,1 # strnlen_user result includes the \0 -1: slr %r2,%r3 + # or return count+1 if \0 not found + slr %r2,%r3 br %r14 2: sacf 0 - lhi %r2,-EFAULT + slr %r2,%r2 # return 0 on exception br %r14 .section __ex_table,"a" .long 0b,2b diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S index 50219786fc7a..19b41a33c230 100644 --- a/arch/s390/lib/uaccess64.S +++ b/arch/s390/lib/uaccess64.S @@ -194,12 +194,12 @@ __strnlen_user_asm: 0: srst %r2,%r1 jo 0b sacf 0 - jh 1f # \0 found in string ? aghi %r2,1 # strnlen_user result includes the \0 -1: slgr %r2,%r3 + # or return count+1 if \0 not found + slgr %r2,%r3 br %r14 2: sacf 0 - lghi %r2,-EFAULT + slgr %r2,%r2 # return 0 on exception br %r14 .section __ex_table,"a" .quad 0b,2b diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index e73621d03a28..e9b275d90737 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -392,9 +392,9 @@ config SH_TMU endmenu -source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" +#source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" -source "arch/sh/boards/renesas/rts7751r2d/Kconfig" +#source "arch/sh/boards/renesas/rts7751r2d/Kconfig" config SH_PCLK_FREQ int "Peripheral clock frequency (in Hz)" diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 60b59375aa78..c4a1cef4b1e5 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -318,7 +318,7 @@ do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) nop nop - .section __ex_table + .section __ex_table,"a" .align 4 .word 1b, __retl_efault, 2b, __retl_efault .word 3b, __retl_efault, 4b, __retl_efault diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S index 1f5b5b708ce7..be183fe41443 100644 --- a/arch/sparc64/kernel/una_asm.S +++ b/arch/sparc64/kernel/una_asm.S @@ -47,7 +47,7 @@ __do_int_store: mov 0, %o0 .size __do_int_store, .-__do_int_store - .section __ex_table + .section __ex_table,"a" .word 4b, __retl_efault .word 5b, __retl_efault .word 6b, __retl_efault @@ -129,7 +129,7 @@ do_int_load: mov 0, %o0 .size __do_int_load, .-__do_int_load - .section __ex_table + .section __ex_table,"a" .word 4b, __retl_efault .word 5b, __retl_efault .word 6b, __retl_efault diff --git a/arch/sparc64/lib/U1copy_from_user.S b/arch/sparc64/lib/U1copy_from_user.S index 93146a81e2d3..3192b0bf4fab 100644 --- a/arch/sparc64/lib/U1copy_from_user.S +++ b/arch/sparc64/lib/U1copy_from_user.S @@ -9,7 +9,7 @@ .align 4; \ 99: retl; \ mov 1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/U1copy_to_user.S b/arch/sparc64/lib/U1copy_to_user.S index 1fccc521e2bd..d1210ffb0b82 100644 --- a/arch/sparc64/lib/U1copy_to_user.S +++ b/arch/sparc64/lib/U1copy_to_user.S @@ -9,7 +9,7 @@ .align 4; \ 99: retl; \ mov 1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc64/lib/U3copy_from_user.S index df600b667e48..f5bfc8d9d216 100644 --- a/arch/sparc64/lib/U3copy_from_user.S +++ b/arch/sparc64/lib/U3copy_from_user.S @@ -9,7 +9,7 @@ .align 4; \ 99: retl; \ mov 1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc64/lib/U3copy_to_user.S index f337f22ed82e..2334f111bb0c 100644 --- a/arch/sparc64/lib/U3copy_to_user.S +++ b/arch/sparc64/lib/U3copy_to_user.S @@ -9,7 +9,7 @@ .align 4; \ 99: retl; \ mov 1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/bzero.S b/arch/sparc64/lib/bzero.S index 21a933ffb7c2..1d2abcfa4e52 100644 --- a/arch/sparc64/lib/bzero.S +++ b/arch/sparc64/lib/bzero.S @@ -92,7 +92,7 @@ __bzero_done: .align 4; \ 99: retl; \ mov %o1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/copy_in_user.S b/arch/sparc64/lib/copy_in_user.S index 816076c0bc06..650af3f21f78 100644 --- a/arch/sparc64/lib/copy_in_user.S +++ b/arch/sparc64/lib/copy_in_user.S @@ -13,7 +13,7 @@ .align 4; \ 99: retl; \ mov 1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/csum_copy_from_user.S b/arch/sparc64/lib/csum_copy_from_user.S index 817ebdae39f8..a22eddbe5dba 100644 --- a/arch/sparc64/lib/csum_copy_from_user.S +++ b/arch/sparc64/lib/csum_copy_from_user.S @@ -9,7 +9,7 @@ .align 4; \ 99: retl; \ mov -1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/csum_copy_to_user.S b/arch/sparc64/lib/csum_copy_to_user.S index c2f9463ea1e2..d5b12f441f02 100644 --- a/arch/sparc64/lib/csum_copy_to_user.S +++ b/arch/sparc64/lib/csum_copy_to_user.S @@ -9,7 +9,7 @@ .align 4; \ 99: retl; \ mov -1, %o0; \ - .section __ex_table; \ + .section __ex_table,"a";\ .align 4; \ .word 98b, 99b; \ .text; \ diff --git a/arch/sparc64/lib/strlen_user.S b/arch/sparc64/lib/strlen_user.S index 9ed54ba14fc6..114ed111e251 100644 --- a/arch/sparc64/lib/strlen_user.S +++ b/arch/sparc64/lib/strlen_user.S @@ -85,7 +85,7 @@ __strnlen_user: retl clr %o0 - .section __ex_table,#alloc + .section __ex_table,"a" .align 4 .word 10b, 30b diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S index e1264650ca7a..b2f499f79427 100644 --- a/arch/sparc64/lib/strncpy_from_user.S +++ b/arch/sparc64/lib/strncpy_from_user.S @@ -125,7 +125,7 @@ __strncpy_from_user: add %o2, %o3, %o0 .size __strncpy_from_user, .-__strncpy_from_user - .section __ex_table,#alloc + .section __ex_table,"a" .align 4 .word 60b, __retl_efault .word 61b, __retl_efault diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S index eb314ed23cdb..f170324e8bf2 100644 --- a/arch/sparc64/solaris/entry64.S +++ b/arch/sparc64/solaris/entry64.S @@ -217,7 +217,7 @@ solaris_unimplemented: ba,pt %xcc, ret_from_solaris nop - .section __ex_table,#alloc + .section __ex_table,"a" .align 4 .word exen, exenf diff --git a/arch/v850/kernel/process.c b/arch/v850/kernel/process.c index eb909937958b..621111ddf907 100644 --- a/arch/v850/kernel/process.c +++ b/arch/v850/kernel/process.c @@ -30,6 +30,9 @@ #include #include +void (*pm_power_off)(void) = NULL; +EXPORT_SYMBOL(pm_power_off); + extern void ret_from_fork (void); diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c index 89fab51e20f4..25ac8a3faae6 100644 --- a/arch/x86_64/kernel/machine_kexec.c +++ b/arch/x86_64/kernel/machine_kexec.c @@ -140,7 +140,7 @@ static void load_segments(void) "\tmovl %0,%%ss\n" "\tmovl %0,%%fs\n" "\tmovl %0,%%gs\n" - : : "a" (__KERNEL_DS) + : : "a" (__KERNEL_DS) : "memory" ); } diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 7ee4a14ec3b1..e90ef5db8913 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -26,6 +26,10 @@ config GENERIC_HARDIRQS bool default y +config RWSEM_GENERIC_SPINLOCK + bool + default y + source "init/Kconfig" menu "Processor type and features" diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index f1f596644bfc..64a649eb883f 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -64,6 +64,9 @@ EXPORT_SYMBOL(init_task); struct task_struct *current_set[NR_CPUS] = {&init_task, }; +void (*pm_power_off)(void) = NULL; +EXPORT_SYMBOL(pm_power_off); + #if XCHAL_CP_NUM > 0 diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 03d9c82b0fe7..0ef2971a9e82 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -625,26 +625,31 @@ static inline int ordered_bio_endio(struct request *rq, struct bio *bio, * Different hardware can have different requirements as to what pages * it can do I/O directly to. A low level driver can call * blk_queue_bounce_limit to have lower memory pages allocated as bounce - * buffers for doing I/O to pages residing above @page. By default - * the block layer sets this to the highest numbered "low" memory page. + * buffers for doing I/O to pages residing above @page. **/ void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr) { unsigned long bounce_pfn = dma_addr >> PAGE_SHIFT; + int dma = 0; - /* - * set appropriate bounce gfp mask -- unfortunately we don't have a - * full 4GB zone, so we have to resort to low memory for any bounces. - * ISA has its own < 16MB zone. - */ - if (bounce_pfn < blk_max_low_pfn) { - BUG_ON(dma_addr < BLK_BOUNCE_ISA); + q->bounce_gfp = GFP_NOIO; +#if BITS_PER_LONG == 64 + /* Assume anything <= 4GB can be handled by IOMMU. + Actually some IOMMUs can handle everything, but I don't + know of a way to test this here. */ + if (bounce_pfn < (0xffffffff>>PAGE_SHIFT)) + dma = 1; + q->bounce_pfn = max_low_pfn; +#else + if (bounce_pfn < blk_max_low_pfn) + dma = 1; + q->bounce_pfn = bounce_pfn; +#endif + if (dma) { init_emergency_isa_pool(); q->bounce_gfp = GFP_NOIO | GFP_DMA; - } else - q->bounce_gfp = GFP_NOIO; - - q->bounce_pfn = bounce_pfn; + q->bounce_pfn = bounce_pfn; + } } EXPORT_SYMBOL(blk_queue_bounce_limit); diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 14f6a6201da3..05983a312d50 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -555,7 +555,7 @@ fore200e_pca_reset(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_pca_map(struct fore200e* fore200e) { DPRINTK(2, "device %s being mapped in memory\n", fore200e->name); @@ -589,7 +589,7 @@ fore200e_pca_unmap(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_pca_configure(struct fore200e* fore200e) { struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev; @@ -2125,7 +2125,7 @@ fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags) } -static int __init +static int __devinit fore200e_irq_request(struct fore200e* fore200e) { if (request_irq(fore200e->irq, fore200e_interrupt, SA_SHIRQ, fore200e->name, fore200e->atm_dev) < 0) { @@ -2148,7 +2148,7 @@ fore200e_irq_request(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_get_esi(struct fore200e* fore200e) { struct prom_data* prom = fore200e_kmalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA); @@ -2180,7 +2180,7 @@ fore200e_get_esi(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_alloc_rx_buf(struct fore200e* fore200e) { int scheme, magn, nbr, size, i; @@ -2245,7 +2245,7 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_init_bs_queue(struct fore200e* fore200e) { int scheme, magn, i; @@ -2308,7 +2308,7 @@ fore200e_init_bs_queue(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_init_rx_queue(struct fore200e* fore200e) { struct host_rxq* rxq = &fore200e->host_rxq; @@ -2368,7 +2368,7 @@ fore200e_init_rx_queue(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_init_tx_queue(struct fore200e* fore200e) { struct host_txq* txq = &fore200e->host_txq; @@ -2431,7 +2431,7 @@ fore200e_init_tx_queue(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_init_cmd_queue(struct fore200e* fore200e) { struct host_cmdq* cmdq = &fore200e->host_cmdq; @@ -2487,7 +2487,7 @@ fore200e_param_bs_queue(struct fore200e* fore200e, } -static int __init +static int __devinit fore200e_initialize(struct fore200e* fore200e) { struct cp_queues __iomem * cpq; @@ -2539,7 +2539,7 @@ fore200e_initialize(struct fore200e* fore200e) } -static void __init +static void __devinit fore200e_monitor_putc(struct fore200e* fore200e, char c) { struct cp_monitor __iomem * monitor = fore200e->cp_monitor; @@ -2551,7 +2551,7 @@ fore200e_monitor_putc(struct fore200e* fore200e, char c) } -static int __init +static int __devinit fore200e_monitor_getc(struct fore200e* fore200e) { struct cp_monitor __iomem * monitor = fore200e->cp_monitor; @@ -2576,7 +2576,7 @@ fore200e_monitor_getc(struct fore200e* fore200e) } -static void __init +static void __devinit fore200e_monitor_puts(struct fore200e* fore200e, char* str) { while (*str) { @@ -2591,7 +2591,7 @@ fore200e_monitor_puts(struct fore200e* fore200e, char* str) } -static int __init +static int __devinit fore200e_start_fw(struct fore200e* fore200e) { int ok; @@ -2622,7 +2622,7 @@ fore200e_start_fw(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_load_fw(struct fore200e* fore200e) { u32* fw_data = (u32*) fore200e->bus->fw_data; @@ -2648,7 +2648,7 @@ fore200e_load_fw(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_register(struct fore200e* fore200e) { struct atm_dev* atm_dev; @@ -2675,7 +2675,7 @@ fore200e_register(struct fore200e* fore200e) } -static int __init +static int __devinit fore200e_init(struct fore200e* fore200e) { if (fore200e_register(fore200e) < 0) @@ -2721,7 +2721,7 @@ fore200e_init(struct fore200e* fore200e) return -EBUSY; fore200e_supply(fore200e); - + /* all done, board initialization is now complete */ fore200e->state = FORE200E_STATE_COMPLETE; return 0; diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 6ede1f352c29..37b8cda3e8bc 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include "DAC960.h" @@ -3463,7 +3464,7 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command, Command->SegmentCount, Command->DmaDirection); if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) { - + add_disk_randomness(Request->rq_disk); end_that_request_last(Request, UpToDate); if (Command->Completion) { diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c index b3bc2e37e616..29dc87e59020 100644 --- a/drivers/char/hw_random.c +++ b/drivers/char/hw_random.c @@ -131,7 +131,9 @@ enum { rng_hw_none, rng_hw_intel, rng_hw_amd, +#ifdef __i386__ rng_hw_via, +#endif rng_hw_geode, }; diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index c92378121b4c..1b05fa688996 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -675,7 +675,7 @@ static int __init mmtimer_init(void) cnodeid_t node, maxn = -1; if (!ia64_platform_is("sn2")) - return -1; + return 0; /* * Sanity check the cycles/sec variable diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 649677b5dc36..5fdf18515433 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -13,11 +13,12 @@ * * (C) 2000,2001,2002,2003,2004 Omnikey AG * - * (C) 2005 Harald Welte + * (C) 2005-2006 Harald Welte * - Adhere to Kernel CodingStyle * - Port to 2.6.13 "new" style PCMCIA * - Check for copy_{from,to}_user return values * - Use nonseekable_open() + * - add class interface for udev device creation * * All rights reserved. Licensed under dual BSD/GPL license. */ @@ -56,7 +57,7 @@ module_param(pc_debug, int, 0600); #else #define DEBUGP(n, rdr, x, args...) #endif -static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte"; +static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte"; #define T_1SEC (HZ) #define T_10MSEC msecs_to_jiffies(10) @@ -156,6 +157,7 @@ struct cm4000_dev { /*queue*/ 4*sizeof(wait_queue_head_t)) static dev_link_t *dev_table[CM4000_MAX_DEV]; +static struct class *cmm_class; /* This table doesn't use spaces after the comma between fields and thus * violates CodingStyle. However, I don't really think wrapping it around will @@ -1937,6 +1939,9 @@ static int cm4000_attach(struct pcmcia_device *p_dev) link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; cm4000_config(link, i); + class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, + "cmm%d", i); + return 0; } @@ -1962,6 +1967,8 @@ static void cm4000_detach(struct pcmcia_device *p_dev) dev_table[devno] = NULL; kfree(dev); + class_device_destroy(cmm_class, MKDEV(major, devno)); + return; } @@ -1995,8 +2002,18 @@ static struct pcmcia_driver cm4000_driver = { static int __init cmm_init(void) { + int rc; + printk(KERN_INFO "%s\n", version); - pcmcia_register_driver(&cm4000_driver); + + cmm_class = class_create(THIS_MODULE, "cardman_4000"); + if (!cmm_class) + return -1; + + rc = pcmcia_register_driver(&cm4000_driver); + if (rc < 0) + return rc; + major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); if (major < 0) { printk(KERN_WARNING MODULE_NAME @@ -2012,6 +2029,7 @@ static void __exit cmm_exit(void) printk(KERN_INFO MODULE_NAME ": unloading\n"); pcmcia_unregister_driver(&cm4000_driver); unregister_chrdev(major, DEVICE_NAME); + class_destroy(cmm_class); }; module_init(cmm_init); diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 46eb371bf17e..466e33bab029 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -3,12 +3,13 @@ * * (c) 2000-2004 Omnikey AG (http://www.omnikey.com/) * - * (C) 2005 Harald Welte + * (C) 2005-2006 Harald Welte * - add support for poll() * - driver cleanup * - add waitqueues * - adhere to linux kernel coding style and policies * - support 2.6.13 "new style" pcmcia interface + * - add class interface for udev device creation * * The device basically is a USB CCID compliant device that has been * attached to an I/O-Mapped FIFO. @@ -53,7 +54,7 @@ module_param(pc_debug, int, 0600); #endif static char *version = -"OMNIKEY CardMan 4040 v1.1.0gm4 - All bugs added by Harald Welte"; +"OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte"; #define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ) #define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ) @@ -67,6 +68,7 @@ static char *version = static void reader_release(dev_link_t *link); static int major; +static struct class *cmx_class; #define BS_READABLE 0x01 #define BS_WRITABLE 0x02 @@ -696,6 +698,9 @@ static int reader_attach(struct pcmcia_device *p_dev) link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; reader_config(link, i); + class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, + "cmx%d", i); + return 0; } @@ -721,6 +726,8 @@ static void reader_detach(struct pcmcia_device *p_dev) dev_table[devno] = NULL; kfree(dev); + class_device_destroy(cmx_class, MKDEV(major, devno)); + return; } @@ -755,8 +762,17 @@ static struct pcmcia_driver reader_driver = { static int __init cm4040_init(void) { + int rc; + printk(KERN_INFO "%s\n", version); - pcmcia_register_driver(&reader_driver); + cmx_class = class_create(THIS_MODULE, "cardman_4040"); + if (!cmx_class) + return -1; + + rc = pcmcia_register_driver(&reader_driver); + if (rc < 0) + return rc; + major = register_chrdev(0, DEVICE_NAME, &reader_fops); if (major < 0) { printk(KERN_WARNING MODULE_NAME @@ -771,6 +787,7 @@ static void __exit cm4040_exit(void) printk(KERN_INFO MODULE_NAME ": unloading\n"); pcmcia_unregister_driver(&reader_driver); unregister_chrdev(major, DEVICE_NAME); + class_destroy(cmx_class); } module_init(cm4040_init); diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 18a455651121..52f3eb45d2b9 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -6,17 +6,29 @@ # $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $ # -menu 'EDAC - error detection and reporting (RAS)' +menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)' config EDAC - tristate "EDAC core system error reporting" - depends on X86 + tristate "EDAC core system error reporting (EXPERIMENTAL)" + depends on X86 && EXPERIMENTAL help EDAC is designed to report errors in the core system. These are low-level errors that are reported in the CPU or supporting chipset: memory errors, cache errors, PCI errors, thermal throttling, etc.. If unsure, select 'Y'. + If this code is reporting problems on your system, please + see the EDAC project web pages for more information at: + + + + and: + + + + There is also a mailing list for the EDAC project, which can + be found via the sourceforge page. + comment "Reporting subsystems" depends on EDAC diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index b10ee4698b1d..262e44544dc8 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -132,11 +132,13 @@ static struct kobject edac_pci_kobj; * /sys/devices/system/edac/mc; * data structures and methods */ +#if 0 static ssize_t memctrl_string_show(void *ptr, char *buffer) { char *value = (char*) ptr; return sprintf(buffer, "%s\n", value); } +#endif static ssize_t memctrl_int_show(void *ptr, char *buffer) { @@ -207,7 +209,9 @@ struct memctrl_dev_attribute attr_##_name = { \ }; /* cwrow attribute f*/ +#if 0 MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL); +#endif /* csrow control files */ MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); @@ -222,7 +226,6 @@ static struct memctrl_dev_attribute *memctrl_attr[] = { &attr_log_ue, &attr_log_ce, &attr_poll_msec, - &attr_mc_version, NULL, }; @@ -309,6 +312,8 @@ struct list_control { int *count; }; + +#if 0 /* Output the list as: vendor_id:device:id<,vendor_id:device_id> */ static ssize_t edac_pci_list_string_show(void *ptr, char *buffer) { @@ -430,6 +435,7 @@ static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer, return count; } +#endif static ssize_t edac_pci_int_show(void *ptr, char *buffer) { int *value = ptr; @@ -498,6 +504,7 @@ struct edac_pci_dev_attribute edac_pci_attr_##_name = { \ .store = _store, \ }; +#if 0 static struct list_control pci_whitelist_control = { .list = pci_whitelist, .count = &pci_whitelist_count @@ -520,6 +527,7 @@ EDAC_PCI_STRING_ATTR(pci_parity_blacklist, S_IRUGO|S_IWUSR, edac_pci_list_string_show, edac_pci_list_string_store); +#endif /* PCI Parity control files */ EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store); @@ -531,8 +539,6 @@ static struct edac_pci_dev_attribute *edac_pci_attr[] = { &edac_pci_attr_check_pci_parity, &edac_pci_attr_panic_on_pci_parity, &edac_pci_attr_pci_parity_count, - &edac_pci_attr_pci_parity_whitelist, - &edac_pci_attr_pci_parity_blacklist, NULL, }; diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 8ed6ddbb9c5d..4652512f7d1a 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -39,7 +39,7 @@ #include "dcdbas.h" #define DRIVER_NAME "dcdbas" -#define DRIVER_VERSION "5.6.0-1" +#define DRIVER_VERSION "5.6.0-2" #define DRIVER_DESCRIPTION "Dell Systems Management Base Driver" static struct platform_device *dcdbas_pdev; @@ -581,9 +581,13 @@ static int __init dcdbas_init(void) */ static void __exit dcdbas_exit(void) { - platform_device_unregister(dcdbas_pdev); + /* + * make sure functions that use dcdbas_pdev are called + * before platform_device_unregister + */ unregister_reboot_notifier(&dcdbas_reboot_nb); smi_data_buf_free(); + platform_device_unregister(dcdbas_pdev); } module_init(dcdbas_init); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 4c2af9020905..6213bd3caee5 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -445,6 +445,7 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), + PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 2d2d4ac3525a..960dae5c87d1 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1155,6 +1155,12 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func) spin_lock_irq(target->scsi_host->host_lock); + if (target->state == SRP_TARGET_DEAD || + target->state == SRP_TARGET_REMOVED) { + scmnd->result = DID_BAD_TARGET << 16; + goto out; + } + if (scmnd->host_scribble == (void *) -1L) goto out; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 19b1b0121726..ad6217467676 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -58,7 +58,7 @@ static unsigned int psmouse_resetafter = 5; module_param_named(resetafter, psmouse_resetafter, uint, 0644); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); -static unsigned int psmouse_resync_time = 5; +static unsigned int psmouse_resync_time; module_param_named(resync_time, psmouse_resync_time, uint, 0644); MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never)."); diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 8159bcecd0c2..df9d65201819 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1929,6 +1929,8 @@ static struct pci_device_id hisax_pci_tbl[] __initdata = { {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B700, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B701, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, PCI_ANY_ID, PCI_ANY_ID}, diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 4866fc32d8d9..91d25acb5ede 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -51,6 +51,8 @@ static const PCI_ENTRY id_list[] = {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"}, {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"}, {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B700, "Primux II S0", "B700"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B701, "Primux II S0 NT", "B701"}, {PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"}, {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"}, {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"}, diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c index ca5b4a3b683e..262c44127419 100644 --- a/drivers/isdn/hisax/hfc_usb.c +++ b/drivers/isdn/hisax/hfc_usb.c @@ -1,7 +1,7 @@ /* * hfc_usb.c * - * $Id: hfc_usb.c,v 4.36 2005/04/08 09:55:13 martinb1 Exp $ + * $Id: hfc_usb.c,v 2.3.2.13 2006/02/17 17:17:22 mbachem Exp $ * * modular HiSax ISDN driver for Colognechip HFC-S USB chip * @@ -45,7 +45,7 @@ #include "hfc_usb.h" static const char *hfcusb_revision = - "$Revision: 4.36 $ $Date: 2005/04/08 09:55:13 $ "; + "$Revision: 2.3.2.13 $ $Date: 2006/02/17 17:17:22 $ "; /* Hisax debug support * use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG @@ -219,7 +219,7 @@ symbolic(struct hfcusb_symbolic_list list[], const int num) for (i = 0; list[i].name != NULL; i++) if (list[i].num == num) return (list[i].name); - return ""; + return ""; } @@ -235,9 +235,9 @@ ctrl_start_transfer(hfcusb_data * hfc) hfc->ctrl_urb->transfer_buffer = NULL; hfc->ctrl_urb->transfer_buffer_length = 0; hfc->ctrl_write.wIndex = - hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg; + cpu_to_le16(hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg); hfc->ctrl_write.wValue = - hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val; + cpu_to_le16(hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val); usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC); /* start transfer */ } @@ -1282,7 +1282,7 @@ usb_init(hfcusb_data * hfc) /* init the background machinery for control requests */ hfc->ctrl_read.bRequestType = 0xc0; hfc->ctrl_read.bRequest = 1; - hfc->ctrl_read.wLength = 1; + hfc->ctrl_read.wLength = cpu_to_le16(1); hfc->ctrl_write.bRequestType = 0x40; hfc->ctrl_write.bRequest = 0; hfc->ctrl_write.wLength = 0; @@ -1373,9 +1373,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) vend_idx = 0xffff; for (i = 0; hfcusb_idtab[i].idVendor; i++) { - if (dev->descriptor.idVendor == hfcusb_idtab[i].idVendor - && dev->descriptor.idProduct == - hfcusb_idtab[i].idProduct) { + if ((le16_to_cpu(dev->descriptor.idVendor) == hfcusb_idtab[i].idVendor) + && (le16_to_cpu(dev->descriptor.idProduct) == hfcusb_idtab[i].idProduct)) { vend_idx = i; continue; } @@ -1516,8 +1515,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_transfer_mode = USB_INT; packet_size = - ep->desc. - wMaxPacketSize; + le16_to_cpu(ep->desc.wMaxPacketSize); break; case USB_ENDPOINT_XFER_BULK: if (ep_addr & 0x80) @@ -1545,8 +1543,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_transfer_mode = USB_BULK; packet_size = - ep->desc. - wMaxPacketSize; + le16_to_cpu(ep->desc.wMaxPacketSize); break; case USB_ENDPOINT_XFER_ISOC: if (ep_addr & 0x80) @@ -1574,8 +1571,7 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_transfer_mode = USB_ISOC; iso_packet_size = - ep->desc. - wMaxPacketSize; + le16_to_cpu(ep->desc.wMaxPacketSize); break; default: context-> @@ -1588,10 +1584,8 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) fifonum = cidx; context->fifos[cidx].hfc = context; - context->fifos[cidx]. - usb_packet_maxlen = - ep->desc. - wMaxPacketSize; + context->fifos[cidx].usb_packet_maxlen = + le16_to_cpu(ep->desc.wMaxPacketSize); context->fifos[cidx]. intervall = ep->desc.bInterval; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 393633681f49..aeaa1db74bd8 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1682,6 +1682,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n"); #endif + module_put(info->owner); return; } info->flags |= ISDN_ASYNC_CLOSING; diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index bb8d5efe19bf..6c0ba04bc57a 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c @@ -35,6 +35,8 @@ #include #include +#include + #include "windfarm.h" #define VERSION "0.2" @@ -465,6 +467,11 @@ static int __init windfarm_core_init(void) { DBG("wf: core loaded\n"); + /* Don't register on old machines that use therm_pm72 for now */ + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) + return -ENODEV; platform_device_register(&wf_platform_device); return 0; } diff --git a/drivers/macintosh/windfarm_cpufreq_clamp.c b/drivers/macintosh/windfarm_cpufreq_clamp.c index 607dbaca69c9..81337cd16e80 100644 --- a/drivers/macintosh/windfarm_cpufreq_clamp.c +++ b/drivers/macintosh/windfarm_cpufreq_clamp.c @@ -8,6 +8,8 @@ #include #include +#include + #include "windfarm.h" #define VERSION "0.3" @@ -74,6 +76,12 @@ static int __init wf_cpufreq_clamp_init(void) { struct wf_control *clamp; + /* Don't register on old machines that use therm_pm72 for now */ + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) + return -ENODEV; + clamp = kmalloc(sizeof(struct wf_control), GFP_KERNEL); if (clamp == NULL) return -ENOMEM; diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index 906d3ecae6e6..423bfa2432c0 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -25,7 +25,7 @@ #include "windfarm.h" -#define VERSION "0.1" +#define VERSION "0.2" #undef DEBUG @@ -113,6 +113,7 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, const char *loc) { struct wf_lm75_sensor *lm; + int rc; DBG("wf_lm75: creating %s device at address 0x%02x\n", ds1775 ? "ds1775" : "lm75", addr); @@ -139,9 +140,11 @@ static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, lm->i2c.driver = &wf_lm75_driver; strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1); - if (i2c_attach_client(&lm->i2c)) { - printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n", - ds1775 ? "ds1775" : "lm75", lm->i2c.name); + rc = i2c_attach_client(&lm->i2c); + if (rc) { + printk(KERN_ERR "windfarm: failed to attach %s %s to i2c," + " err %d\n", ds1775 ? "ds1775" : "lm75", + lm->i2c.name, rc); goto fail; } @@ -175,16 +178,22 @@ static int wf_lm75_attach(struct i2c_adapter *adapter) (dev = of_get_next_child(busnode, dev)) != NULL;) { const char *loc = get_property(dev, "hwsensor-location", NULL); - u32 *reg = (u32 *)get_property(dev, "reg", NULL); - DBG(" dev: %s... (loc: %p, reg: %p)\n", dev->name, loc, reg); - if (loc == NULL || reg == NULL) + u8 addr; + + /* We must re-match the adapter in order to properly check + * the channel on multibus setups + */ + if (!pmac_i2c_match_adapter(dev, adapter)) + continue; + addr = pmac_i2c_get_dev_addr(dev); + if (loc == NULL || addr == 0) continue; /* real lm75 */ if (device_is_compatible(dev, "lm75")) - wf_lm75_create(adapter, *reg, 0, loc); + wf_lm75_create(adapter, addr, 0, loc); /* ds1775 (compatible, better resolution */ else if (device_is_compatible(dev, "ds1775")) - wf_lm75_create(adapter, *reg, 1, loc); + wf_lm75_create(adapter, addr, 1, loc); } return 0; } @@ -206,6 +215,11 @@ static int wf_lm75_detach(struct i2c_client *client) static int __init wf_lm75_sensor_init(void) { + /* Don't register on old machines that use therm_pm72 for now */ + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) + return -ENODEV; return i2c_add_driver(&wf_lm75_driver); } diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index 5b9ad6ca7cba..8e99d408fddd 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -17,7 +17,7 @@ #include "windfarm.h" -#define VERSION "0.1" +#define VERSION "0.2" /* This currently only exports the external temperature sensor, since that's all the control loops need. */ @@ -81,7 +81,7 @@ static struct wf_sensor_ops wf_max6690_ops = { static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr) { struct wf_6690_sensor *max; - char *name = "u4-temp"; + char *name = "backside-temp"; max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); if (max == NULL) { @@ -118,7 +118,6 @@ static int wf_max6690_attach(struct i2c_adapter *adapter) struct device_node *busnode, *dev = NULL; struct pmac_i2c_bus *bus; const char *loc; - u32 *reg; bus = pmac_i2c_adapter_to_bus(adapter); if (bus == NULL) @@ -126,16 +125,23 @@ static int wf_max6690_attach(struct i2c_adapter *adapter) busnode = pmac_i2c_get_bus_node(bus); while ((dev = of_get_next_child(busnode, dev)) != NULL) { + u8 addr; + + /* We must re-match the adapter in order to properly check + * the channel on multibus setups + */ + if (!pmac_i2c_match_adapter(dev, adapter)) + continue; if (!device_is_compatible(dev, "max6690")) continue; + addr = pmac_i2c_get_dev_addr(dev); loc = get_property(dev, "hwsensor-location", NULL); - reg = (u32 *) get_property(dev, "reg", NULL); - if (!loc || !reg) + if (loc == NULL || addr == 0) continue; - printk("found max6690, loc=%s reg=%x\n", loc, *reg); + printk("found max6690, loc=%s addr=0x%02x\n", loc, addr); if (strcmp(loc, "BACKSIDE")) continue; - wf_max6690_create(adapter, *reg); + wf_max6690_create(adapter, addr); } return 0; @@ -153,6 +159,11 @@ static int wf_max6690_detach(struct i2c_client *client) static int __init wf_max6690_sensor_init(void) { + /* Don't register on old machines that use therm_pm72 for now */ + if (machine_is_compatible("PowerMac7,2") || + machine_is_compatible("PowerMac7,3") || + machine_is_compatible("RackMac3,1")) + return -ENODEV; return i2c_add_driver(&wf_max6690_driver); } diff --git a/drivers/macintosh/windfarm_pid.c b/drivers/macintosh/windfarm_pid.c index 0842432e27ad..f10efb28cae4 100644 --- a/drivers/macintosh/windfarm_pid.c +++ b/drivers/macintosh/windfarm_pid.c @@ -143,3 +143,7 @@ s32 wf_cpu_pid_run(struct wf_cpu_pid_state *st, s32 new_power, s32 new_temp) return st->target; } EXPORT_SYMBOL_GPL(wf_cpu_pid_run); + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("PID algorithm for PowerMacs thermal control"); +MODULE_LICENSE("GPL"); diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c index c2a4e689c784..ef66bf2778ec 100644 --- a/drivers/macintosh/windfarm_pm112.c +++ b/drivers/macintosh/windfarm_pm112.c @@ -358,6 +358,7 @@ static void backside_fan_tick(void) return; if (!backside_tick) { /* first time; initialize things */ + printk(KERN_INFO "windfarm: Backside control loop started.\n"); backside_param.min = backside_fan->ops->get_min(backside_fan); backside_param.max = backside_fan->ops->get_max(backside_fan); wf_pid_init(&backside_pid, &backside_param); @@ -407,6 +408,7 @@ static void drive_bay_fan_tick(void) return; if (!drive_bay_tick) { /* first time; initialize things */ + printk(KERN_INFO "windfarm: Drive bay control loop started.\n"); drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan); drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan); wf_pid_init(&drive_bay_pid, &drive_bay_prm); @@ -458,6 +460,7 @@ static void slots_fan_tick(void) return; if (!slots_started) { /* first time; initialize things */ + printk(KERN_INFO "windfarm: Slots control loop started.\n"); wf_pid_init(&slots_pid, &slots_param); slots_started = 1; } @@ -504,6 +507,7 @@ static void pm112_tick(void) if (!started) { started = 1; + printk(KERN_INFO "windfarm: CPUs control loops started.\n"); for (i = 0; i < nr_cores; ++i) { if (create_cpu_loop(i) < 0) { failure_state = FAILURE_PERM; @@ -594,8 +598,6 @@ static void pm112_new_sensor(struct wf_sensor *sr) { unsigned int i; - if (have_all_sensors) - return; if (!strncmp(sr->name, "cpu-temp-", 9)) { i = sr->name[9] - '0'; if (sr->name[10] == 0 && i < NR_CORES && @@ -613,7 +615,7 @@ static void pm112_new_sensor(struct wf_sensor *sr) } else if (!strcmp(sr->name, "slots-power")) { if (slots_power == NULL && wf_get_sensor(sr) == 0) slots_power = sr; - } else if (!strcmp(sr->name, "u4-temp")) { + } else if (!strcmp(sr->name, "backside-temp")) { if (u4_temp == NULL && wf_get_sensor(sr) == 0) u4_temp = sr; } else diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d39f584cd8b3..5d88329e3c7a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -306,6 +306,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state); conf_t *conf = mddev_to_conf(r1_bio->mddev); + struct bio *to_put = NULL; if (bio->bi_size) return 1; @@ -323,6 +324,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int * this branch is our 'one mirror IO has finished' event handler: */ r1_bio->bios[mirror] = NULL; + to_put = bio; if (!uptodate) { md_error(r1_bio->mddev, conf->mirrors[mirror].rdev); /* an I/O failed, we can't clear the bitmap */ @@ -375,7 +377,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int /* Don't dec_pending yet, we want to hold * the reference over the retry */ - return 0; + goto out; } if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { /* free extra copy of the data pages */ @@ -392,10 +394,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int raid_end_bio_io(r1_bio); } - if (r1_bio->bios[mirror]==NULL) - bio_put(bio); - rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); + out: + if (to_put) + bio_put(to_put); + return 0; } @@ -857,7 +860,7 @@ static int make_request(request_queue_t *q, struct bio * bio) atomic_set(&r1_bio->remaining, 0); atomic_set(&r1_bio->behind_remaining, 0); - do_barriers = bio->bi_rw & BIO_RW_BARRIER; + do_barriers = bio_barrier(bio); if (do_barriers) set_bit(R1BIO_Barrier, &r1_bio->state); diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 390cc3a99ce6..9c7f122826e0 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -526,7 +526,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address); } else /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ - if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { ops = fc->fe->ops; ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd; diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c index 34c3189a1a33..356f447ee2ab 100644 --- a/drivers/media/dvb/bt8xx/bt878.c +++ b/drivers/media/dvb/bt8xx/bt878.c @@ -382,7 +382,7 @@ bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet * EXPORT_SYMBOL(bt878_device_control); -struct cards card_list[] __devinitdata = { +static struct cards card_list[] __devinitdata = { { 0x01010071, BTTV_BOARD_NEBULA_DIGITV, "Nebula Electronics DigiTV" }, { 0x07611461, BTTV_BOARD_AVDVBT_761, "AverMedia AverTV DVB-T 761" }, diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 3a2ff1cc24b7..0310e3dd07e6 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -602,7 +602,7 @@ static int dst_type_print(u8 type) */ -struct dst_types dst_tlist[] = { +static struct dst_types dst_tlist[] = { { .device_id = "200103A", .offset = 0, diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h index 9f025825b2d2..0c1d87c5227a 100644 --- a/drivers/media/dvb/dvb-core/demux.h +++ b/drivers/media/dvb/dvb-core/demux.h @@ -216,7 +216,7 @@ struct dmx_frontend { /*--------------------------------------------------------------------------*/ /* - * Flags OR'ed in the capabilites field of struct dmx_demux. + * Flags OR'ed in the capabilities field of struct dmx_demux. */ #define DMX_TS_FILTERING 1 diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index f327fac1688e..162f9795cd89 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -282,7 +282,7 @@ static struct cx22702_config cxusb_cx22702_config = { .pll_set = dvb_usb_pll_set_i2c, }; -static struct lgdt330x_config cxusb_lgdt330x_config = { +static struct lgdt330x_config cxusb_lgdt3303_config = { .demod_address = 0x0e, .demod_chip = LGDT3303, .pll_set = dvb_usb_pll_set_i2c, @@ -357,14 +357,14 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d) return -EIO; } -static int cxusb_lgdt330x_frontend_attach(struct dvb_usb_device *d) +static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d) { if (usb_set_interface(d->udev,0,7) < 0) err("set interface failed"); cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); - if ((d->fe = lgdt330x_attach(&cxusb_lgdt330x_config, &d->i2c_adap)) != NULL) + if ((d->fe = lgdt330x_attach(&cxusb_lgdt3303_config, &d->i2c_adap)) != NULL) return 0; return -EIO; @@ -506,7 +506,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = { .streaming_ctrl = cxusb_streaming_ctrl, .power_ctrl = cxusb_power_ctrl, - .frontend_attach = cxusb_lgdt330x_frontend_attach, + .frontend_attach = cxusb_lgdt3303_frontend_attach, .tuner_attach = cxusb_lgh064f_tuner_attach, .i2c_algo = &cxusb_i2c_algo, diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c index 716f8bf528cd..ce34a55e5c24 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c @@ -47,7 +47,7 @@ static int dvb_usb_init(struct dvb_usb_device *d) d->state = DVB_USB_STATE_INIT; -/* check the capabilites and set appropriate variables */ +/* check the capabilities and set appropriate variables */ /* speed - when running at FULL speed we need a HW PID filter */ if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) { diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 5e5d21ad93c9..d4909e5c67e0 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -87,7 +87,7 @@ struct dvb_usb_device; /** * struct dvb_usb_properties - properties of a dvb-usb-device - * @caps: capabilites of the DVB USB device. + * @caps: capabilities of the DVB USB device. * @pid_filter_count: number of PID filter position in the optional hardware * PID-filter. * diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 76b6a2aef32f..c676b1e23ab0 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -29,7 +29,7 @@ config DVB_TDA8083 A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_MT312 - tristate "Zarlink MT312 based" + tristate "Zarlink VP310/MT312 based" depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index ec4e641acc64..d3aea83cf218 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -612,76 +612,6 @@ static void mt312_release(struct dvb_frontend* fe) kfree(state); } -static struct dvb_frontend_ops vp310_mt312_ops; - -struct dvb_frontend* vp310_attach(const struct mt312_config* config, - struct i2c_adapter* i2c) -{ - struct mt312_state* state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); - if (state == NULL) - goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); - strcpy(state->ops.info.name, "Zarlink VP310 DVB-S"); - - /* check if the demod is there */ - if (mt312_readreg(state, ID, &state->id) < 0) - goto error; - if (state->id != ID_VP310) { - goto error; - } - - /* create dvb_frontend */ - state->frequency = 90; - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - -struct dvb_frontend* mt312_attach(const struct mt312_config* config, - struct i2c_adapter* i2c) -{ - struct mt312_state* state = NULL; - - /* allocate memory for the internal state */ - state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); - if (state == NULL) - goto error; - - /* setup the state */ - state->config = config; - state->i2c = i2c; - memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); - strcpy(state->ops.info.name, "Zarlink MT312 DVB-S"); - - /* check if the demod is there */ - if (mt312_readreg(state, ID, &state->id) < 0) - goto error; - if (state->id != ID_MT312) { - goto error; - } - - /* create dvb_frontend */ - state->frequency = 60; - state->frontend.ops = &state->ops; - state->frontend.demodulator_priv = state; - return &state->frontend; - -error: - kfree(state); - return NULL; -} - static struct dvb_frontend_ops vp310_mt312_ops = { .info = { @@ -720,6 +650,49 @@ static struct dvb_frontend_ops vp310_mt312_ops = { .set_voltage = mt312_set_voltage, }; +struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c) +{ + struct mt312_state* state = NULL; + + /* allocate memory for the internal state */ + state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL); + if (state == NULL) + goto error; + + /* setup the state */ + state->config = config; + state->i2c = i2c; + memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops)); + + /* check if the demod is there */ + if (mt312_readreg(state, ID, &state->id) < 0) + goto error; + + switch (state->id) { + case ID_VP310: + strcpy(state->ops.info.name, "Zarlink VP310 DVB-S"); + state->frequency = 90; + break; + case ID_MT312: + strcpy(state->ops.info.name, "Zarlink MT312 DVB-S"); + state->frequency = 60; + break; + default: + printk (KERN_WARNING "Only Zarlink VP310/MT312 are supported chips.\n"); + goto error; + } + + /* create dvb_frontend */ + state->frontend.ops = &state->ops; + state->frontend.demodulator_priv = state; + return &state->frontend; + +error: + kfree(state); + return NULL; +} + module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); @@ -727,5 +700,4 @@ MODULE_DESCRIPTION("Zarlink VP310/MT312 DVB-S Demodulator driver"); MODULE_AUTHOR("Andreas Oberritter "); MODULE_LICENSE("GPL"); -EXPORT_SYMBOL(mt312_attach); -EXPORT_SYMBOL(vp310_attach); +EXPORT_SYMBOL(vp310_mt312_attach); diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index b3a53a73a117..074d844f0139 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -38,10 +38,8 @@ struct mt312_config int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); }; -extern struct dvb_frontend* mt312_attach(const struct mt312_config* config, - struct i2c_adapter* i2c); +struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c); -extern struct dvb_frontend* vp310_attach(const struct mt312_config* config, - struct i2c_adapter* i2c); #endif // MT312_H diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c index 6122ba754bc5..eb15676d374f 100644 --- a/drivers/media/dvb/frontends/stv0297.c +++ b/drivers/media/dvb/frontends/stv0297.c @@ -393,10 +393,6 @@ static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_par break; case QAM_128: - delay = 150; - sweeprate = 1000; - break; - case QAM_256: delay = 200; sweeprate = 500; diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c index d36369e9e88f..7c6ccb96b157 100644 --- a/drivers/media/dvb/ttpci/av7110.c +++ b/drivers/media/dvb/ttpci/av7110.c @@ -1439,7 +1439,7 @@ static int check_firmware(struct av7110* av7110) len = ntohl(*(u32*) ptr); ptr += 4; if (len >= 512) { - printk("dvb-ttpci: dpram file is way to big.\n"); + printk("dvb-ttpci: dpram file is way too big.\n"); return -EINVAL; } if (crc != crc32_le(0, ptr, len)) { @@ -2477,7 +2477,8 @@ static int frontend_init(struct av7110 *av7110) * The same behaviour of missing VSYNC can be duplicated on budget * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble. */ -static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) +static int __devinit av7110_attach(struct saa7146_dev* dev, + struct saa7146_pci_extension_data *pci_ext) { const int length = TS_WIDTH * TS_HEIGHT; struct pci_dev *pdev = dev->pci; @@ -2827,7 +2828,7 @@ err_kfree_0: goto out; } -static int av7110_detach(struct saa7146_dev* saa) +static int __devexit av7110_detach(struct saa7146_dev* saa) { struct av7110 *av7110 = saa->ext_priv; dprintk(4, "%p\n", av7110); @@ -2974,7 +2975,7 @@ static struct saa7146_extension av7110_extension = { .module = THIS_MODULE, .pci_tbl = &pci_tbl[0], .attach = av7110_attach, - .detach = av7110_detach, + .detach = __devexit_p(av7110_detach), .irq_mask = MASK_19 | MASK_03 | MASK_10, .irq_func = av7110_irq, diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index b2e63e9fc053..0bb6e74ae7f0 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c @@ -245,6 +245,9 @@ int av7110_bootarm(struct av7110 *av7110) /* test DEBI */ iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4); + /* FIXME: Why does Nexus CA require 2x iwdebi for first init? */ + iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4); + if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) { printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: " "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n", diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c index 617e4f6c0ed7..d54bbcdde2cc 100644 --- a/drivers/media/dvb/ttpci/av7110_ir.c +++ b/drivers/media/dvb/ttpci/av7110_ir.c @@ -208,7 +208,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom) } -int __init av7110_ir_init(struct av7110 *av7110) +int __devinit av7110_ir_init(struct av7110 *av7110) { static struct proc_dir_entry *e; @@ -248,7 +248,7 @@ int __init av7110_ir_init(struct av7110 *av7110) } -void __exit av7110_ir_exit(struct av7110 *av7110) +void __devexit av7110_ir_exit(struct av7110 *av7110) { int i; diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index 9f59541155d9..85d964b5b33c 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c @@ -3369,7 +3369,7 @@ static int cpia_do_ioctl(struct inode *inode, struct file *file, //DBG("cpia_ioctl: %u\n", ioctlnr); switch (ioctlnr) { - /* query capabilites */ + /* query capabilities */ case VIDIOCGCAP: { struct video_capability *b = arg; diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 08ffd1f325fc..5588b9a5c430 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -567,7 +567,7 @@ static struct v4l2_queryctrl cx25840_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, @@ -576,7 +576,7 @@ static struct v4l2_queryctrl cx25840_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index 048d000941c7..ffd87ce55556 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1027,7 +1027,7 @@ static struct v4l2_queryctrl saa7115_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Contrast", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, @@ -1036,7 +1036,7 @@ static struct v4l2_queryctrl saa7115_qctrl[] = { .type = V4L2_CTRL_TYPE_INTEGER, .name = "Saturation", .minimum = 0, - .maximum = 255, + .maximum = 127, .step = 1, .default_value = 64, .flags = 0, diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index a7a6ab9298a9..7df5e0826e12 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -54,10 +54,12 @@ MODULE_PARM_DESC(debug,"enable debug messages [alsa]"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; +static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(index, int, NULL, 0444); +module_param_array(enable, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s)."); +MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s)."); #define dprintk(fmt, arg...) if (debug) \ printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ##arg) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 5a35d3b6550d..6bc63a4086c1 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -977,7 +977,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .inputs = {{ .name = name_tv, .vmux = 3, @@ -1666,7 +1666,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_ACTIVE, + .tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, @@ -2187,7 +2187,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = 0x61, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, @@ -2211,7 +2211,7 @@ struct saa7134_board saa7134_boards[] = { .radio_type = UNSET, .tuner_addr = 0x61, .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, + .tda9887_conf = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE, .mpeg = SAA7134_MPEG_DVB, .inputs = {{ .name = name_tv, @@ -2392,7 +2392,7 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_PINNACLE_PCTV_110i] = { - .name = "Pinnacle PCTV 110i (saa7133)", + .name = "Pinnacle PCTV 40i/50i/110i (saa7133)", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_TDA8290, .radio_type = UNSET, @@ -2407,6 +2407,10 @@ struct saa7134_board saa7134_boards[] = { },{ .name = name_comp1, .vmux = 1, + .amux = LINE2, + },{ + .name = name_comp2, + .vmux = 0, .amux = LINE2, },{ .name = name_svideo, @@ -2745,7 +2749,7 @@ struct pci_device_id saa7134_pci_tbl[] = { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1048, - .subdevice = 0x226b, + .subdevice = 0x226a, .driver_data = SAA7134_BOARD_ELSA_500TV, },{ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -3201,6 +3205,11 @@ 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); + 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); + saa_writeb(SAA7134_GPIO_GPSTATUS1, 0x80); + break; case SAA7134_BOARD_MONSTERTV_MOBILE: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 1a536e865277..9db8e13f21c3 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -110,6 +110,7 @@ static int mt352_pinnacle_init(struct dvb_frontend* fe) mt352_write(fe, fsm_ctl_cfg, sizeof(fsm_ctl_cfg)); mt352_write(fe, scan_ctl_cfg, sizeof(scan_ctl_cfg)); mt352_write(fe, irq_cfg, sizeof(irq_cfg)); + return 0; } @@ -117,8 +118,10 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf) { - static int on = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE; - static int off = TDA9887_PRESENT | TDA9887_PORT2_ACTIVE; + u8 off[] = { 0x00, 0xf1}; + u8 on[] = { 0x00, 0x71}; + struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)}; + struct saa7134_dev *dev = fe->dvb->priv; struct v4l2_frequency f; @@ -126,9 +129,10 @@ static int mt352_pinnacle_pll_set(struct dvb_frontend* fe, f.tuner = 0; f.type = V4L2_TUNER_DIGITAL_TV; f.frequency = params->frequency / 1000 * 16 / 1000; - saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&on); + i2c_transfer(&dev->i2c_adap, &msg, 1); saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f); - saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&off); + msg.buf = on; + i2c_transfer(&dev->i2c_adap, &msg, 1); pinnacle_antenna_pwr(dev, antenna_pwr); diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 7b4fb282ac82..a796a4e1917c 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -580,9 +580,10 @@ int tda8290_init(struct i2c_client *c) int tda8290_probe(struct i2c_client *c) { - unsigned char soft_reset[] = { 0x00, 0x00 }; - unsigned char easy_mode_b[] = { 0x01, 0x02 }; - unsigned char easy_mode_g[] = { 0x01, 0x04 }; + unsigned char soft_reset[] = { 0x00, 0x00 }; + unsigned char easy_mode_b[] = { 0x01, 0x02 }; + unsigned char easy_mode_g[] = { 0x01, 0x04 }; + unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 }; unsigned char addr_dto_lsb = 0x07; unsigned char data; @@ -599,6 +600,7 @@ int tda8290_probe(struct i2c_client *c) return 0; } } + i2c_master_send(c, restore_9886, 3); return -1; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index e7ee619d62c5..b6101bf446d4 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -713,8 +713,9 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) struct v4l2_frequency *f = arg; switch_v4l2(); - if (V4L2_TUNER_RADIO == f->type && - V4L2_TUNER_RADIO != t->mode) { + if ((V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) + || (V4L2_TUNER_DIGITAL_TV == f->type + && V4L2_TUNER_DIGITAL_TV != t->mode)) { if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") == EINVAL) return 0; diff --git a/drivers/media/video/videocodec.h b/drivers/media/video/videocodec.h index 156ae57096fe..b1239ac7f371 100644 --- a/drivers/media/video/videocodec.h +++ b/drivers/media/video/videocodec.h @@ -56,7 +56,7 @@ the slave is bound to it). Otherwise it doesn't need this functions and therfor they may not be initialized. - The other fuctions are just for convenience, as they are for shure used by + The other fuctions are just for convenience, as they are for sure used by most/all of the codecs. The last ones may be ommited, too. See the structure declaration below for more information and which data has diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index bd0cd28543ca..6699725be605 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -159,7 +159,7 @@ zr36050_wait_end (struct zr36050 *ptr) while (!(zr36050_read_status1(ptr) & 0x4)) { udelay(1); - if (i++ > 200000) { // 200ms, there is for shure something wrong!!! + if (i++ > 200000) { // 200ms, there is for sure something wrong!!! dprintk(1, "%s: timout at wait_end (last status: 0x%02x)\n", ptr->name, ptr->status1); diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index 28fa31a5f150..d8dd003a7aad 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -161,7 +161,7 @@ zr36060_wait_end (struct zr36060 *ptr) while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) { udelay(1); - if (i++ > 200000) { // 200ms, there is for shure something wrong!!! + if (i++ > 200000) { // 200ms, there is for sure something wrong!!! dprintk(1, "%s: timout at wait_end (last status: 0x%02x)\n", ptr->name, ptr->status); diff --git a/drivers/media/video/zr36120_i2c.c b/drivers/media/video/zr36120_i2c.c index 6bfe84d657f1..21fde43a6aed 100644 --- a/drivers/media/video/zr36120_i2c.c +++ b/drivers/media/video/zr36120_i2c.c @@ -65,7 +65,7 @@ void attach_inform(struct i2c_bus *bus, int id) case I2C_DRIVERID_VIDEODECODER: DEBUG(printk(CARD_INFO "decoder attached\n",CARD)); - /* fetch the capabilites of the decoder */ + /* fetch the capabilities of the decoder */ rv = i2c_control_device(&ztv->i2c, I2C_DRIVERID_VIDEODECODER, DECODER_GET_CAPABILITIES, &dc); if (rv) { DEBUG(printk(CARD_DEBUG "decoder is not V4L aware!\n",CARD)); diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index 1cef2387fa65..6aba41954448 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h @@ -101,15 +101,16 @@ struct command { static inline void command_put(struct command *cmd) { unsigned long flags; + spinlock_t *lock = cmd->lock; - spin_lock_irqsave(cmd->lock, flags); - kobject_put(&cmd->kobj); - spin_unlock_irqrestore(cmd->lock, flags); + spin_lock_irqsave(lock, flags); + kobject_put(&cmd->kobj); + spin_unlock_irqrestore(lock, flags); } static inline void command_get(struct command *cmd) { - kobject_get(&cmd->kobj); + kobject_get(&cmd->kobj); } diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 227c39a7c1b4..8d84b045bc83 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -194,7 +194,7 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); - switch (mmc_rsp_type(cmd->flags)) { + switch (mmc_resp_type(cmd)) { case MMC_RSP_R1: mmccmd |= SD_CMD_RT_1; break; @@ -740,7 +740,6 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios) static void au1xmmc_dma_callback(int irq, void *dev_id, struct pt_regs *regs) { struct au1xmmc_host *host = (struct au1xmmc_host *) dev_id; - u32 status; /* Avoid spurious interrupts */ @@ -887,7 +886,7 @@ struct mmc_host_ops au1xmmc_ops = { .set_ios = au1xmmc_set_ios, }; -static int au1xmmc_probe(struct device *dev) +static int __devinit au1xmmc_probe(struct platform_device *pdev) { int i, ret = 0; @@ -904,7 +903,7 @@ static int au1xmmc_probe(struct device *dev) disable_irq(AU1100_SD_IRQ); for(i = 0; i < AU1XMMC_CONTROLLER_COUNT; i++) { - struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), dev); + struct mmc_host *mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev); struct au1xmmc_host *host = 0; if (!mmc) { @@ -967,7 +966,7 @@ static int au1xmmc_probe(struct device *dev) return 0; } -static int au1xmmc_remove(struct device *dev) +static int __devexit au1xmmc_remove(struct platform_device *pdev) { int i; @@ -997,23 +996,24 @@ static int au1xmmc_remove(struct device *dev) return 0; } -static struct device_driver au1xmmc_driver = { - .name = DRIVER_NAME, - .bus = &platform_bus_type, +static struct platform_driver au1xmmc_driver = { .probe = au1xmmc_probe, .remove = au1xmmc_remove, .suspend = NULL, - .resume = NULL + .resume = NULL, + .driver = { + .name = DRIVER_NAME, + }, }; static int __init au1xmmc_init(void) { - return driver_register(&au1xmmc_driver); + return platform_driver_register(&au1xmmc_driver); } static void __exit au1xmmc_exit(void) { - driver_unregister(&au1xmmc_driver); + platform_driver_unregister(&au1xmmc_driver); } module_init(au1xmmc_init); diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c index d01b6a9198e0..8815c8dbef2d 100644 --- a/drivers/mtd/redboot.c +++ b/drivers/mtd/redboot.c @@ -1,5 +1,5 @@ /* - * $Id: redboot.c,v 1.18 2005/11/07 11:14:21 gleixner Exp $ + * $Id: redboot.c,v 1.19 2005/12/01 10:03:51 dwmw2 Exp $ * * Parse RedBoot-style Flash Image System (FIS) tables and * produce a Linux partition array to match. @@ -92,10 +92,10 @@ static int parse_redboot_partitions(struct mtd_info *master, if (!memcmp(buf[i].name, "FIS directory", 14)) { /* This is apparently the FIS directory entry for the * FIS directory itself. The FIS directory size is - * one erase block, if the buf[i].size field is + * one erase block; if the buf[i].size field is * swab32(erasesize) then we know we are looking at * a byte swapped FIS directory - swap all the entries! - * (NOTE: this is 'size' not 'data_length', size is + * (NOTE: this is 'size' not 'data_length'; size is * the full size of the entry.) */ if (swab32(buf[i].size) == master->erasesize) { @@ -104,15 +104,13 @@ static int parse_redboot_partitions(struct mtd_info *master, /* The unsigned long fields were written with the * wrong byte sex, name and pad have no byte sex. */ -# define do_swab32(x) (x) = swab32(x) - do_swab32(buf[j].flash_base); - do_swab32(buf[j].mem_base); - do_swab32(buf[j].size); - do_swab32(buf[j].entry_point); - do_swab32(buf[j].data_length); - do_swab32(buf[j].desc_cksum); - do_swab32(buf[j].file_cksum); -# undef do_swab32 + swab32s(&buf[j].flash_base); + swab32s(&buf[j].mem_base); + swab32s(&buf[j].size); + swab32s(&buf[j].entry_point); + swab32s(&buf[j].data_length); + swab32s(&buf[j].desc_cksum); + swab32s(&buf[j].file_cksum); } } break; diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c index 230642571c92..e824acaf188a 100644 --- a/drivers/net/chelsio/espi.c +++ b/drivers/net/chelsio/espi.c @@ -296,9 +296,7 @@ void t1_espi_destroy(struct peespi *espi) struct peespi *t1_espi_create(adapter_t *adapter) { - struct peespi *espi = kmalloc(sizeof(*espi), GFP_KERNEL); - - memset(espi, 0, sizeof(*espi)); + struct peespi *espi = kzalloc(sizeof(*espi), GFP_KERNEL); if (espi) espi->adapter = adapter; diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 27c77306193b..99baf0e099fc 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -225,9 +225,6 @@ struct e1000_rx_ring { struct e1000_ps_page *ps_page; struct e1000_ps_page_dma *ps_page_dma; - struct sk_buff *rx_skb_top; - struct sk_buff *rx_skb_prev; - /* cpu for rx queue */ int cpu; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 31e332935e5a..5b7d0f425af2 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -103,7 +103,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "6.3.9-k2"DRIVERNAPI +#define DRV_VERSION "6.3.9-k4"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation."; @@ -1635,8 +1635,6 @@ setup_rx_desc_die: rxdr->next_to_clean = 0; rxdr->next_to_use = 0; - rxdr->rx_skb_top = NULL; - rxdr->rx_skb_prev = NULL; return 0; } @@ -1713,8 +1711,23 @@ e1000_setup_rctl(struct e1000_adapter *adapter) rctl |= adapter->rx_buffer_len << 0x11; } else { rctl &= ~E1000_RCTL_SZ_4096; - rctl &= ~E1000_RCTL_BSEX; - rctl |= E1000_RCTL_SZ_2048; + rctl |= E1000_RCTL_BSEX; + switch (adapter->rx_buffer_len) { + case E1000_RXBUFFER_2048: + default: + rctl |= E1000_RCTL_SZ_2048; + rctl &= ~E1000_RCTL_BSEX; + break; + case E1000_RXBUFFER_4096: + rctl |= E1000_RCTL_SZ_4096; + break; + case E1000_RXBUFFER_8192: + rctl |= E1000_RCTL_SZ_8192; + break; + case E1000_RXBUFFER_16384: + rctl |= E1000_RCTL_SZ_16384; + break; + } } #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT @@ -2107,16 +2120,6 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter, } } - /* there also may be some cached data in our adapter */ - if (rx_ring->rx_skb_top) { - dev_kfree_skb(rx_ring->rx_skb_top); - - /* rx_skb_prev will be wiped out by rx_skb_top */ - rx_ring->rx_skb_top = NULL; - rx_ring->rx_skb_prev = NULL; - } - - size = sizeof(struct e1000_buffer) * rx_ring->count; memset(rx_ring->buffer_info, 0, size); size = sizeof(struct e1000_ps_page) * rx_ring->count; @@ -3106,24 +3109,27 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) break; } - /* since the driver code now supports splitting a packet across - * multiple descriptors, most of the fifo related limitations on - * jumbo frame traffic have gone away. - * simply use 2k descriptors for everything. - * - * NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN - * means we reserve 2 more, this pushes us to allocate from the next - * larger slab size - * i.e. RXBUFFER_2048 --> size-4096 slab */ - /* recent hardware supports 1KB granularity */ if (adapter->hw.mac_type > e1000_82547_rev_2) { - adapter->rx_buffer_len = - ((max_frame < E1000_RXBUFFER_2048) ? - max_frame : E1000_RXBUFFER_2048); + adapter->rx_buffer_len = max_frame; E1000_ROUNDUP(adapter->rx_buffer_len, 1024); - } else - adapter->rx_buffer_len = E1000_RXBUFFER_2048; + } else { + if(unlikely((adapter->hw.mac_type < e1000_82543) && + (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) { + DPRINTK(PROBE, ERR, "Jumbo Frames not supported " + "on 82542\n"); + return -EINVAL; + } else { + if(max_frame <= E1000_RXBUFFER_2048) + adapter->rx_buffer_len = E1000_RXBUFFER_2048; + else if(max_frame <= E1000_RXBUFFER_4096) + adapter->rx_buffer_len = E1000_RXBUFFER_4096; + else if(max_frame <= E1000_RXBUFFER_8192) + adapter->rx_buffer_len = E1000_RXBUFFER_8192; + else if(max_frame <= E1000_RXBUFFER_16384) + adapter->rx_buffer_len = E1000_RXBUFFER_16384; + } + } netdev->mtu = new_mtu; @@ -3620,7 +3626,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, uint8_t last_byte; unsigned int i; int cleaned_count = 0; - boolean_t cleaned = FALSE, multi_descriptor = FALSE; + boolean_t cleaned = FALSE; i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC(*rx_ring, i); @@ -3652,43 +3658,12 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); - skb_put(skb, length); - - if (!(status & E1000_RXD_STAT_EOP)) { - if (!rx_ring->rx_skb_top) { - rx_ring->rx_skb_top = skb; - rx_ring->rx_skb_top->len = length; - rx_ring->rx_skb_prev = skb; - } else { - if (skb_shinfo(rx_ring->rx_skb_top)->frag_list) { - rx_ring->rx_skb_prev->next = skb; - skb->prev = rx_ring->rx_skb_prev; - } else { - skb_shinfo(rx_ring->rx_skb_top)->frag_list = skb; - } - rx_ring->rx_skb_prev = skb; - rx_ring->rx_skb_top->data_len += length; - } + if (unlikely(!(status & E1000_RXD_STAT_EOP))) { + /* All receives must fit into a single buffer */ + E1000_DBG("%s: Receive packet consumed multiple" + " buffers\n", netdev->name); + dev_kfree_skb_irq(skb); goto next_desc; - } else { - if (rx_ring->rx_skb_top) { - if (skb_shinfo(rx_ring->rx_skb_top) - ->frag_list) { - rx_ring->rx_skb_prev->next = skb; - skb->prev = rx_ring->rx_skb_prev; - } else - skb_shinfo(rx_ring->rx_skb_top) - ->frag_list = skb; - - rx_ring->rx_skb_top->data_len += length; - rx_ring->rx_skb_top->len += - rx_ring->rx_skb_top->data_len; - - skb = rx_ring->rx_skb_top; - multi_descriptor = TRUE; - rx_ring->rx_skb_top = NULL; - rx_ring->rx_skb_prev = NULL; - } } if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { @@ -3712,10 +3687,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, * performance for small packets with large amounts * of reassembly being done in the stack */ #define E1000_CB_LENGTH 256 - if ((length < E1000_CB_LENGTH) && - !rx_ring->rx_skb_top && - /* or maybe (status & E1000_RXD_STAT_EOP) && */ - !multi_descriptor) { + if (length < E1000_CB_LENGTH) { struct sk_buff *new_skb = dev_alloc_skb(length + NET_IP_ALIGN); if (new_skb) { @@ -3729,7 +3701,8 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, skb = new_skb; skb_put(skb, length); } - } + } else + skb_put(skb, length); /* end copybreak code */ diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 01ddfc8cce3f..aa5581369399 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -806,6 +806,7 @@ static struct pcmcia_device_id axnet_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309), PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106), PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), + PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc), PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef), PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef), PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1), diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 49b597cbc19a..b7f00d6eb6a6 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -4092,6 +4092,7 @@ static void s2io_set_multicast(struct net_device *dev) i++, mclist = mclist->next) { memcpy(sp->usr_addrs[i].addr, mclist->dmi_addr, ETH_ALEN); + mac_addr = 0; for (j = 0; j < ETH_ALEN; j++) { mac_addr |= mclist->dmi_addr[j]; mac_addr <<= 8; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e8e92c853e89..15545620ab0e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -3532,9 +3532,23 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) (base + len + 8 < base)); } +/* Test for DMA addresses > 40-bit */ +static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping, + int len) +{ +#if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64) + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + return (((u64) mapping + len) > DMA_40BIT_MASK); + return 0; +#else + return 0; +#endif +} + static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); -static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, +/* Workaround 4GB and 40-bit hardware DMA bugs. */ +static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, u32 last_plus_one, u32 *start, u32 base_flags, u32 mss) { @@ -3742,6 +3756,9 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) if (tg3_4g_overflow_test(mapping, len)) would_hit_hwbug = 1; + if (tg3_40bit_overflow_test(tp, mapping, len)) + would_hit_hwbug = 1; + if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) tg3_set_txd(tp, entry, mapping, len, base_flags, (i == last)|(mss << 1)); @@ -3763,7 +3780,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) /* If the workaround fails due to memory/mapping * failure, silently drop this packet. */ - if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one, + if (tigon3_dma_hwbug_workaround(tp, skb, last_plus_one, &start, base_flags, mss)) goto out_unlock; @@ -10608,8 +10625,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, unsigned long tg3reg_base, tg3reg_len; struct net_device *dev; struct tg3 *tp; - int i, err, pci_using_dac, pm_cap; + int i, err, pm_cap; char str[40]; + u64 dma_mask, persist_dma_mask; if (tg3_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -10646,26 +10664,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_free_res; } - /* Configure DMA attributes. */ - err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (!err) { - pci_using_dac = 1; - err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (err < 0) { - printk(KERN_ERR PFX "Unable to obtain 64 bit DMA " - "for consistent allocations\n"); - goto err_out_free_res; - } - } else { - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - printk(KERN_ERR PFX "No usable DMA configuration, " - "aborting.\n"); - goto err_out_free_res; - } - pci_using_dac = 0; - } - tg3reg_base = pci_resource_start(pdev, 0); tg3reg_len = pci_resource_len(pdev, 0); @@ -10679,8 +10677,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_using_dac) - dev->features |= NETIF_F_HIGHDMA; dev->features |= NETIF_F_LLTX; #if TG3_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; @@ -10765,6 +10761,44 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } + /* 5714, 5715 and 5780 cannot support DMA addresses > 40-bit. + * On 64-bit systems with IOMMU, use 40-bit dma_mask. + * On 64-bit systems without IOMMU, use 64-bit dma_mask and + * do DMA address check in tg3_start_xmit(). + */ + if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { + persist_dma_mask = dma_mask = DMA_40BIT_MASK; +#ifdef CONFIG_HIGHMEM + dma_mask = DMA_64BIT_MASK; +#endif + } else if (tp->tg3_flags2 & TG3_FLG2_IS_5788) + persist_dma_mask = dma_mask = DMA_32BIT_MASK; + else + persist_dma_mask = dma_mask = DMA_64BIT_MASK; + + /* Configure DMA attributes. */ + if (dma_mask > DMA_32BIT_MASK) { + err = pci_set_dma_mask(pdev, dma_mask); + if (!err) { + dev->features |= NETIF_F_HIGHDMA; + err = pci_set_consistent_dma_mask(pdev, + persist_dma_mask); + if (err < 0) { + printk(KERN_ERR PFX "Unable to obtain 64 bit " + "DMA for consistent allocations\n"); + goto err_out_iounmap; + } + } + } + if (err || dma_mask == DMA_32BIT_MASK) { + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (err) { + printk(KERN_ERR PFX "No usable DMA configuration, " + "aborting.\n"); + goto err_out_iounmap; + } + } + tg3_init_bufmgr_config(tp); #if TG3_TSO_SUPPORT != 0 @@ -10833,9 +10867,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, } else tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS; - if (tp->tg3_flags2 & TG3_FLG2_IS_5788) - dev->features &= ~NETIF_F_HIGHDMA; - /* flow control autonegotiation is default behavior */ tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG; diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 8bc0b528548f..f8f4503475f9 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -877,7 +877,6 @@ static struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b), PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), @@ -891,6 +890,10 @@ static struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010), + PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL", + 0x74c5e40d), + PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil", + 0x4b801a17), PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), PCMCIA_DEVICE_PROD_ID1234( diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index 166de3507780..10845253c9e0 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -312,8 +312,7 @@ static int __devinit parport_register (struct pci_dev *dev, { struct parport_pc_pci *card; struct parport_serial_private *priv = pci_get_drvdata (dev); - int i = id->driver_data, n; - int success = 0; + int n, success = 0; priv->par = cards[id->driver_data]; card = &priv->par; @@ -344,10 +343,8 @@ static int __devinit parport_register (struct pci_dev *dev, "hi" as an offset (see SYBA def.) */ /* TODO: test if sharing interrupts works */ - printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, " - "I/O at %#lx(%#lx)\n", - parport_serial_pci_tbl[i].vendor, - parport_serial_pci_tbl[i].device, io_lo, io_hi); + dev_dbg(&dev->dev, "PCI parallel port detected: I/O at " + "%#lx(%#lx)\n", io_lo, io_hi); port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, dev); if (port) { @@ -359,7 +356,7 @@ static int __devinit parport_register (struct pci_dev *dev, if (card->postinit_hook) card->postinit_hook (dev, card, !success); - return success ? 0 : 1; + return 0; } static int __devinit parport_serial_pci_probe (struct pci_dev *dev, diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0a424a4e8187..bb96ce1db08c 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -352,11 +352,20 @@ static void pcmcia_release_dev(struct device *dev) kfree(p_dev); } +static void pcmcia_add_pseudo_device(struct pcmcia_socket *s) +{ + if (!s->pcmcia_state.device_add_pending) { + s->pcmcia_state.device_add_pending = 1; + schedule_work(&s->device_add); + } + return; +} static int pcmcia_device_probe(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; + struct pcmcia_device_id *did; struct pcmcia_socket *s; int ret = 0; @@ -392,6 +401,19 @@ static int pcmcia_device_probe(struct device * dev) } ret = p_drv->probe(p_dev); + if (ret) + goto put_module; + + /* handle pseudo multifunction devices: + * there are at most two pseudo multifunction devices. + * if we're matching against the first, schedule a + * call which will then check whether there are two + * pseudo devices, and if not, add the second one. + */ + did = (struct pcmcia_device_id *) p_dev->dev.driver_data; + if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && + (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) + pcmcia_add_pseudo_device(p_dev->socket); put_module: if (ret) @@ -660,15 +682,6 @@ static void pcmcia_delayed_add_pseudo_device(void *data) s->pcmcia_state.device_add_pending = 0; } -static inline void pcmcia_add_pseudo_device(struct pcmcia_socket *s) -{ - if (!s->pcmcia_state.device_add_pending) { - s->pcmcia_state.device_add_pending = 1; - schedule_work(&s->device_add); - } - return; -} - static int pcmcia_requery(struct device *dev, void * _data) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); @@ -755,15 +768,6 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, } if (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) { - /* handle pseudo multifunction devices: - * there are at most two pseudo multifunction devices. - * if we're matching against the first, schedule a - * call which will then check whether there are two - * pseudo devices, and if not, add the second one. - */ - if (dev->device_no == 0) - pcmcia_add_pseudo_device(dev->socket); - if (dev->device_no != did->device_no) return 0; } diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index af1d5b404cee..33157c84d1d3 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -215,9 +215,10 @@ dasd_state_basic_to_known(struct dasd_device * device) * interrupt for this detection ccw uses the kernel event daemon to * trigger the call to dasd_change_state. All this is done in the * discipline code, see dasd_eckd.c. - * After the analysis ccw is done (do_analysis returned 0 or error) - * the block device is setup. Either a fake disk is added to allow - * formatting or a proper device request queue is created. + * After the analysis ccw is done (do_analysis returned 0) the block + * device is setup. + * In case the analysis returns an error, the device setup is stopped + * (a fake disk was already added to allow formatting). */ static inline int dasd_state_basic_to_ready(struct dasd_device * device) @@ -227,13 +228,19 @@ dasd_state_basic_to_ready(struct dasd_device * device) rc = 0; if (device->discipline->do_analysis != NULL) rc = device->discipline->do_analysis(device); - if (rc) + if (rc) { + if (rc != -EAGAIN) + device->state = DASD_STATE_UNFMT; return rc; + } + /* make disk known with correct capacity */ dasd_setup_queue(device); + set_capacity(device->gdp, device->blocks << device->s2b_shift); device->state = DASD_STATE_READY; - if (dasd_scan_partitions(device) != 0) + rc = dasd_scan_partitions(device); + if (rc) device->state = DASD_STATE_BASIC; - return 0; + return rc; } /* @@ -253,6 +260,15 @@ dasd_state_ready_to_basic(struct dasd_device * device) device->state = DASD_STATE_BASIC; } +/* + * Back to basic. + */ +static inline void +dasd_state_unfmt_to_basic(struct dasd_device * device) +{ + device->state = DASD_STATE_BASIC; +} + /* * Make the device online and schedule the bottom half to start * the requeueing of requests from the linux request queue to the @@ -319,8 +335,12 @@ dasd_decrease_state(struct dasd_device *device) if (device->state == DASD_STATE_READY && device->target <= DASD_STATE_BASIC) dasd_state_ready_to_basic(device); - - if (device->state == DASD_STATE_BASIC && + + if (device->state == DASD_STATE_UNFMT && + device->target <= DASD_STATE_BASIC) + dasd_state_unfmt_to_basic(device); + + if (device->state == DASD_STATE_BASIC && device->target <= DASD_STATE_KNOWN) dasd_state_basic_to_known(device); @@ -1722,7 +1742,7 @@ dasd_open(struct inode *inp, struct file *filp) goto out; } - if (device->state < DASD_STATE_BASIC) { + if (device->state <= DASD_STATE_BASIC) { DBF_DEV_EVENT(DBF_ERR, device, " %s", " Cannot open unrecognized device"); rc = -ENODEV; diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index 65dc844b975c..fce2835e7d19 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -100,8 +100,6 @@ dasd_scan_partitions(struct dasd_device * device) { struct block_device *bdev; - /* Make the disk known. */ - set_capacity(device->gdp, device->blocks << device->s2b_shift); bdev = bdget_disk(device->gdp, 0); if (!bdev || blkdev_get(bdev, FMODE_READ, 1) < 0) return -ENODEV; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 0592354cc604..7cb0b9e78a6a 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -26,7 +26,7 @@ * new: the dasd_device structure is allocated. * known: the discipline for the device is identified. * basic: the device can do basic i/o. - * accept: the device is analysed (format is known). + * unfmt: the device could not be analyzed (format is unknown). * ready: partition detection is done and the device is can do block io. * online: the device accepts requests from the block device queue. * @@ -47,8 +47,9 @@ #define DASD_STATE_NEW 0 #define DASD_STATE_KNOWN 1 #define DASD_STATE_BASIC 2 -#define DASD_STATE_READY 3 -#define DASD_STATE_ONLINE 4 +#define DASD_STATE_UNFMT 3 +#define DASD_STATE_READY 4 +#define DASD_STATE_ONLINE 5 #include #include diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 2d5da3c75ca7..1aa3c261718a 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -93,6 +93,9 @@ dasd_devices_show(struct seq_file *m, void *v) case DASD_STATE_BASIC: seq_printf(m, "basic"); break; + case DASD_STATE_UNFMT: + seq_printf(m, "unformatted"); + break; case DASD_STATE_READY: case DASD_STATE_ONLINE: seq_printf(m, "active "); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 8cf9905d484b..f4183d660258 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1115,6 +1115,9 @@ chsc_enable_facility(int operation_code) goto out; } switch (sda_area->response.code) { + case 0x0001: /* everything ok */ + ret = 0; + break; case 0x0003: /* invalid request block */ case 0x0007: ret = -EINVAL; @@ -1123,6 +1126,8 @@ chsc_enable_facility(int operation_code) case 0x0101: /* facility not provided */ ret = -EOPNOTSUPP; break; + default: /* something went wrong */ + ret = -EIO; } out: free_page((unsigned long)sda_area); diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index d6469baa7e16..72118ee68954 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -168,7 +168,7 @@ smsg_init(void) driver_unregister(&smsg_driver); return -EIO; /* better errno ? */ } - rc = iucv_connect (&smsg_pathid, 1, 0, "*MSG ", 0, 0, 0, 0, + rc = iucv_connect (&smsg_pathid, 255, 0, "*MSG ", 0, 0, 0, 0, smsg_handle, 0); if (rc) { printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG"); diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 1c2ab3dede71..00dfdefe2967 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -778,23 +778,17 @@ static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs * struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); if (!ahci_host_intr(ap, qc)) - if (ata_ratelimit()) { - struct pci_dev *pdev = - to_pci_dev(ap->host_set->dev); - dev_printk(KERN_WARNING, &pdev->dev, + if (ata_ratelimit()) + dev_printk(KERN_WARNING, host_set->dev, "unhandled interrupt on port %u\n", i); - } VPRINTK("port %u\n", i); } else { VPRINTK("port %u (no irq)\n", i); - if (ata_ratelimit()) { - struct pci_dev *pdev = - to_pci_dev(ap->host_set->dev); - dev_printk(KERN_WARNING, &pdev->dev, + if (ata_ratelimit()) + dev_printk(KERN_WARNING, host_set->dev, "interrupt on disabled port %u\n", i); - } } irq_ack |= (1 << i); diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index c662bf531514..9327b62f97de 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -101,6 +101,8 @@ enum { ICH5_PCS = 0x92, /* port control and status */ PIIX_SCC = 0x0A, /* sub-class code register */ + PIIX_FLAG_IGNORE_PCS = (1 << 25), /* ignore PCS present bits */ + PIIX_FLAG_SCR = (1 << 26), /* SCR available */ PIIX_FLAG_AHCI = (1 << 27), /* AHCI possible */ PIIX_FLAG_CHECKINTR = (1 << 28), /* make sure PCI INTx enabled */ PIIX_FLAG_COMBINED = (1 << 29), /* combined mode possible */ @@ -110,24 +112,38 @@ enum { /* combined mode. if set, PATA is channel 0. * if clear, PATA is channel 1. */ - PIIX_COMB_PATA_P0 = (1 << 1), - PIIX_COMB = (1 << 2), /* combined mode enabled? */ - PIIX_PORT_ENABLED = (1 << 0), PIIX_PORT_PRESENT = (1 << 4), PIIX_80C_PRI = (1 << 5) | (1 << 4), PIIX_80C_SEC = (1 << 7) | (1 << 6), - ich5_pata = 0, - ich5_sata = 1, - piix4_pata = 2, - ich6_sata = 3, - ich6_sata_ahci = 4, + /* controller IDs */ + piix4_pata = 0, + ich5_pata = 1, + ich5_sata = 2, + esb_sata = 3, + ich6_sata = 4, + ich6_sata_ahci = 5, + ich6m_sata_ahci = 6, + + /* constants for mapping table */ + P0 = 0, /* port 0 */ + P1 = 1, /* port 1 */ + P2 = 2, /* port 2 */ + P3 = 3, /* port 3 */ + IDE = -1, /* IDE */ + NA = -2, /* not avaliable */ + RV = -3, /* reserved */ PIIX_AHCI_DEVICE = 6, }; +struct piix_map_db { + const u32 mask; + const int map[][4]; +}; + static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); @@ -149,19 +165,32 @@ static const struct pci_device_id piix_pci_tbl[] = { * list in drivers/pci/quirks.c. */ + /* 82801EB (ICH5) */ { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + /* 82801EB (ICH5) */ { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, - { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, - { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + /* 6300ESB (ICH5 variant with broken PCS present bits) */ + { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + /* 6300ESB pretending RAID */ + { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_sata }, + /* 82801FB/FW (ICH6/ICH6W) */ { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata }, + /* 82801FR/FRW (ICH6R/ICH6RW) */ { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, - { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* 82801FBM ICH6M (ICH6R with only port 0 and 2 implemented) */ + { 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, + /* 82801GB/GR/GH (ICH7, identical to ICH6) */ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, - { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ + { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, + /* Enterprise Southbridge 2 (where's the datasheet?) */ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* SATA Controller 1 IDE (ICH8, no datasheet yet) */ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* SATA Controller 2 IDE (ICH8, ditto) */ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, - { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, + /* Mobile SATA Controller IDE (ICH8M, ditto) */ + { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, { } /* terminate list */ }; @@ -254,7 +283,58 @@ static const struct ata_port_operations piix_sata_ops = { .host_stop = ata_host_stop, }; +static struct piix_map_db ich5_map_db = { + .mask = 0x7, + .map = { + /* PM PS SM SS MAP */ + { P0, NA, P1, NA }, /* 000b */ + { P1, NA, P0, NA }, /* 001b */ + { RV, RV, RV, RV }, + { RV, RV, RV, RV }, + { P0, P1, IDE, IDE }, /* 100b */ + { P1, P0, IDE, IDE }, /* 101b */ + { IDE, IDE, P0, P1 }, /* 110b */ + { IDE, IDE, P1, P0 }, /* 111b */ + }, +}; + +static struct piix_map_db ich6_map_db = { + .mask = 0x3, + .map = { + /* PM PS SM SS MAP */ + { P0, P1, P2, P3 }, /* 00b */ + { IDE, IDE, P1, P3 }, /* 01b */ + { P0, P2, IDE, IDE }, /* 10b */ + { RV, RV, RV, RV }, + }, +}; + +static struct piix_map_db ich6m_map_db = { + .mask = 0x3, + .map = { + /* PM PS SM SS MAP */ + { P0, P1, P2, P3 }, /* 00b */ + { RV, RV, RV, RV }, + { P0, P2, IDE, IDE }, /* 10b */ + { RV, RV, RV, RV }, + }, +}; + static struct ata_port_info piix_port_info[] = { + /* piix4_pata */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = 0x1f, /* pio0-4 */ +#if 0 + .mwdma_mask = 0x06, /* mwdma1-2 */ +#else + .mwdma_mask = 0x00, /* mwdma broken */ +#endif + .udma_mask = ATA_UDMA_MASK_40C, + .port_ops = &piix_pata_ops, + }, + /* ich5_pata */ { .sht = &piix_sht, @@ -278,43 +358,57 @@ static struct ata_port_info piix_port_info[] = { .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich5_map_db, }, - /* piix4_pata */ + /* i6300esb_sata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | + PIIX_FLAG_CHECKINTR | PIIX_FLAG_IGNORE_PCS, .pio_mask = 0x1f, /* pio0-4 */ -#if 0 - .mwdma_mask = 0x06, /* mwdma1-2 */ -#else - .mwdma_mask = 0x00, /* mwdma broken */ -#endif - .udma_mask = ATA_UDMA_MASK_40C, - .port_ops = &piix_pata_ops, + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + .private_data = &ich5_map_db, }, /* ich6_sata */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | - PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS, + PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich6_map_db, }, /* ich6_sata_ahci */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | - PIIX_FLAG_CHECKINTR | ATA_FLAG_SLAVE_POSS | + PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &piix_sata_ops, + .private_data = &ich6_map_db, + }, + + /* ich6m_sata_ahci */ + { + .sht = &piix_sht, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED_ICH6 | + PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | + PIIX_FLAG_AHCI, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &piix_sata_ops, + .private_data = &ich6m_map_db, }, }; @@ -405,44 +499,59 @@ static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes) * piix_sata_probe - Probe PCI device for present SATA devices * @ap: Port associated with the PCI device we wish to probe * - * Reads SATA PCI device's PCI config register Port Configuration - * and Status (PCS) to determine port and device availability. + * Reads and configures SATA PCI device's PCI config register + * Port Configuration and Status (PCS) to determine port and + * device availability. * * LOCKING: * None (inherited from caller). * * RETURNS: - * Non-zero if port is enabled, it may or may not have a device - * attached in that case (PRESENT bit would only be set if BIOS probe - * was done). Zero is returned if port is disabled. + * Mask of avaliable devices on the port. */ -static int piix_sata_probe (struct ata_port *ap) +static unsigned int piix_sata_probe (struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - int combined = (ap->flags & ATA_FLAG_SLAVE_POSS); - int orig_mask, mask, i; + const unsigned int *map = ap->host_set->private_data; + int base = 2 * ap->hard_port_no; + unsigned int present_mask = 0; + int port, i; u8 pcs; pci_read_config_byte(pdev, ICH5_PCS, &pcs); - orig_mask = (int) pcs & 0xff; + DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base); - /* TODO: this is vaguely wrong for ICH6 combined mode, - * where only two of the four SATA ports are mapped - * onto a single ATA channel. It is also vaguely inaccurate - * for ICH5, which has only two ports. However, this is ok, - * as further device presence detection code will handle - * any false positives produced here. - */ - - for (i = 0; i < 4; i++) { - mask = (PIIX_PORT_ENABLED << i); - - if ((orig_mask & mask) == mask) - if (combined || (i == ap->hard_port_no)) - return 1; + /* enable all ports on this ap and wait for them to settle */ + for (i = 0; i < 2; i++) { + port = map[base + i]; + if (port >= 0) + pcs |= 1 << port; } - return 0; + pci_write_config_byte(pdev, ICH5_PCS, pcs); + msleep(100); + + /* let's see which devices are present */ + pci_read_config_byte(pdev, ICH5_PCS, &pcs); + + for (i = 0; i < 2; i++) { + port = map[base + i]; + if (port < 0) + continue; + if (ap->flags & PIIX_FLAG_IGNORE_PCS || pcs & 1 << (4 + port)) + present_mask |= 1 << i; + else + pcs &= ~(1 << port); + } + + /* disable offline ports on non-AHCI controllers */ + if (!(ap->flags & PIIX_FLAG_AHCI)) + pci_write_config_byte(pdev, ICH5_PCS, pcs); + + DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", + ap->id, pcs, present_mask); + + return present_mask; } /** @@ -666,6 +775,54 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) return no_piix_dma; } +static void __devinit piix_init_sata_map(struct pci_dev *pdev, + struct ata_port_info *pinfo) +{ + struct piix_map_db *map_db = pinfo[0].private_data; + const unsigned int *map; + int i, invalid_map = 0; + u8 map_value; + + pci_read_config_byte(pdev, ICH5_PMR, &map_value); + + map = map_db->map[map_value & map_db->mask]; + + dev_printk(KERN_INFO, &pdev->dev, "MAP ["); + for (i = 0; i < 4; i++) { + switch (map[i]) { + case RV: + invalid_map = 1; + printk(" XX"); + break; + + case NA: + printk(" --"); + break; + + case IDE: + WARN_ON((i & 1) || map[i + 1] != IDE); + pinfo[i / 2] = piix_port_info[ich5_pata]; + i++; + printk(" IDE IDE"); + break; + + default: + printk(" P%d", map[i]); + if (i & 1) + pinfo[i / 2].host_flags |= ATA_FLAG_SLAVE_POSS; + break; + } + } + printk(" ]\n"); + + if (invalid_map) + dev_printk(KERN_ERR, &pdev->dev, + "invalid MAP value %u\n", map_value); + + pinfo[0].private_data = (void *)map; + pinfo[1].private_data = (void *)map; +} + /** * piix_init_one - Register PIIX ATA PCI device with kernel services * @pdev: PCI device to register @@ -684,9 +841,8 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - struct ata_port_info *port_info[2]; - unsigned int combined = 0; - unsigned int pata_chan = 0, sata_chan = 0; + struct ata_port_info port_info[2]; + struct ata_port_info *ppinfo[2] = { &port_info[0], &port_info[1] }; unsigned long host_flags; if (!printed_version++) @@ -697,10 +853,10 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (!in_module_init) return -ENODEV; - port_info[0] = &piix_port_info[ent->driver_data]; - port_info[1] = &piix_port_info[ent->driver_data]; + port_info[0] = piix_port_info[ent->driver_data]; + port_info[1] = piix_port_info[ent->driver_data]; - host_flags = port_info[0]->host_flags; + host_flags = port_info[0].host_flags; if (host_flags & PIIX_FLAG_AHCI) { u8 tmp; @@ -712,37 +868,9 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) } } - if (host_flags & PIIX_FLAG_COMBINED) { - u8 tmp; - pci_read_config_byte(pdev, ICH5_PMR, &tmp); - - if (host_flags & PIIX_FLAG_COMBINED_ICH6) { - switch (tmp & 0x3) { - case 0: - break; - case 1: - combined = 1; - sata_chan = 1; - break; - case 2: - combined = 1; - pata_chan = 1; - break; - case 3: - dev_printk(KERN_WARNING, &pdev->dev, - "invalid MAP value %u\n", tmp); - break; - } - } else { - if (tmp & PIIX_COMB) { - combined = 1; - if (tmp & PIIX_COMB_PATA_P0) - sata_chan = 1; - else - pata_chan = 1; - } - } - } + /* Initialize SATA map */ + if (host_flags & ATA_FLAG_SATA) + piix_init_sata_map(pdev, port_info); /* On ICH5, some BIOSen disable the interrupt using the * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. @@ -753,25 +881,16 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (host_flags & PIIX_FLAG_CHECKINTR) pci_intx(pdev, 1); - if (combined) { - port_info[sata_chan] = &piix_port_info[ent->driver_data]; - port_info[sata_chan]->host_flags |= ATA_FLAG_SLAVE_POSS; - port_info[pata_chan] = &piix_port_info[ich5_pata]; - - dev_printk(KERN_WARNING, &pdev->dev, - "combined mode detected (p=%u, s=%u)\n", - pata_chan, sata_chan); - } if (piix_check_450nx_errata(pdev)) { /* This writes into the master table but it does not really matter for this errata as we will apply it to all the PIIX devices on the board */ - port_info[0]->mwdma_mask = 0; - port_info[0]->udma_mask = 0; - port_info[1]->mwdma_mask = 0; - port_info[1]->udma_mask = 0; + port_info[0].mwdma_mask = 0; + port_info[0].udma_mask = 0; + port_info[1].mwdma_mask = 0; + port_info[1].udma_mask = 0; } - return ata_pci_init_one(pdev, port_info, 2); + return ata_pci_init_one(pdev, ppinfo, 2); } static int __init piix_init(void) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 9132698d29b8..5060a1a1ad25 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -65,12 +65,9 @@ static unsigned int ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); static void ata_set_mode(struct ata_port *ap); static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev); -static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift); -static int fgb(u32 bitmap); -static int ata_choose_xfer_mode(const struct ata_port *ap, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out); static void ata_pio_error(struct ata_port *ap); +static unsigned int ata_dev_xfermask(struct ata_port *ap, + struct ata_device *dev); static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; @@ -232,58 +229,148 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) return -1; } -static const char * const xfer_mode_str[] = { - "UDMA/16", - "UDMA/25", - "UDMA/33", - "UDMA/44", - "UDMA/66", - "UDMA/100", - "UDMA/133", - "UDMA7", - "MWDMA0", - "MWDMA1", - "MWDMA2", - "PIO0", - "PIO1", - "PIO2", - "PIO3", - "PIO4", +/** + * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask + * @pio_mask: pio_mask + * @mwdma_mask: mwdma_mask + * @udma_mask: udma_mask + * + * Pack @pio_mask, @mwdma_mask and @udma_mask into a single + * unsigned int xfer_mask. + * + * LOCKING: + * None. + * + * RETURNS: + * Packed xfer_mask. + */ +static unsigned int ata_pack_xfermask(unsigned int pio_mask, + unsigned int mwdma_mask, + unsigned int udma_mask) +{ + return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) | + ((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) | + ((udma_mask << ATA_SHIFT_UDMA) & ATA_MASK_UDMA); +} + +static const struct ata_xfer_ent { + unsigned int shift, bits; + u8 base; +} ata_xfer_tbl[] = { + { ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 }, + { ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 }, + { ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 }, + { -1, }, }; /** - * ata_udma_string - convert UDMA bit offset to string - * @mask: mask of bits supported; only highest bit counts. + * ata_xfer_mask2mode - Find matching XFER_* for the given xfer_mask + * @xfer_mask: xfer_mask of interest + * + * Return matching XFER_* value for @xfer_mask. Only the highest + * bit of @xfer_mask is considered. + * + * LOCKING: + * None. + * + * RETURNS: + * Matching XFER_* value, 0 if no match found. + */ +static u8 ata_xfer_mask2mode(unsigned int xfer_mask) +{ + int highbit = fls(xfer_mask) - 1; + const struct ata_xfer_ent *ent; + + for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) + if (highbit >= ent->shift && highbit < ent->shift + ent->bits) + return ent->base + highbit - ent->shift; + return 0; +} + +/** + * ata_xfer_mode2mask - Find matching xfer_mask for XFER_* + * @xfer_mode: XFER_* of interest + * + * Return matching xfer_mask for @xfer_mode. + * + * LOCKING: + * None. + * + * RETURNS: + * Matching xfer_mask, 0 if no match found. + */ +static unsigned int ata_xfer_mode2mask(u8 xfer_mode) +{ + const struct ata_xfer_ent *ent; + + for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) + if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits) + return 1 << (ent->shift + xfer_mode - ent->base); + return 0; +} + +/** + * ata_xfer_mode2shift - Find matching xfer_shift for XFER_* + * @xfer_mode: XFER_* of interest + * + * Return matching xfer_shift for @xfer_mode. + * + * LOCKING: + * None. + * + * RETURNS: + * Matching xfer_shift, -1 if no match found. + */ +static int ata_xfer_mode2shift(unsigned int xfer_mode) +{ + const struct ata_xfer_ent *ent; + + for (ent = ata_xfer_tbl; ent->shift >= 0; ent++) + if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits) + return ent->shift; + return -1; +} + +/** + * ata_mode_string - convert xfer_mask to string + * @xfer_mask: mask of bits supported; only highest bit counts. * * Determine string which represents the highest speed - * (highest bit in @udma_mask). + * (highest bit in @modemask). * * LOCKING: * None. * * RETURNS: * Constant C string representing highest speed listed in - * @udma_mask, or the constant C string "". + * @mode_mask, or the constant C string "". */ - -static const char *ata_mode_string(unsigned int mask) +static const char *ata_mode_string(unsigned int xfer_mask) { - int i; - - for (i = 7; i >= 0; i--) - if (mask & (1 << i)) - goto out; - for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--) - if (mask & (1 << i)) - goto out; - for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--) - if (mask & (1 << i)) - goto out; + static const char * const xfer_mode_str[] = { + "PIO0", + "PIO1", + "PIO2", + "PIO3", + "PIO4", + "MWDMA0", + "MWDMA1", + "MWDMA2", + "UDMA/16", + "UDMA/25", + "UDMA/33", + "UDMA/44", + "UDMA/66", + "UDMA/100", + "UDMA/133", + "UDMA7", + }; + int highbit; + highbit = fls(xfer_mask) - 1; + if (highbit >= 0 && highbit < ARRAY_SIZE(xfer_mode_str)) + return xfer_mode_str[highbit]; return ""; - -out: - return xfer_mode_str[i]; } /** @@ -693,69 +780,104 @@ static inline void ata_dump_id(const u16 *id) id[93]); } -/* - * Compute the PIO modes available for this device. This is not as - * trivial as it seems if we must consider early devices correctly. +/** + * ata_id_xfermask - Compute xfermask from the given IDENTIFY data + * @id: IDENTIFY data to compute xfer mask from * - * FIXME: pre IDE drive timing (do we care ?). + * Compute the xfermask for this device. This is not as trivial + * as it seems if we must consider early devices correctly. + * + * FIXME: pre IDE drive timing (do we care ?). + * + * LOCKING: + * None. + * + * RETURNS: + * Computed xfermask */ - -static unsigned int ata_pio_modes(const struct ata_device *adev) +static unsigned int ata_id_xfermask(const u16 *id) { - u16 modes; + unsigned int pio_mask, mwdma_mask, udma_mask; /* Usual case. Word 53 indicates word 64 is valid */ - if (adev->id[ATA_ID_FIELD_VALID] & (1 << 1)) { - modes = adev->id[ATA_ID_PIO_MODES] & 0x03; - modes <<= 3; - modes |= 0x7; - return modes; + if (id[ATA_ID_FIELD_VALID] & (1 << 1)) { + pio_mask = id[ATA_ID_PIO_MODES] & 0x03; + pio_mask <<= 3; + pio_mask |= 0x7; + } else { + /* If word 64 isn't valid then Word 51 high byte holds + * the PIO timing number for the maximum. Turn it into + * a mask. + */ + pio_mask = (2 << (id[ATA_ID_OLD_PIO_MODES] & 0xFF)) - 1 ; + + /* But wait.. there's more. Design your standards by + * committee and you too can get a free iordy field to + * process. However its the speeds not the modes that + * are supported... Note drivers using the timing API + * will get this right anyway + */ } - /* If word 64 isn't valid then Word 51 high byte holds the PIO timing - number for the maximum. Turn it into a mask and return it */ - modes = (2 << ((adev->id[ATA_ID_OLD_PIO_MODES] >> 8) & 0xFF)) - 1 ; - return modes; - /* But wait.. there's more. Design your standards by committee and - you too can get a free iordy field to process. However its the - speeds not the modes that are supported... Note drivers using the - timing API will get this right anyway */ -} + mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; + udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; -static inline void -ata_queue_pio_task(struct ata_port *ap) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_work(ata_wq, &ap->pio_task); -} - -static inline void -ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay) -{ - if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK)) - queue_delayed_work(ata_wq, &ap->pio_task, delay); + return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask); } /** - * ata_flush_pio_tasks - Flush pio_task - * @ap: the target ata_port + * ata_port_queue_task - Queue port_task + * @ap: The ata_port to queue port_task for * - * After this function completes, pio_task is - * guranteed not to be running or scheduled. + * Schedule @fn(@data) for execution after @delay jiffies using + * port_task. There is one port_task per port and it's the + * user(low level driver)'s responsibility to make sure that only + * one task is active at any given time. + * + * libata core layer takes care of synchronization between + * port_task and EH. ata_port_queue_task() may be ignored for EH + * synchronization. + * + * LOCKING: + * Inherited from caller. + */ +void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), void *data, + unsigned long delay) +{ + int rc; + + if (ap->flags & ATA_FLAG_FLUSH_PORT_TASK) + return; + + PREPARE_WORK(&ap->port_task, fn, data); + + if (!delay) + rc = queue_work(ata_wq, &ap->port_task); + else + rc = queue_delayed_work(ata_wq, &ap->port_task, delay); + + /* rc == 0 means that another user is using port task */ + WARN_ON(rc == 0); +} + +/** + * ata_port_flush_task - Flush port_task + * @ap: The ata_port to flush port_task for + * + * After this function completes, port_task is guranteed not to + * be running or scheduled. * * LOCKING: * Kernel thread context (may sleep) */ - -static void ata_flush_pio_tasks(struct ata_port *ap) +void ata_port_flush_task(struct ata_port *ap) { - int tmp = 0; unsigned long flags; DPRINTK("ENTER\n"); spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags |= ATA_FLAG_FLUSH_PIO_TASK; + ap->flags |= ATA_FLAG_FLUSH_PORT_TASK; spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("flush #1\n"); @@ -766,14 +888,13 @@ static void ata_flush_pio_tasks(struct ata_port *ap) * the FLUSH flag; thus, it will never queue pio tasks again. * Cancel and flush. */ - tmp |= cancel_delayed_work(&ap->pio_task); - if (!tmp) { + if (!cancel_delayed_work(&ap->port_task)) { DPRINTK("flush #2\n"); flush_workqueue(ata_wq); } spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_FLUSH_PIO_TASK; + ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK; spin_unlock_irqrestore(&ap->host_set->lock, flags); DPRINTK("EXIT\n"); @@ -904,7 +1025,7 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * @dev: target device * @p_class: pointer to class of the target device (may be changed) * @post_reset: is this read ID post-reset? - * @id: buffer to fill IDENTIFY page into + * @p_id: read IDENTIFY page (newly allocated) * * Read ID data from the specified device. ATA_CMD_ID_ATA is * performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI @@ -919,12 +1040,13 @@ unsigned int ata_pio_need_iordy(const struct ata_device *adev) * 0 on success, -errno otherwise. */ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, - unsigned int *p_class, int post_reset, u16 *id) + unsigned int *p_class, int post_reset, u16 **p_id) { unsigned int class = *p_class; unsigned int using_edd; struct ata_taskfile tf; unsigned int err_mask = 0; + u16 *id; const char *reason; int rc; @@ -938,6 +1060,13 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ + id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL); + if (id == NULL) { + rc = -ENOMEM; + reason = "out of memory"; + goto err_out; + } + retry: ata_tf_init(ap, &tf, dev->devno); @@ -1028,53 +1157,59 @@ static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev, } *p_class = class; + *p_id = id; return 0; err_out: printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n", ap->id, dev->devno, reason); + kfree(id); return rc; } +static inline u8 ata_dev_knobble(const struct ata_port *ap, + struct ata_device *dev) +{ + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); +} + /** - * ata_dev_identify - obtain IDENTIFY x DEVICE page - * @ap: port on which device we wish to probe resides - * @device: device bus address, starting at zero + * ata_dev_configure - Configure the specified ATA/ATAPI device + * @ap: Port on which target device resides + * @dev: Target device to configure + * @print_info: Enable device info printout * - * Following bus reset, we issue the IDENTIFY [PACKET] DEVICE - * command, and read back the 512-byte device information page. - * The device information page is fed to us via the standard - * PIO-IN protocol, but we hand-code it here. (TODO: investigate - * using standard PIO-IN paths) - * - * After reading the device information page, we use several - * bits of information from it to initialize data structures - * that will be used during the lifetime of the ata_device. - * Other data from the info page is used to disqualify certain - * older ATA devices we do not wish to support. + * Configure @dev according to @dev->id. Generic and low-level + * driver specific fixups are also applied. * * LOCKING: - * Inherited from caller. Some functions called by this function - * obtain the host_set lock. + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, -errno otherwise */ - -static void ata_dev_identify(struct ata_port *ap, unsigned int device) +static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev, + int print_info) { - struct ata_device *dev = &ap->device[device]; - unsigned long xfer_modes; + unsigned int xfer_mask; int i, rc; if (!ata_dev_present(dev)) { DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n", - ap->id, device); - return; + ap->id, dev->devno); + return 0; } - DPRINTK("ENTER, host %u, dev %u\n", ap->id, device); + DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno); - rc = ata_dev_read_id(ap, dev, &dev->class, 1, dev->id); - if (rc) - goto err_out; + /* initialize to-be-configured parameters */ + dev->flags = 0; + dev->max_sectors = 0; + dev->cdb_len = 0; + dev->n_sectors = 0; + dev->cylinders = 0; + dev->heads = 0; + dev->sectors = 0; /* * common ATA, ATAPI feature tests @@ -1083,15 +1218,12 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) /* we require DMA support (bits 8 of word 49) */ if (!ata_id_has_dma(dev->id)) { printk(KERN_DEBUG "ata%u: no dma\n", ap->id); + rc = -EINVAL; goto err_out_nosup; } - /* quick-n-dirty find max transfer mode; for printk only */ - xfer_modes = dev->id[ATA_ID_UDMA_MODES]; - if (!xfer_modes) - xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA; - if (!xfer_modes) - xfer_modes = ata_pio_modes(dev); + /* find max transfer mode; for printk only */ + xfer_mask = ata_id_xfermask(dev->id); ata_dump_id(dev->id); @@ -1100,19 +1232,25 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) dev->n_sectors = ata_id_n_sectors(dev->id); if (ata_id_has_lba(dev->id)) { - dev->flags |= ATA_DFLAG_LBA; + const char *lba_desc; - if (ata_id_has_lba48(dev->id)) + lba_desc = "LBA"; + dev->flags |= ATA_DFLAG_LBA; + if (ata_id_has_lba48(dev->id)) { dev->flags |= ATA_DFLAG_LBA48; + lba_desc = "LBA48"; + } /* print device info to dmesg */ - printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors:%s\n", - ap->id, device, - ata_id_major_version(dev->id), - ata_mode_string(xfer_modes), - (unsigned long long)dev->n_sectors, - dev->flags & ATA_DFLAG_LBA48 ? " LBA48" : " LBA"); - } else { + if (print_info) + printk(KERN_INFO "ata%u: dev %u ATA-%d, " + "max %s, %Lu sectors: %s\n", + ap->id, dev->devno, + ata_id_major_version(dev->id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + lba_desc); + } else { /* CHS */ /* Default translation */ @@ -1128,13 +1266,14 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) } /* print device info to dmesg */ - printk(KERN_INFO "ata%u: dev %u ATA-%d, max %s, %Lu sectors: CHS %d/%d/%d\n", - ap->id, device, - ata_id_major_version(dev->id), - ata_mode_string(xfer_modes), - (unsigned long long)dev->n_sectors, - (int)dev->cylinders, (int)dev->heads, (int)dev->sectors); - + if (print_info) + printk(KERN_INFO "ata%u: dev %u ATA-%d, " + "max %s, %Lu sectors: CHS %u/%u/%u\n", + ap->id, dev->devno, + ata_id_major_version(dev->id), + ata_mode_string(xfer_mask), + (unsigned long long)dev->n_sectors, + dev->cylinders, dev->heads, dev->sectors); } if (dev->id[59] & 0x100) { @@ -1150,6 +1289,7 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) rc = atapi_cdb_len(dev->id); if ((rc < 12) || (rc > ATAPI_CDB_LEN)) { printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); + rc = -EINVAL; goto err_out_nosup; } dev->cdb_len = (unsigned int) rc; @@ -1158,9 +1298,9 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) dev->flags |= ATA_DFLAG_CDB_INTR; /* print device info to dmesg */ - printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", - ap->id, device, - ata_mode_string(xfer_modes)); + if (print_info) + printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", + ap->id, dev->devno, ata_mode_string(xfer_mask)); } ap->host->max_cmd_len = 0; @@ -1169,44 +1309,26 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ap->host->max_cmd_len, ap->device[i].cdb_len); - DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); - return; - -err_out_nosup: - printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", - ap->id, device); -err_out: - dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */ - DPRINTK("EXIT, err\n"); -} - - -static inline u8 ata_dev_knobble(const struct ata_port *ap, - struct ata_device *dev) -{ - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); -} - -/** - * ata_dev_config - Run device specific handlers & check for SATA->PATA bridges - * @ap: Bus - * @i: Device - * - * LOCKING: - */ - -void ata_dev_config(struct ata_port *ap, unsigned int i) -{ /* limit bridge transfers to udma5, 200 sectors */ - if (ata_dev_knobble(ap, &ap->device[i])) { - printk(KERN_INFO "ata%u(%u): applying bridge limits\n", - ap->id, i); + if (ata_dev_knobble(ap, dev)) { + if (print_info) + printk(KERN_INFO "ata%u(%u): applying bridge limits\n", + ap->id, dev->devno); ap->udma_mask &= ATA_UDMA5; - ap->device[i].max_sectors = ATA_MAX_SECTORS; + dev->max_sectors = ATA_MAX_SECTORS; } if (ap->ops->dev_config) - ap->ops->dev_config(ap, &ap->device[i]); + ap->ops->dev_config(ap, dev); + + DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap)); + return 0; + +err_out_nosup: + printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", + ap->id, dev->devno); + DPRINTK("EXIT, err\n"); + return rc; } /** @@ -1226,41 +1348,61 @@ void ata_dev_config(struct ata_port *ap, unsigned int i) static int ata_bus_probe(struct ata_port *ap) { - unsigned int i, found = 0; + unsigned int classes[ATA_MAX_DEVICES]; + unsigned int i, rc, found = 0; + ata_port_probe(ap); + + /* reset */ if (ap->ops->probe_reset) { - unsigned int classes[ATA_MAX_DEVICES]; - int rc; - - ata_port_probe(ap); + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_UNKNOWN; rc = ap->ops->probe_reset(ap, classes); - if (rc == 0) { - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (classes[i] == ATA_DEV_UNKNOWN) - classes[i] = ATA_DEV_NONE; - ap->device[i].class = classes[i]; - } - } else { - printk(KERN_ERR "ata%u: probe reset failed, " - "disabling port\n", ap->id); - ata_port_disable(ap); + if (rc) { + printk("ata%u: reset failed (errno=%d)\n", ap->id, rc); + return rc; } - } else + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; + } else { ap->ops->phy_reset(ap); - if (ap->flags & ATA_FLAG_PORT_DISABLED) - goto err_out; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - ata_dev_identify(ap, i); - if (ata_dev_present(&ap->device[i])) { - found = 1; - ata_dev_config(ap,i); + for (i = 0; i < ATA_MAX_DEVICES; i++) { + if (!(ap->flags & ATA_FLAG_PORT_DISABLED)) + classes[i] = ap->device[i].class; + else + ap->device[i].class = ATA_DEV_UNKNOWN; } + ata_port_probe(ap); } - if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED)) + /* read IDENTIFY page and configure devices */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + + dev->class = classes[i]; + + if (!ata_dev_present(dev)) + continue; + + WARN_ON(dev->id != NULL); + if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) { + dev->class = ATA_DEV_NONE; + continue; + } + + if (ata_dev_configure(ap, dev, 1)) { + dev->class++; /* disable device */ + continue; + } + + found = 1; + } + + if (!found) goto err_out_disable; ata_set_mode(ap); @@ -1271,7 +1413,6 @@ static int ata_bus_probe(struct ata_port *ap) err_out_disable: ap->ops->port_disable(ap); -err_out: return -1; } @@ -1567,31 +1708,8 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed, return 0; } -static const struct { - unsigned int shift; - u8 base; -} xfer_mode_classes[] = { - { ATA_SHIFT_UDMA, XFER_UDMA_0 }, - { ATA_SHIFT_MWDMA, XFER_MW_DMA_0 }, - { ATA_SHIFT_PIO, XFER_PIO_0 }, -}; - -static u8 base_from_shift(unsigned int shift) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) - if (xfer_mode_classes[i].shift == shift) - return xfer_mode_classes[i].base; - - return 0xff; -} - static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) { - int ofs, idx; - u8 base; - if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED)) return; @@ -1600,65 +1718,58 @@ static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev) ata_dev_set_xfermode(ap, dev); - base = base_from_shift(dev->xfer_shift); - ofs = dev->xfer_mode - base; - idx = ofs + dev->xfer_shift; - WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str)); + if (ata_dev_revalidate(ap, dev, 0)) { + printk(KERN_ERR "ata%u: failed to revalidate after set " + "xfermode, disabled\n", ap->id); + ata_port_disable(ap); + } - DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n", - idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs); + DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n", + dev->xfer_shift, (int)dev->xfer_mode); printk(KERN_INFO "ata%u: dev %u configured for %s\n", - ap->id, dev->devno, xfer_mode_str[idx]); + ap->id, dev->devno, + ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode))); } static int ata_host_set_pio(struct ata_port *ap) -{ - unsigned int mask; - int x, i; - u8 base, xfer_mode; - - mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); - x = fgb(mask); - if (x < 0) { - printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); - return -1; - } - - base = base_from_shift(ATA_SHIFT_PIO); - xfer_mode = base + x; - - DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", - (int)base, (int)xfer_mode, mask, x); - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *dev = &ap->device[i]; - if (ata_dev_present(dev)) { - dev->pio_mode = xfer_mode; - dev->xfer_mode = xfer_mode; - dev->xfer_shift = ATA_SHIFT_PIO; - if (ap->ops->set_piomode) - ap->ops->set_piomode(ap, dev); - } - } - - return 0; -} - -static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, - unsigned int xfer_shift) { int i; for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_present(dev)) { - dev->dma_mode = xfer_mode; - dev->xfer_mode = xfer_mode; - dev->xfer_shift = xfer_shift; - if (ap->ops->set_dmamode) - ap->ops->set_dmamode(ap, dev); + + if (!ata_dev_present(dev)) + continue; + + if (!dev->pio_mode) { + printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); + return -1; } + + dev->xfer_mode = dev->pio_mode; + dev->xfer_shift = ATA_SHIFT_PIO; + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + + return 0; +} + +static void ata_host_set_dma(struct ata_port *ap) +{ + int i; + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + + if (!ata_dev_present(dev) || !dev->dma_mode) + continue; + + dev->xfer_mode = dev->dma_mode; + dev->xfer_shift = ata_xfer_mode2shift(dev->dma_mode); + if (ap->ops->set_dmamode) + ap->ops->set_dmamode(ap, dev); } } @@ -1673,28 +1784,34 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, */ static void ata_set_mode(struct ata_port *ap) { - unsigned int xfer_shift; - u8 xfer_mode; - int rc; + int i, rc; - /* step 1: always set host PIO timings */ + /* step 1: calculate xfer_mask */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + unsigned int xfer_mask; + + if (!ata_dev_present(dev)) + continue; + + xfer_mask = ata_dev_xfermask(ap, dev); + + dev->pio_mode = ata_xfer_mask2mode(xfer_mask & ATA_MASK_PIO); + dev->dma_mode = ata_xfer_mask2mode(xfer_mask & (ATA_MASK_MWDMA | + ATA_MASK_UDMA)); + } + + /* step 2: always set host PIO timings */ rc = ata_host_set_pio(ap); if (rc) goto err_out; - /* step 2: choose the best data xfer mode */ - xfer_mode = xfer_shift = 0; - rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift); - if (rc) - goto err_out; - - /* step 3: if that xfer mode isn't PIO, set host DMA timings */ - if (xfer_shift != ATA_SHIFT_PIO) - ata_host_set_dma(ap, xfer_mode, xfer_shift); + /* step 3: set host DMA timings */ + ata_host_set_dma(ap); /* step 4: update devices' xfer mode */ - ata_dev_set_mode(ap, &ap->device[0]); - ata_dev_set_mode(ap, &ap->device[1]); + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_set_mode(ap, &ap->device[i]); if (ap->flags & ATA_FLAG_PORT_DISABLED) return; @@ -2325,11 +2442,118 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, return rc; } -static void ata_pr_blacklisted(const struct ata_port *ap, - const struct ata_device *dev) +/** + * ata_dev_same_device - Determine whether new ID matches configured device + * @ap: port on which the device to compare against resides + * @dev: device to compare against + * @new_class: class of the new device + * @new_id: IDENTIFY page of the new device + * + * Compare @new_class and @new_id against @dev and determine + * whether @dev is the device indicated by @new_class and + * @new_id. + * + * LOCKING: + * None. + * + * RETURNS: + * 1 if @dev matches @new_class and @new_id, 0 otherwise. + */ +static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev, + unsigned int new_class, const u16 *new_id) { - printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n", - ap->id, dev->devno); + const u16 *old_id = dev->id; + unsigned char model[2][41], serial[2][21]; + u64 new_n_sectors; + + if (dev->class != new_class) { + printk(KERN_INFO + "ata%u: dev %u class mismatch %d != %d\n", + ap->id, dev->devno, dev->class, new_class); + return 0; + } + + ata_id_c_string(old_id, model[0], ATA_ID_PROD_OFS, sizeof(model[0])); + ata_id_c_string(new_id, model[1], ATA_ID_PROD_OFS, sizeof(model[1])); + ata_id_c_string(old_id, serial[0], ATA_ID_SERNO_OFS, sizeof(serial[0])); + ata_id_c_string(new_id, serial[1], ATA_ID_SERNO_OFS, sizeof(serial[1])); + new_n_sectors = ata_id_n_sectors(new_id); + + if (strcmp(model[0], model[1])) { + printk(KERN_INFO + "ata%u: dev %u model number mismatch '%s' != '%s'\n", + ap->id, dev->devno, model[0], model[1]); + return 0; + } + + if (strcmp(serial[0], serial[1])) { + printk(KERN_INFO + "ata%u: dev %u serial number mismatch '%s' != '%s'\n", + ap->id, dev->devno, serial[0], serial[1]); + return 0; + } + + if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) { + printk(KERN_INFO + "ata%u: dev %u n_sectors mismatch %llu != %llu\n", + ap->id, dev->devno, (unsigned long long)dev->n_sectors, + (unsigned long long)new_n_sectors); + return 0; + } + + return 1; +} + +/** + * ata_dev_revalidate - Revalidate ATA device + * @ap: port on which the device to revalidate resides + * @dev: device to revalidate + * @post_reset: is this revalidation after reset? + * + * Re-read IDENTIFY page and make sure @dev is still attached to + * the port. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * 0 on success, negative errno otherwise + */ +int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, + int post_reset) +{ + unsigned int class; + u16 *id; + int rc; + + if (!ata_dev_present(dev)) + return -ENODEV; + + class = dev->class; + id = NULL; + + /* allocate & read ID data */ + rc = ata_dev_read_id(ap, dev, &class, post_reset, &id); + if (rc) + goto fail; + + /* is the device still there? */ + if (!ata_dev_same_device(ap, dev, class, id)) { + rc = -ENODEV; + goto fail; + } + + kfree(dev->id); + dev->id = id; + + /* configure device according to the new ID */ + return ata_dev_configure(ap, dev, 0); + + fail: + printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n", + ap->id, dev->devno, rc); + kfree(id); + return rc; } static const char * const ata_dma_blacklist [] = { @@ -2378,128 +2602,45 @@ static int ata_dma_blacklisted(const struct ata_device *dev) return 0; } -static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift) -{ - const struct ata_device *master, *slave; - unsigned int mask; - - master = &ap->device[0]; - slave = &ap->device[1]; - - WARN_ON(!ata_dev_present(master) && !ata_dev_present(slave)); - - if (shift == ATA_SHIFT_UDMA) { - mask = ap->udma_mask; - if (ata_dev_present(master)) { - mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); - if (ata_dma_blacklisted(master)) { - mask = 0; - ata_pr_blacklisted(ap, master); - } - } - if (ata_dev_present(slave)) { - mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); - if (ata_dma_blacklisted(slave)) { - mask = 0; - ata_pr_blacklisted(ap, slave); - } - } - } - else if (shift == ATA_SHIFT_MWDMA) { - mask = ap->mwdma_mask; - if (ata_dev_present(master)) { - mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07); - if (ata_dma_blacklisted(master)) { - mask = 0; - ata_pr_blacklisted(ap, master); - } - } - if (ata_dev_present(slave)) { - mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); - if (ata_dma_blacklisted(slave)) { - mask = 0; - ata_pr_blacklisted(ap, slave); - } - } - } - else if (shift == ATA_SHIFT_PIO) { - mask = ap->pio_mask; - if (ata_dev_present(master)) { - /* spec doesn't return explicit support for - * PIO0-2, so we fake it - */ - u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03; - tmp_mode <<= 3; - tmp_mode |= 0x7; - mask &= tmp_mode; - } - if (ata_dev_present(slave)) { - /* spec doesn't return explicit support for - * PIO0-2, so we fake it - */ - u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03; - tmp_mode <<= 3; - tmp_mode |= 0x7; - mask &= tmp_mode; - } - } - else { - mask = 0xffffffff; /* shut up compiler warning */ - BUG(); - } - - return mask; -} - -/* find greatest bit */ -static int fgb(u32 bitmap) -{ - unsigned int i; - int x = -1; - - for (i = 0; i < 32; i++) - if (bitmap & (1 << i)) - x = i; - - return x; -} - /** - * ata_choose_xfer_mode - attempt to find best transfer mode - * @ap: Port for which an xfer mode will be selected - * @xfer_mode_out: (output) SET FEATURES - XFER MODE code - * @xfer_shift_out: (output) bit shift that selects this mode + * ata_dev_xfermask - Compute supported xfermask of the given device + * @ap: Port on which the device to compute xfermask for resides + * @dev: Device to compute xfermask for * - * Based on host and device capabilities, determine the - * maximum transfer mode that is amenable to all. + * Compute supported xfermask of @dev. This function is + * responsible for applying all known limits including host + * controller limits, device blacklist, etc... * * LOCKING: - * PCI/etc. bus probe sem. + * None. * * RETURNS: - * Zero on success, negative on error. + * Computed xfermask. */ - -static int ata_choose_xfer_mode(const struct ata_port *ap, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out) +static unsigned int ata_dev_xfermask(struct ata_port *ap, + struct ata_device *dev) { - unsigned int mask, shift; - int x, i; + unsigned long xfer_mask; + int i; - for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) { - shift = xfer_mode_classes[i].shift; - mask = ata_get_mode_mask(ap, shift); + xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, + ap->udma_mask); - x = fgb(mask); - if (x >= 0) { - *xfer_mode_out = xfer_mode_classes[i].base + x; - *xfer_shift_out = shift; - return 0; - } + /* use port-wide xfermask for now */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *d = &ap->device[i]; + if (!ata_dev_present(d)) + continue; + xfer_mask &= ata_id_xfermask(d->id); + if (ata_dma_blacklisted(d)) + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); } - return -1; + if (ata_dma_blacklisted(dev)) + printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, " + "disabling DMA\n", ap->id, dev->devno); + + return xfer_mask; } /** @@ -3667,11 +3808,83 @@ fsm_start: } if (timeout) - ata_queue_delayed_pio_task(ap, timeout); - else if (has_next) + ata_port_queue_task(ap, ata_pio_task, ap, timeout); + else if (!qc_completed) goto fsm_start; } +/** + * atapi_packet_task - Write CDB bytes to hardware + * @_data: Port to which ATAPI device is attached. + * + * When device has indicated its readiness to accept + * a CDB, this function is called. Send the CDB. + * If DMA is to be performed, exit immediately. + * Otherwise, we are in polling mode, so poll + * status under operation succeeds or fails. + * + * LOCKING: + * Kernel thread context (may sleep) + */ + +static void atapi_packet_task(void *_data) +{ + struct ata_port *ap = _data; + struct ata_queued_cmd *qc; + u8 status; + + qc = ata_qc_from_tag(ap, ap->active_tag); + WARN_ON(qc == NULL); + WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE)); + + /* sleep-wait for BSY to clear */ + DPRINTK("busy wait\n"); + if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) { + qc->err_mask |= AC_ERR_TIMEOUT; + goto err_out; + } + + /* make sure DRQ is set */ + status = ata_chk_status(ap); + if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) { + qc->err_mask |= AC_ERR_HSM; + goto err_out; + } + + /* send SCSI cdb */ + DPRINTK("send cdb\n"); + WARN_ON(qc->dev->cdb_len < 12); + + if (qc->tf.protocol == ATA_PROT_ATAPI_DMA || + qc->tf.protocol == ATA_PROT_ATAPI_NODATA) { + unsigned long flags; + + /* Once we're done issuing command and kicking bmdma, + * irq handler takes over. To not lose irq, we need + * to clear NOINTR flag before sending cdb, but + * interrupt handler shouldn't be invoked before we're + * finished. Hence, the following locking. + */ + spin_lock_irqsave(&ap->host_set->lock, flags); + ap->flags &= ~ATA_FLAG_NOINTR; + ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); + if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) + ap->ops->bmdma_start(qc); /* initiate bmdma */ + spin_unlock_irqrestore(&ap->host_set->lock, flags); + } else { + ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1); + + /* PIO commands are handled by polling */ + ap->hsm_task_state = HSM_ST; + ata_port_queue_task(ap, ata_pio_task, ap, 0); + } + + return; + +err_out: + ata_poll_qc_complete(qc); +} + /** * ata_qc_timeout - Handle timeout of queued command * @qc: Command that timed out @@ -3700,7 +3913,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) DPRINTK("ENTER\n"); - ata_flush_pio_tasks(ap); ap->hsm_task_state = HSM_ST_IDLE; spin_lock_irqsave(&host_set->lock, flags); @@ -4010,7 +4222,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_WRITE) { /* PIO data out protocol */ ap->hsm_task_state = HSM_ST_FIRST; - ata_queue_pio_task(ap); + ata_port_queue_task(ap, ata_pio_task, ap, 0); /* always send first data block using * the ata_pio_task() codepath. @@ -4020,7 +4232,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_queue_pio_task(ap); + ata_port_queue_task(ap, ata_pio_task, ap, 0); /* if polling, ata_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. @@ -4041,7 +4253,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - ata_queue_pio_task(ap); + ata_port_queue_task(ap, atapi_packet_task, ap, 0); break; case ATA_PROT_ATAPI_DMA: @@ -4053,7 +4265,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - ata_queue_pio_task(ap); + ata_port_queue_task(ap, atapi_packet_task, ap, 0); break; default: @@ -4533,6 +4745,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) return IRQ_RETVAL(handled); } + /* * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, * without filling any other registers @@ -4752,7 +4965,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, ap->active_tag = ATA_TAG_POISON; ap->last_ctl = 0xFF; - INIT_WORK(&ap->pio_task, ata_pio_task, ap); + INIT_WORK(&ap->port_task, NULL, NULL); INIT_LIST_HEAD(&ap->eh_done_q); for (i = 0; i < ATA_MAX_DEVICES; i++) @@ -5007,11 +5220,14 @@ void ata_host_set_remove(struct ata_host_set *host_set) int ata_scsi_release(struct Scsi_Host *host) { struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + int i; DPRINTK("ENTER\n"); ap->ops->port_disable(ap); ata_host_remove(ap, 0); + for (i = 0; i < ATA_MAX_DEVICES; i++) + kfree(ap->device[i].id); DPRINTK("EXIT\n"); return 1; @@ -5215,9 +5431,11 @@ EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); EXPORT_SYMBOL_GPL(ata_std_probe_reset); EXPORT_SYMBOL_GPL(ata_drive_probe_reset); +EXPORT_SYMBOL_GPL(ata_dev_revalidate); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); EXPORT_SYMBOL_GPL(ata_busy_sleep); +EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_timed_out); @@ -5228,7 +5446,6 @@ EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_id_string); EXPORT_SYMBOL_GPL(ata_id_c_string); -EXPORT_SYMBOL_GPL(ata_dev_config); EXPORT_SYMBOL_GPL(ata_scsi_simulate); EXPORT_SYMBOL_GPL(ata_eh_qc_complete); EXPORT_SYMBOL_GPL(ata_eh_qc_retry); diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index d0bd94abb413..ccedb4536977 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -785,6 +785,8 @@ int ata_scsi_error(struct Scsi_Host *host) WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); spin_unlock_irqrestore(&ap->host_set->lock, flags); + ata_port_flush_task(ap); + ap->ops->eng_timeout(ap); WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index d822eba05f3c..f4c48c91b63d 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -45,6 +45,7 @@ extern int libata_fua; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); +extern void ata_port_flush_task(struct ata_port *ap); extern void ata_qc_free(struct ata_queued_cmd *qc); extern unsigned int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 7fa807d7d9e1..e5862ad5e6cd 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -256,6 +256,8 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, + { PCI_VENDOR_ID_PROMISE, 0x3515, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3519, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, { PCI_VENDOR_ID_PROMISE, 0x3d17, PCI_ANY_ID, PCI_ANY_ID, 0, 0, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index cdf800e3ec13..4f2a67ed39d8 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -49,24 +49,30 @@ #define DRV_VERSION "0.9" enum { + /* + * host flags + */ SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), SIL_FLAG_MOD15WRITE = (1 << 30), + SIL_DFL_HOST_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO, + /* + * Controller IDs + */ sil_3112 = 0, - sil_3112_m15w = 1, - sil_3512 = 2, - sil_3114 = 3, - - SIL_FIFO_R0 = 0x40, - SIL_FIFO_W0 = 0x41, - SIL_FIFO_R1 = 0x44, - SIL_FIFO_W1 = 0x45, - SIL_FIFO_R2 = 0x240, - SIL_FIFO_W2 = 0x241, - SIL_FIFO_R3 = 0x244, - SIL_FIFO_W3 = 0x245, + sil_3512 = 1, + sil_3114 = 2, + /* + * Register offsets + */ SIL_SYSCFG = 0x48, + + /* + * Register bits + */ + /* SYSCFG */ SIL_MASK_IDE0_INT = (1 << 22), SIL_MASK_IDE1_INT = (1 << 23), SIL_MASK_IDE2_INT = (1 << 24), @@ -75,9 +81,12 @@ enum { SIL_MASK_4PORT = SIL_MASK_2PORT | SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, - SIL_IDE2_BMDMA = 0x200, - + /* BMDMA/BMDMA2 */ SIL_INTR_STEERING = (1 << 1), + + /* + * Others + */ SIL_QUIRK_MOD15WRITE = (1 << 0), SIL_QUIRK_UDMA5MAX = (1 << 1), }; @@ -90,13 +99,13 @@ static void sil_post_set_mode (struct ata_port *ap); static const struct pci_device_id sil_pci_tbl[] = { - { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, - { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, + { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 }, { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, - { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, - { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, - { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, + { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, + { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, { } /* terminate list */ }; @@ -181,18 +190,7 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3112 */ { .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x3f, /* udma0-5 */ - .port_ops = &sil_ops, - }, - /* sil_3112_15w - keep it sync'd w/ sil_3112 */ - { - .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | SIL_FLAG_MOD15WRITE, + .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -201,9 +199,7 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3512 */ { .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | - SIL_FLAG_RERR_ON_DMA_ACT, + .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -212,9 +208,7 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3114 */ { .sht = &sil_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | - SIL_FLAG_RERR_ON_DMA_ACT, + .host_flags = SIL_DFL_HOST_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -228,16 +222,17 @@ static const struct { unsigned long tf; /* ATA taskfile register block */ unsigned long ctl; /* ATA control/altstatus register block */ unsigned long bmdma; /* DMA register block */ + unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ unsigned long scr; /* SATA control register block */ unsigned long sien; /* SATA Interrupt Enable register */ unsigned long xfer_mode;/* data transfer mode register */ unsigned long sfis_cfg; /* SATA FIS reception config register */ } sil_port[] = { /* port 0 ... */ - { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4, 0x14c }, - { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4, 0x1cc }, - { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4, 0x34c }, - { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4, 0x3cc }, + { 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c }, + { 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, + { 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, + { 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, /* ... port 3 */ }; @@ -418,13 +413,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_regions; - probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); if (probe_ent == NULL) { rc = -ENOMEM; goto err_out_regions; } - memset(probe_ent, 0, sizeof(*probe_ent)); INIT_LIST_HEAD(&probe_ent->node); probe_ent->dev = pci_dev_to_dev(pdev); probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops; @@ -461,19 +455,12 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (cls) { cls >>= 3; cls++; /* cls = (line_size/8)+1 */ - writeb(cls, mmio_base + SIL_FIFO_R0); - writeb(cls, mmio_base + SIL_FIFO_W0); - writeb(cls, mmio_base + SIL_FIFO_R1); - writeb(cls, mmio_base + SIL_FIFO_W1); - if (ent->driver_data == sil_3114) { - writeb(cls, mmio_base + SIL_FIFO_R2); - writeb(cls, mmio_base + SIL_FIFO_W2); - writeb(cls, mmio_base + SIL_FIFO_R3); - writeb(cls, mmio_base + SIL_FIFO_W3); - } + for (i = 0; i < probe_ent->n_ports; i++) + writew(cls << 8 | cls, + mmio_base + sil_port[i].fifo_cfg); } else dev_printk(KERN_WARNING, &pdev->dev, - "cache line size not set. Driver may not function\n"); + "cache line size not set. Driver may not function\n"); /* Apply R_ERR on DMA activate FIS errata workaround */ if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) { @@ -496,10 +483,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) irq_mask = SIL_MASK_4PORT; /* flip the magic "make 4 ports work" bit */ - tmp = readl(mmio_base + SIL_IDE2_BMDMA); + tmp = readl(mmio_base + sil_port[2].bmdma); if ((tmp & SIL_INTR_STEERING) == 0) writel(tmp | SIL_INTR_STEERING, - mmio_base + SIL_IDE2_BMDMA); + mmio_base + sil_port[2].bmdma); } else { irq_mask = SIL_MASK_2PORT; diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 5c5822e33a49..8fb62427be84 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -892,6 +892,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->sht = pinfo->sht; probe_ent->host_flags = pinfo->host_flags; probe_ent->pio_mask = pinfo->pio_mask; + probe_ent->mwdma_mask = pinfo->mwdma_mask; probe_ent->udma_mask = pinfo->udma_mask; probe_ent->port_ops = pinfo->port_ops; probe_ent->n_ports = SIL24_FLAG2NPORTS(pinfo->host_flags); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index 5d02ff4db6cc..b65462f76484 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -192,7 +192,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) SDev = cd->device; if (!sense) { - sense = kmalloc(sizeof(*sense), GFP_KERNEL); + sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); if (!sense) { err = -ENOMEM; goto out; diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index f3763d2ccb86..a37579ce6d76 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -2301,7 +2301,6 @@ static void receive_chars(struct uart_port *the_port) int read_count, request_count = IOC4_MAX_CHARS; struct uart_icount *icount; struct uart_info *info = the_port->info; - int flip = 0; unsigned long pflags; /* Make sure all the pointers are "good" ones */ @@ -2313,7 +2312,7 @@ static void receive_chars(struct uart_port *the_port) spin_lock_irqsave(&the_port->lock, pflags); tty = info->tty; - request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS - 2); + request_count = tty_buffer_request_room(tty, IOC4_MAX_CHARS); if (request_count > 0) { icount = &the_port->icount; @@ -2326,8 +2325,7 @@ static void receive_chars(struct uart_port *the_port) spin_unlock_irqrestore(&the_port->lock, pflags); - if (flip) - tty_flip_buffer_push(tty); + tty_flip_buffer_push(tty); } /** diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index 419dd3cd7862..193722d680cf 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -420,10 +420,8 @@ static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up, if (up->port.info == NULL) goto ack_tx_int; xmit = &up->port.info->xmit; - if (uart_circ_empty(xmit)) { - uart_write_wakeup(&up->port); + if (uart_circ_empty(xmit)) goto ack_tx_int; - } if (uart_tx_stopped(&up->port)) goto ack_tx_int; diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 95fb4939c675..cc1faa31d124 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -71,6 +71,11 @@ static void uart_change_pm(struct uart_state *state, int pm_state); void uart_write_wakeup(struct uart_port *port) { struct uart_info *info = port->info; + /* + * This means you called this function _after_ the port was + * closed. No cookie for you. + */ + BUG_ON(!info); tasklet_schedule(&info->tlet); } @@ -471,14 +476,26 @@ static void uart_flush_chars(struct tty_struct *tty) } static int -uart_write(struct tty_struct *tty, const unsigned char * buf, int count) +uart_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - struct circ_buf *circ = &state->info->xmit; + struct uart_port *port; + struct circ_buf *circ; unsigned long flags; int c, ret = 0; + /* + * This means you called this function _after_ the port was + * closed. No cookie for you. + */ + if (!state || !state->info) { + WARN_ON(1); + return -EL3HLT; + } + + port = state->port; + circ = &state->info->xmit; + if (!circ->buf) return 0; @@ -521,6 +538,15 @@ static void uart_flush_buffer(struct tty_struct *tty) struct uart_port *port = state->port; unsigned long flags; + /* + * This means you called this function _after_ the port was + * closed. No cookie for you. + */ + if (!state || !state->info) { + WARN_ON(1); + return; + } + DPRINTK("uart_flush_buffer(%d) called\n", tty->index); spin_lock_irqsave(&port->lock, flags); diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 43e67d6c29d4..60ea4a3f0713 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -820,7 +820,7 @@ static int __init sn_sal_module_init(void) int retval; if (!ia64_platform_is("sn2")) - return -ENODEV; + return 0; printk(KERN_INFO "sn_console: Console driver init\n"); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4dd6865d32b0..b5c96e74a903 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -242,8 +242,10 @@ static void serial_close(struct tty_struct *tty, struct file * filp) down(&port->sem); - if (port->open_count == 0) - goto out; + if (port->open_count == 0) { + up(&port->sem); + return; + } --port->open_count; if (port->open_count == 0) { @@ -260,10 +262,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp) module_put(port->serial->type->driver.owner); } - kref_put(&port->serial->kref, destroy_serial); - -out: up(&port->sem); + kref_put(&port->serial->kref, destroy_serial); } static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index df8e5667b348..466042808daf 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -253,7 +253,7 @@ static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper, { unsigned char *src; unsigned int xindex, yindex, chipindex, linesize; - int i, count; + int i; unsigned char val; unsigned char bitmask, rightshift; @@ -282,7 +282,6 @@ static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper, } ks108_writeb_data(par, chipindex, val); left++; - count++; if (bitmask == 0x80) { bitmask = 1; src++; @@ -460,11 +459,11 @@ static ssize_t arcfb_write(struct file *file, const char __user *buf, size_t cou inode = file->f_dentry->d_inode; fbidx = iminor(inode); info = registered_fb[fbidx]; - par = info->par; if (!info || !info->screen_base) return -ENODEV; + par = info->par; xres = info->var.xres; fbmemlength = (xres * info->var.yres)/8; diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index bfc8a93b2c73..620c9a934e0e 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1326,7 +1326,7 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, unsigned char post_dividers[] = {1,2,4,8,3,6,12}; u32 output_freq; u32 vclk; /* in .01 MHz */ - int i; + int i = 0; u32 n, d; vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */ @@ -1340,15 +1340,16 @@ static int aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll, /* now, find an acceptable divider */ for (i = 0; i < sizeof(post_dividers); i++) { output_freq = post_dividers[i] * vclk; - if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) + if (output_freq >= c.ppll_min && output_freq <= c.ppll_max) { + pll->post_divider = post_dividers[i]; break; + } } /* calculate feedback divider */ n = c.ref_divider * output_freq; d = c.ref_clk; - pll->post_divider = post_dividers[i]; pll->feedback_divider = round_div(n, d); pll->vclk = vclk; diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c index 7f9838dceab5..98c05bc0de44 100644 --- a/drivers/video/aty/radeon_monitor.c +++ b/drivers/video/aty/radeon_monitor.c @@ -396,6 +396,10 @@ static int __devinit radeon_parse_monitor_layout(struct radeonfb_info *rinfo, s1[i] = *s; i++; } + + if (i > 4) + i = 4; + } while (*s++); if (second) s2[i] = 0; diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index bd39bbd88d41..151fda8dded0 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -172,7 +172,7 @@ struct backlight_device *backlight_device_register(const char *name, void *devda new_bd = kmalloc(sizeof(struct backlight_device), GFP_KERNEL); if (unlikely(!new_bd)) - return ERR_PTR(ENOMEM); + return ERR_PTR(-ENOMEM); init_MUTEX(&new_bd->sem); new_bd->props = bp; diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 9e32485ee7bb..86908a60c630 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -171,7 +171,7 @@ struct lcd_device *lcd_device_register(const char *name, void *devdata, new_ld = kmalloc(sizeof(struct lcd_device), GFP_KERNEL); if (unlikely(!new_ld)) - return ERR_PTR(ENOMEM); + return ERR_PTR(-ENOMEM); init_MUTEX(&new_ld->sem); new_ld->props = lp; diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index ad416ae47596..7db42542eb19 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1510,6 +1510,8 @@ imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) default: printk(KERN_INFO "imsttfb: Device 0x%x unknown, " "contact maintainer.\n", pdev->device); + release_mem_region(addr, size); + framebuffer_release(info); return -ENODEV; } diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 6b8bd3cdf9c0..995b47c165a7 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1333,33 +1333,35 @@ intelfb_setcolreg(unsigned regno, unsigned red, unsigned green, if (regno > 255) return 1; - switch (dinfo->depth) { - case 8: - { - red >>= 8; - green >>= 8; - blue >>= 8; + if (dinfo->depth == 8) { + red >>= 8; + green >>= 8; + blue >>= 8; - intelfbhw_setcolreg(dinfo, regno, red, green, blue, - transp); - } - break; - case 15: - dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) | - ((green & 0xf800) >> 6) | - ((blue & 0xf800) >> 11); - break; - case 16: - dinfo->pseudo_palette[regno] = (red & 0xf800) | - ((green & 0xfc00) >> 5) | - ((blue & 0xf800) >> 11); - break; - case 24: - dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) | - (green & 0xff00) | - ((blue & 0xff00) >> 8); - break; + intelfbhw_setcolreg(dinfo, regno, red, green, blue, + transp); } + + if (regno < 16) { + switch (dinfo->depth) { + case 15: + dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) | + ((green & 0xf800) >> 6) | + ((blue & 0xf800) >> 11); + break; + case 16: + dinfo->pseudo_palette[regno] = (red & 0xf800) | + ((green & 0xfc00) >> 5) | + ((blue & 0xf800) >> 11); + break; + case 24: + dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) | + (green & 0xff00) | + ((blue & 0xff00) >> 8); + break; + } + } + return 0; } diff --git a/drivers/video/kyro/STG4000VTG.c b/drivers/video/kyro/STG4000VTG.c index 3690b04190af..bd389709d234 100644 --- a/drivers/video/kyro/STG4000VTG.c +++ b/drivers/video/kyro/STG4000VTG.c @@ -17,7 +17,7 @@ void DisableVGA(volatile STG4000REG __iomem *pSTGReg) { u32 tmp; - volatile u32 count, i; + volatile u32 count = 0, i; /* Reset the VGA registers */ tmp = STG_READ_REG(SoftwareReset); diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index a2e201dc40f7..b961d5601bd9 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -486,10 +486,8 @@ static void vgaHWRestore(const struct fb_info *info, static inline int neo2200_sync(struct fb_info *info) { struct neofb_par *par = info->par; - int waitcycles; - while (readl(&par->neo2200->bltStat) & 1) - waitcycles++; + while (readl(&par->neo2200->bltStat) & 1); return 0; } diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index e5d0f92eeae3..feec47bdd479 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -588,6 +588,7 @@ s1d13xxxfb_probe(struct platform_device *pdev) goto bail; } + platform_set_drvdata(pdev, info); default_par = info->par; default_par->regs = ioremap_nocache(pdev->resource[1].start, pdev->resource[1].end - pdev->resource[1].start +1); @@ -638,8 +639,6 @@ s1d13xxxfb_probe(struct platform_device *pdev) goto bail; } - platform_set_drvdata(pdev, info); - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index ab727eaa7f43..10e6b3aab9ea 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -2021,8 +2021,8 @@ static int __devinit savagefb_probe (struct pci_dev* dev, #if defined(CONFIG_FB_SAVAGE_I2C) savagefb_create_i2c_busses(info); savagefb_probe_i2c_connector(info, &par->edid); - kfree(par->edid); fb_edid_to_monspecs(par->edid, &info->monspecs); + kfree(par->edid); fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len, &info->modelist); diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 3e7baf4c9fa8..5e5328d682db 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -786,28 +786,32 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green, if (regno >= info->cmap.len || regno > 255) return 1; switch (info->fix.visual) { - case FB_VISUAL_PSEUDOCOLOR: - rgbcol =(((u32)red & 0xff00) << 8) | - (((u32)green & 0xff00) << 0) | - (((u32)blue & 0xff00) >> 8); - do_setpalentry(par, regno, rgbcol); - break; - /* Truecolor has no hardware color palettes. */ - case FB_VISUAL_TRUECOLOR: + case FB_VISUAL_PSEUDOCOLOR: + rgbcol =(((u32)red & 0xff00) << 8) | + (((u32)green & 0xff00) << 0) | + (((u32)blue & 0xff00) >> 8); + do_setpalentry(par, regno, rgbcol); + break; + /* Truecolor has no hardware color palettes. */ + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { rgbcol = (CNVT_TOHW( red, info->var.red.length) << info->var.red.offset) | - (CNVT_TOHW( green, info->var.green.length) << - info->var.green.offset) | - (CNVT_TOHW( blue, info->var.blue.length) << - info->var.blue.offset) | - (CNVT_TOHW( transp, info->var.transp.length) << - info->var.transp.offset); - par->palette[regno] = rgbcol; - break; - default: - DPRINTK("bad depth %u\n", info->var.bits_per_pixel); - break; + (CNVT_TOHW( green, info->var.green.length) << + info->var.green.offset) | + (CNVT_TOHW( blue, info->var.blue.length) << + info->var.blue.offset) | + (CNVT_TOHW( transp, info->var.transp.length) << + info->var.transp.offset); + par->palette[regno] = rgbcol; + } + + break; + default: + DPRINTK("bad depth %u\n", info->var.bits_per_pixel); + break; } + return 0; } diff --git a/fs/9p/9p.c b/fs/9p/9p.c index 1a6d08761f39..f86a28d1d6a6 100644 --- a/fs/9p/9p.c +++ b/fs/9p/9p.c @@ -111,7 +111,6 @@ static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc, if (!rc) return; - dprintk(DEBUG_9P, "tcall id %d rcall id %d\n", tc->id, rc->id); v9ses = a; if (rc->id == RCLUNK) v9fs_put_idpool(fid, &v9ses->fidpool); diff --git a/fs/9p/fid.c b/fs/9p/fid.c index eda449778fa5..c4d13bf904d2 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -1,7 +1,7 @@ /* * V9FS FID Management * - * Copyright (C) 2005 by Eric Van Hensbergen + * Copyright (C) 2005, 2006 by Eric Van Hensbergen * * 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 @@ -40,7 +40,7 @@ * */ -static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) +int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) { struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid, @@ -57,7 +57,6 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) } fid->uid = current->uid; - fid->pid = current->pid; list_add(&fid->list, fid_list); return 0; } @@ -68,14 +67,11 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry) * */ -struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, - struct v9fs_session_info *v9ses, int fid, int create) +struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid) { struct v9fs_fid *new; - dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n", - dentry, fid, create); - + dprintk(DEBUG_9P, "fid create fid %d\n", fid); new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); if (new == NULL) { dprintk(DEBUG_ERROR, "Out of Memory\n"); @@ -85,19 +81,13 @@ struct v9fs_fid *v9fs_fid_create(struct dentry *dentry, new->fid = fid; new->v9ses = v9ses; new->fidopen = 0; - new->fidcreate = create; new->fidclunked = 0; new->iounit = 0; new->rdir_pos = 0; new->rdir_fcall = NULL; + INIT_LIST_HEAD(&new->list); - if (v9fs_fid_insert(new, dentry) == 0) - return new; - else { - dprintk(DEBUG_ERROR, "Problems inserting to dentry\n"); - kfree(new); - return NULL; - } + return new; } /** @@ -112,141 +102,30 @@ void v9fs_fid_destroy(struct v9fs_fid *fid) kfree(fid); } -/** - * v9fs_fid_walk_up - walks from the process current directory - * up to the specified dentry. - */ -static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry) -{ - int fidnum, cfidnum, err; - struct v9fs_fid *cfid; - struct dentry *cde; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(current->fs->pwd->d_inode); - cfid = v9fs_fid_lookup(current->fs->pwd); - if (cfid == NULL) { - dprintk(DEBUG_ERROR, "process cwd doesn't have a fid\n"); - return ERR_PTR(-ENOENT); - } - - cfidnum = cfid->fid; - cde = current->fs->pwd; - /* TODO: take advantage of multiwalk */ - - fidnum = v9fs_get_idpool(&v9ses->fidpool); - if (fidnum < 0) { - dprintk(DEBUG_ERROR, "could not get a new fid num\n"); - err = -ENOENT; - goto clunk_fid; - } - - while (cde != dentry) { - if (cde == cde->d_parent) { - dprintk(DEBUG_ERROR, "can't find dentry\n"); - err = -ENOENT; - goto clunk_fid; - } - - err = v9fs_t_walk(v9ses, cfidnum, fidnum, "..", NULL); - if (err < 0) { - dprintk(DEBUG_ERROR, "problem walking to parent\n"); - goto clunk_fid; - } - - cfidnum = fidnum; - cde = cde->d_parent; - } - - return v9fs_fid_create(dentry, v9ses, fidnum, 0); - -clunk_fid: - v9fs_t_clunk(v9ses, fidnum); - return ERR_PTR(err); -} - /** * v9fs_fid_lookup - retrieve the right fid from a particular dentry * @dentry: dentry to look for fid in * @type: intent of lookup (operation or traversal) * - * search list of fids associated with a dentry for a fid with a matching - * thread id or uid. If that fails, look up the dentry's parents to see if you - * can find a matching fid. + * find a fid in the dentry + * + * TODO: only match fids that have the same uid as current user * */ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry) { struct list_head *fid_list = (struct list_head *)dentry->d_fsdata; - struct v9fs_fid *current_fid = NULL; - struct v9fs_fid *temp = NULL; struct v9fs_fid *return_fid = NULL; dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); - if (fid_list) { - list_for_each_entry_safe(current_fid, temp, fid_list, list) { - if (!current_fid->fidcreate) { - return_fid = current_fid; - break; - } - } - - if (!return_fid) - return_fid = current_fid; - } - - /* we are at the root but didn't match */ - if ((!return_fid) && (dentry->d_parent == dentry)) { - /* TODO: clone attach with new uid */ - return_fid = current_fid; - } + if (fid_list) + return_fid = list_entry(fid_list->next, struct v9fs_fid, list); if (!return_fid) { - struct dentry *par = current->fs->pwd->d_parent; - int count = 1; - while (par != NULL) { - if (par == dentry) - break; - count++; - if (par == par->d_parent) { - dprintk(DEBUG_ERROR, - "got to root without finding dentry\n"); - break; - } - par = par->d_parent; - } - -/* XXX - there may be some duplication we can get rid of */ - if (par == dentry) { - return_fid = v9fs_fid_walk_up(dentry); - if (IS_ERR(return_fid)) - return_fid = NULL; - } + dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n"); } return return_fid; } - -struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry) -{ - struct list_head *fid_list; - struct v9fs_fid *fid, *ftmp, *ret; - - dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry); - fid_list = (struct list_head *)dentry->d_fsdata; - ret = NULL; - if (fid_list) { - list_for_each_entry_safe(fid, ftmp, fid_list, list) { - if (fid->fidcreate && fid->pid == current->pid) { - list_del(&fid->list); - ret = fid; - break; - } - } - } - - dprintk(DEBUG_9P, "return %p\n", ret); - return ret; -} diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 84c673a44c83..1fc2dd08d75a 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h @@ -33,7 +33,6 @@ struct v9fs_fid { u32 fid; unsigned char fidopen; /* set when fid is opened */ - unsigned char fidcreate; /* set when fid was just created */ unsigned char fidclunked; /* set when fid has already been clunked */ struct v9fs_qid qid; @@ -45,7 +44,6 @@ struct v9fs_fid { struct v9fs_fcall *rdir_fcall; /* management stuff */ - pid_t pid; /* thread associated with this fid */ uid_t uid; /* user associated with this fid */ /* private data */ @@ -56,5 +54,5 @@ struct v9fs_fid { struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry); struct v9fs_fid *v9fs_fid_get_created(struct dentry *); void v9fs_fid_destroy(struct v9fs_fid *fid); -struct v9fs_fid *v9fs_fid_create(struct dentry *, - struct v9fs_session_info *v9ses, int fid, int create); +struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid); +int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry); diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c index 1a28ef97a3d1..5b2ce21b10fa 100644 --- a/fs/9p/trans_fd.c +++ b/fs/9p/trans_fd.c @@ -80,6 +80,7 @@ static int v9fs_fd_send(struct v9fs_transport *trans, void *v, int len) if (!trans || trans->status != Connected || !ts) return -EIO; + oldfs = get_fs(); set_fs(get_ds()); /* The cast to a user pointer is valid due to the set_fs() */ ret = vfs_write(ts->out_file, (void __user *)v, len, &ts->out_file->f_pos); diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index ef3386549140..61352491ba36 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -397,6 +397,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses, } if (v9ses->afid != ~0) { + dprintk(DEBUG_ERROR, "afid not equal to ~0\n"); if (v9fs_t_clunk(v9ses, v9ses->afid)) dprintk(DEBUG_ERROR, "clunk failed\n"); } diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 69cf2905dc90..a759278acaae 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -51,3 +51,4 @@ int v9fs_dir_release(struct inode *inode, struct file *filp); int v9fs_file_open(struct inode *inode, struct file *file); void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat); void v9fs_dentry_release(struct dentry *); +int v9fs_uflags2omode(int uflags); diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 2dd806dac9f1..12c9cc926b71 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -43,47 +43,18 @@ #include "fid.h" /** - * v9fs_dentry_validate - VFS dcache hook to validate cache - * @dentry: dentry that is being validated - * @nd: path data + * v9fs_dentry_delete - called when dentry refcount equals 0 + * @dentry: dentry in question * - * dcache really shouldn't be used for 9P2000 as at all due to - * potential attached semantics to directory traversal (walk). - * - * FUTURE: look into how to use dcache to allow multi-stage - * walks in Plan 9 & potential for better dcache operation which - * would remain valid for Plan 9 semantics. Older versions - * had validation via stat for those interested. However, since - * stat has the same approximate overhead as walk there really - * is no difference. The only improvement would be from a - * time-decay cache like NFS has and that undermines the - * synchronous nature of 9P2000. + * By returning 1 here we should remove cacheing of unused + * dentry components. * */ -static int v9fs_dentry_validate(struct dentry *dentry, struct nameidata *nd) +int v9fs_dentry_delete(struct dentry *dentry) { - struct dentry *dc = current->fs->pwd; - - dprintk(DEBUG_VFS, "dentry: %s (%p)\n", dentry->d_iname, dentry); - if (v9fs_fid_lookup(dentry)) { - dprintk(DEBUG_VFS, "VALID\n"); - return 1; - } - - while (dc != NULL) { - if (dc == dentry) { - dprintk(DEBUG_VFS, "VALID\n"); - return 1; - } - if (dc == dc->d_parent) - break; - - dc = dc->d_parent; - } - - dprintk(DEBUG_VFS, "INVALID\n"); - return 0; + dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); + return 1; } /** @@ -118,6 +89,6 @@ void v9fs_dentry_release(struct dentry *dentry) } struct dentry_operations v9fs_dentry_operations = { - .d_revalidate = v9fs_dentry_validate, + .d_delete = v9fs_dentry_delete, .d_release = v9fs_dentry_release, }; diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index c7e14d917215..de3a129698da 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -53,94 +53,70 @@ int v9fs_file_open(struct inode *inode, struct file *file) { struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - struct v9fs_fid *v9fid, *fid; + struct v9fs_fid *vfid; struct v9fs_fcall *fcall = NULL; - int open_mode = 0; - unsigned int iounit = 0; - int newfid = -1; - long result = -1; + int omode; + int fid = V9FS_NOFID; + int err; dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file); - v9fid = v9fs_fid_get_created(file->f_dentry); - if (!v9fid) - v9fid = v9fs_fid_lookup(file->f_dentry); - - if (!v9fid) { + vfid = v9fs_fid_lookup(file->f_dentry); + if (!vfid) { dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n"); return -EBADF; } - if (!v9fid->fidcreate) { - fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); - if (fid == NULL) { - dprintk(DEBUG_ERROR, "Out of Memory\n"); - return -ENOMEM; - } - - fid->fidopen = 0; - fid->fidcreate = 0; - fid->fidclunked = 0; - fid->iounit = 0; - fid->v9ses = v9ses; - - newfid = v9fs_get_idpool(&v9ses->fidpool); - if (newfid < 0) { + fid = v9fs_get_idpool(&v9ses->fidpool); + if (fid < 0) { eprintk(KERN_WARNING, "newfid fails!\n"); return -ENOSPC; } - result = - v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL); - - if (result < 0) { - v9fs_put_idpool(newfid, &v9ses->fidpool); + err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL); + if (err < 0) { dprintk(DEBUG_ERROR, "rewalk didn't work\n"); - return -EBADF; - } - - fid->fid = newfid; - v9fid = fid; - /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ - /* translate open mode appropriately */ - open_mode = file->f_flags & 0x3; - - if (file->f_flags & O_EXCL) - open_mode |= V9FS_OEXCL; - - if (v9ses->extended) { - if (file->f_flags & O_TRUNC) - open_mode |= V9FS_OTRUNC; - - if (file->f_flags & O_APPEND) - open_mode |= V9FS_OAPPEND; - } - - result = v9fs_t_open(v9ses, newfid, open_mode, &fcall); - if (result < 0) { - PRINT_FCALL_ERROR("open failed", fcall); - kfree(fcall); - return result; - } - - iounit = fcall->params.ropen.iounit; - kfree(fcall); - } else { - /* create case */ - newfid = v9fid->fid; - iounit = v9fid->iounit; - v9fid->fidcreate = 0; + goto put_fid; } - file->private_data = v9fid; + vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL); + if (vfid == NULL) { + dprintk(DEBUG_ERROR, "out of memory\n"); + goto clunk_fid; + } - v9fid->rdir_pos = 0; - v9fid->rdir_fcall = NULL; - v9fid->fidopen = 1; - v9fid->filp = file; - v9fid->iounit = iounit; + /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */ + /* translate open mode appropriately */ + omode = v9fs_uflags2omode(file->f_flags); + err = v9fs_t_open(v9ses, fid, omode, &fcall); + if (err < 0) { + PRINT_FCALL_ERROR("open failed", fcall); + goto destroy_vfid; + } + + file->private_data = vfid; + vfid->fid = fid; + vfid->fidopen = 1; + vfid->fidclunked = 0; + vfid->iounit = fcall->params.ropen.iounit; + vfid->rdir_pos = 0; + vfid->rdir_fcall = NULL; + vfid->filp = file; + kfree(fcall); return 0; + +destroy_vfid: + v9fs_fid_destroy(vfid); + +clunk_fid: + v9fs_t_clunk(v9ses, fid); + +put_fid: + v9fs_put_idpool(fid, &v9ses->fidpool); + kfree(fcall); + + return err; } /** @@ -289,9 +265,7 @@ v9fs_file_write(struct file *filp, const char __user * data, total += result; } while (count); - if(inode->i_mapping->nrpages) invalidate_inode_pages2(inode->i_mapping); - return total; } diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 63e5b0398e8b..3ad8455f8577 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -125,6 +125,38 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) return res; } +int v9fs_uflags2omode(int uflags) +{ + int ret; + + ret = 0; + switch (uflags&3) { + default: + case O_RDONLY: + ret = V9FS_OREAD; + break; + + case O_WRONLY: + ret = V9FS_OWRITE; + break; + + case O_RDWR: + ret = V9FS_ORDWR; + break; + } + + if (uflags & O_EXCL) + ret |= V9FS_OEXCL; + + if (uflags & O_TRUNC) + ret |= V9FS_OTRUNC; + + if (uflags & O_APPEND) + ret |= V9FS_OAPPEND; + + return ret; +} + /** * v9fs_blank_wstat - helper function to setup a 9P stat structure * @v9ses: 9P session info (for determining extended mode) @@ -163,7 +195,7 @@ v9fs_blank_wstat(struct v9fs_wstat *wstat) struct inode *v9fs_get_inode(struct super_block *sb, int mode) { - struct inode *inode = NULL; + struct inode *inode; struct v9fs_session_info *v9ses = sb->s_fs_info; dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode); @@ -222,171 +254,133 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) return inode; } -/** - * v9fs_create - helper function to create files and directories - * @dir: directory inode file is being created in - * @file_dentry: dentry file is being created in - * @perm: permissions file is being created with - * @open_mode: resulting open mode for file - * - */ - static int -v9fs_create(struct inode *dir, - struct dentry *file_dentry, - unsigned int perm, unsigned int open_mode) +v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, + u32 perm, u8 mode, u32 *fidp, struct v9fs_qid *qid, u32 *iounit) { - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); - struct super_block *sb = dir->i_sb; - struct v9fs_fid *dirfid = - v9fs_fid_lookup(file_dentry->d_parent); - struct v9fs_fid *fid = NULL; - struct inode *file_inode = NULL; - struct v9fs_fcall *fcall = NULL; - struct v9fs_qid qid; - int dirfidnum = -1; - long newfid = -1; - int result = 0; - unsigned int iounit = 0; - int wfidno = -1; + u32 fid; int err; + struct v9fs_fcall *fcall; - perm = unixmode2p9mode(v9ses, perm); - - dprintk(DEBUG_VFS, "dir: %p dentry: %p perm: %o mode: %o\n", dir, - file_dentry, perm, open_mode); - - if (!dirfid) - return -EBADF; - - dirfidnum = dirfid->fid; - if (dirfidnum < 0) { - dprintk(DEBUG_ERROR, "No fid for the directory #%lu\n", - dir->i_ino); - return -EBADF; - } - - if (file_dentry->d_inode) { - dprintk(DEBUG_ERROR, - "Odd. There is an inode for dir %lu, name :%s:\n", - dir->i_ino, file_dentry->d_name.name); - return -EEXIST; - } - - newfid = v9fs_get_idpool(&v9ses->fidpool); - if (newfid < 0) { + fid = v9fs_get_idpool(&v9ses->fidpool); + if (fid < 0) { eprintk(KERN_WARNING, "no free fids available\n"); return -ENOSPC; } - result = v9fs_t_walk(v9ses, dirfidnum, newfid, NULL, &fcall); - if (result < 0) { + err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall); + if (err < 0) { PRINT_FCALL_ERROR("clone error", fcall); - v9fs_put_idpool(newfid, &v9ses->fidpool); - newfid = -1; - goto CleanUpFid; + goto error; } - kfree(fcall); - fcall = NULL; - result = v9fs_t_create(v9ses, newfid, (char *)file_dentry->d_name.name, - perm, open_mode, &fcall); - if (result < 0) { + err = v9fs_t_create(v9ses, fid, name, perm, mode, &fcall); + if (err < 0) { PRINT_FCALL_ERROR("create fails", fcall); - goto CleanUpFid; + goto error; } - iounit = fcall->params.rcreate.iounit; - qid = fcall->params.rcreate.qid; + if (iounit) + *iounit = fcall->params.rcreate.iounit; + + if (qid) + *qid = fcall->params.rcreate.qid; + + if (fidp) + *fidp = fid; + kfree(fcall); - fcall = NULL; - - if (!(perm&V9FS_DMDIR)) { - fid = v9fs_fid_create(file_dentry, v9ses, newfid, 1); - dprintk(DEBUG_VFS, "fid %p %d\n", fid, fid->fidcreate); - if (!fid) { - result = -ENOMEM; - goto CleanUpFid; - } - - fid->qid = qid; - fid->iounit = iounit; - } else { - err = v9fs_t_clunk(v9ses, newfid); - newfid = -1; - if (err < 0) - dprintk(DEBUG_ERROR, "clunk for mkdir failed: %d\n", err); - } - - /* walk to the newly created file and put the fid in the dentry */ - wfidno = v9fs_get_idpool(&v9ses->fidpool); - if (wfidno < 0) { - eprintk(KERN_WARNING, "no free fids available\n"); - return -ENOSPC; - } - - result = v9fs_t_walk(v9ses, dirfidnum, wfidno, - (char *) file_dentry->d_name.name, &fcall); - if (result < 0) { - PRINT_FCALL_ERROR("clone error", fcall); - v9fs_put_idpool(wfidno, &v9ses->fidpool); - wfidno = -1; - goto CleanUpFid; - } - kfree(fcall); - fcall = NULL; - - if (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) { - v9fs_put_idpool(wfidno, &v9ses->fidpool); - - goto CleanUpFid; - } - - if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) || - (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) || - (perm & V9FS_DMDEVICE)) - return 0; - - result = v9fs_t_stat(v9ses, wfidno, &fcall); - if (result < 0) { - PRINT_FCALL_ERROR("stat error", fcall); - goto CleanUpFid; - } - - - file_inode = v9fs_get_inode(sb, - p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode)); - - if ((!file_inode) || IS_ERR(file_inode)) { - dprintk(DEBUG_ERROR, "create inode failed\n"); - result = -EBADF; - goto CleanUpFid; - } - - v9fs_stat2inode(&fcall->params.rstat.stat, file_inode, sb); - kfree(fcall); - fcall = NULL; - file_dentry->d_op = &v9fs_dentry_operations; - d_instantiate(file_dentry, file_inode); - return 0; - CleanUpFid: +error: + if (fid >= 0) + v9fs_put_idpool(fid, &v9ses->fidpool); + + kfree(fcall); + return err; +} + +static struct v9fs_fid* +v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) +{ + int err; + u32 nfid; + struct v9fs_fid *ret; + struct v9fs_fcall *fcall; + + nfid = v9fs_get_idpool(&v9ses->fidpool); + if (nfid < 0) { + eprintk(KERN_WARNING, "no free fids available\n"); + return ERR_PTR(-ENOSPC); + } + + err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, + &fcall); + + if (err < 0) { + PRINT_FCALL_ERROR("walk error", fcall); + v9fs_put_idpool(nfid, &v9ses->fidpool); + goto error; + } + kfree(fcall); fcall = NULL; + ret = v9fs_fid_create(v9ses, nfid); + if (!ret) { + err = -ENOMEM; + goto clunk_fid; + } - if (newfid >= 0) { - err = v9fs_t_clunk(v9ses, newfid); - if (err < 0) - dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); + err = v9fs_fid_insert(ret, dentry); + if (err < 0) { + v9fs_fid_destroy(ret); + goto clunk_fid; } - if (wfidno >= 0) { - err = v9fs_t_clunk(v9ses, wfidno); - if (err < 0) - dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); + + return ret; + +clunk_fid: + v9fs_t_clunk(v9ses, nfid); + +error: + kfree(fcall); + return ERR_PTR(err); +} + +struct inode * +v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid, + struct super_block *sb) +{ + int err, umode; + struct inode *ret; + struct v9fs_fcall *fcall; + + ret = NULL; + err = v9fs_t_stat(v9ses, fid, &fcall); + if (err) { + PRINT_FCALL_ERROR("stat error", fcall); + goto error; } - return result; + + umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode); + ret = v9fs_get_inode(sb, umode); + if (IS_ERR(ret)) { + err = PTR_ERR(ret); + ret = NULL; + goto error; + } + + v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb); + kfree(fcall); + return ret; + +error: + kfree(fcall); + if (ret) + iput(ret); + + return ERR_PTR(err); } /** @@ -440,20 +434,97 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) return result; } +static int +v9fs_open_created(struct inode *inode, struct file *file) +{ + return 0; +} + /** * v9fs_vfs_create - VFS hook to create files * @inode: directory inode that is being deleted * @dentry: dentry that is being deleted - * @perm: create permissions + * @mode: create permissions * @nd: path information * */ static int -v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, +v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { - return v9fs_create(inode, dentry, perm, O_RDWR); + int err; + u32 fid, perm, iounit; + int flags; + struct v9fs_session_info *v9ses; + struct v9fs_fid *dfid, *vfid, *ffid; + struct inode *inode; + struct v9fs_qid qid; + struct file *filp; + + inode = NULL; + vfid = NULL; + v9ses = v9fs_inode2v9ses(dir); + dfid = v9fs_fid_lookup(dentry->d_parent); + perm = unixmode2p9mode(v9ses, mode); + + if (nd && nd->flags & LOOKUP_OPEN) + flags = nd->intent.open.flags - 1; + else + flags = O_RDWR; + + err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, + perm, v9fs_uflags2omode(flags), &fid, &qid, &iounit); + + if (err) + goto error; + + vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); + if (IS_ERR(vfid)) { + err = PTR_ERR(vfid); + vfid = NULL; + goto error; + } + + inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + inode = NULL; + goto error; + } + + dentry->d_op = &v9fs_dentry_operations; + d_instantiate(dentry, inode); + + if (nd && nd->flags & LOOKUP_OPEN) { + ffid = v9fs_fid_create(v9ses, fid); + if (!ffid) + return -ENOMEM; + + filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); + if (IS_ERR(filp)) { + v9fs_fid_destroy(ffid); + return PTR_ERR(filp); + } + + ffid->rdir_pos = 0; + ffid->rdir_fcall = NULL; + ffid->fidopen = 1; + ffid->iounit = iounit; + ffid->filp = filp; + filp->private_data = ffid; + } + + return 0; + +error: + if (vfid) + v9fs_fid_destroy(vfid); + + if (inode) + iput(inode); + + return err; } /** @@ -464,9 +535,57 @@ v9fs_vfs_create(struct inode *inode, struct dentry *dentry, int perm, * */ -static int v9fs_vfs_mkdir(struct inode *inode, struct dentry *dentry, int mode) +static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) { - return v9fs_create(inode, dentry, mode | S_IFDIR, O_RDONLY); + int err; + u32 fid, perm; + struct v9fs_session_info *v9ses; + struct v9fs_fid *dfid, *vfid; + struct inode *inode; + + inode = NULL; + vfid = NULL; + v9ses = v9fs_inode2v9ses(dir); + dfid = v9fs_fid_lookup(dentry->d_parent); + perm = unixmode2p9mode(v9ses, mode | S_IFDIR); + + err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, + perm, V9FS_OREAD, &fid, NULL, NULL); + + if (err) { + dprintk(DEBUG_ERROR, "create error %d\n", err); + goto error; + } + + err = v9fs_t_clunk(v9ses, fid); + if (err) { + dprintk(DEBUG_ERROR, "clunk error %d\n", err); + goto error; + } + + vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); + if (IS_ERR(vfid)) { + err = PTR_ERR(vfid); + vfid = NULL; + goto error; + } + + inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + inode = NULL; + goto error; + } + + dentry->d_op = &v9fs_dentry_operations; + d_instantiate(dentry, inode); + return 0; + +error: + if (vfid) + v9fs_fid_destroy(vfid); + + return err; } /** @@ -491,7 +610,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, int result = 0; dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", - dir, dentry->d_iname, dentry, nameidata); + dir, dentry->d_name.name, dentry, nameidata); sb = dir->i_sb; v9ses = v9fs_inode2v9ses(dir); @@ -516,9 +635,8 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, return ERR_PTR(-ENOSPC); } - result = - v9fs_t_walk(v9ses, dirfidnum, newfid, (char *)dentry->d_name.name, - NULL); + result = v9fs_t_walk(v9ses, dirfidnum, newfid, + (char *)dentry->d_name.name, NULL); if (result < 0) { v9fs_put_idpool(newfid, &v9ses->fidpool); if (result == -ENOENT) { @@ -551,13 +669,17 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); - fid = v9fs_fid_create(dentry, v9ses, newfid, 0); + fid = v9fs_fid_create(v9ses, newfid); if (fid == NULL) { dprintk(DEBUG_ERROR, "couldn't insert\n"); result = -ENOMEM; goto FreeFcall; } + result = v9fs_fid_insert(fid, dentry); + if (result < 0) + goto FreeFcall; + fid->qid = fcall->params.rstat.stat.qid; dentry->d_op = &v9fs_dentry_operations; @@ -886,8 +1008,8 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) } /* copy extension buffer into buffer */ - if (fcall->params.rstat.stat.extension.len+1 < buflen) - buflen = fcall->params.rstat.stat.extension.len + 1; + if (fcall->params.rstat.stat.extension.len < buflen) + buflen = fcall->params.rstat.stat.extension.len; memcpy(buffer, fcall->params.rstat.stat.extension.str, buflen - 1); buffer[buflen-1] = 0; @@ -951,7 +1073,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) if (!link) link = ERR_PTR(-ENOMEM); else { - len = v9fs_readlink(dentry, link, PATH_MAX); + len = v9fs_readlink(dentry, link, strlen(link)); if (len < 0) { __putname(link); @@ -983,53 +1105,75 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, int mode, const char *extension) { - int err, retval; + int err; + u32 fid, perm; struct v9fs_session_info *v9ses; + struct v9fs_fid *dfid, *vfid; + struct inode *inode; struct v9fs_fcall *fcall; - struct v9fs_fid *fid; struct v9fs_wstat wstat; - v9ses = v9fs_inode2v9ses(dir); - retval = -EPERM; fcall = NULL; + inode = NULL; + vfid = NULL; + v9ses = v9fs_inode2v9ses(dir); + dfid = v9fs_fid_lookup(dentry->d_parent); + perm = unixmode2p9mode(v9ses, mode); if (!v9ses->extended) { dprintk(DEBUG_ERROR, "not extended\n"); - goto free_mem; + return -EPERM; } - /* issue a create */ - retval = v9fs_create(dir, dentry, mode, 0); - if (retval != 0) - goto free_mem; + err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name, + perm, V9FS_OREAD, &fid, NULL, NULL); - fid = v9fs_fid_get_created(dentry); - if (!fid) { - dprintk(DEBUG_ERROR, "couldn't resolve fid from dentry\n"); - goto free_mem; + if (err) + goto error; + + err = v9fs_t_clunk(v9ses, fid); + if (err) + goto error; + + vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry); + if (IS_ERR(vfid)) { + err = PTR_ERR(vfid); + vfid = NULL; + goto error; + } + + inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + inode = NULL; + goto error; } /* issue a Twstat */ v9fs_blank_wstat(&wstat); wstat.muid = v9ses->name; wstat.extension = (char *) extension; - retval = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall); - if (retval < 0) { - PRINT_FCALL_ERROR("wstat error", fcall); - goto free_mem; - } - - err = v9fs_t_clunk(v9ses, fid->fid); + err = v9fs_t_wstat(v9ses, vfid->fid, &wstat, &fcall); if (err < 0) { - dprintk(DEBUG_ERROR, "clunk failed: %d\n", err); - goto free_mem; + PRINT_FCALL_ERROR("wstat error", fcall); + goto error; } - d_drop(dentry); /* FID - will this also clunk? */ - -free_mem: kfree(fcall); - return retval; + dentry->d_op = &v9fs_dentry_operations; + d_instantiate(dentry, inode); + return 0; + +error: + kfree(fcall); + if (vfid) + v9fs_fid_destroy(vfid); + + if (inode) + iput(inode); + + return err; + } /** diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 2c4fa75be025..d05318fa684e 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -146,7 +146,6 @@ static struct super_block *v9fs_get_sb(struct file_system_type inode->i_gid = gid; root = d_alloc_root(inode); - if (!root) { retval = -ENOMEM; goto put_back_sb; @@ -158,15 +157,20 @@ static struct super_block *v9fs_get_sb(struct file_system_type if (stat_result < 0) { dprintk(DEBUG_ERROR, "stat error\n"); v9fs_t_clunk(v9ses, newfid); - v9fs_put_idpool(newfid, &v9ses->fidpool); } else { /* Setup the Root Inode */ - root_fid = v9fs_fid_create(root, v9ses, newfid, 0); + root_fid = v9fs_fid_create(v9ses, newfid); if (root_fid == NULL) { retval = -ENOMEM; goto put_back_sb; } + retval = v9fs_fid_insert(root_fid, root); + if (retval < 0) { + kfree(fcall); + goto put_back_sb; + } + root_fid->qid = fcall->params.rstat.stat.qid; root->d_inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 3c03aadaff0c..7b25463d3c14 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -52,7 +52,7 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, int * /* type of buf returned */ , const int long_op); extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); -extern int is_valid_oplock_break(struct smb_hdr *smb); +extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); extern int is_size_safe_to_change(struct cifsInodeInfo *); extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *); extern unsigned int smbCalcSize(struct smb_hdr *ptr); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ef5ae6f93c75..2a0c1f4ca0ae 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -630,7 +630,7 @@ multi_t2_fnd: smallbuf = NULL; } wake_up_process(task_to_wake); - } else if ((is_valid_oplock_break(smb_buffer) == FALSE) + } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE) && (isMultiRsp == FALSE)) { cERROR(1, ("No task to wake, unknown frame rcvd!")); cifs_dump_mem("Received Data is: ",(char *)smb_buffer, diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 812c6bb0fe38..432ba15e2c2d 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -475,7 +475,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) return 0; } int -is_valid_oplock_break(struct smb_hdr *buf) +is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) { struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf; struct list_head *tmp; @@ -535,7 +535,7 @@ is_valid_oplock_break(struct smb_hdr *buf) read_lock(&GlobalSMBSeslock); list_for_each(tmp, &GlobalTreeConnectionList) { tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); - if (tcon->tid == buf->Tid) { + if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) { cifs_stats_inc(&tcon->num_oplock_brks); list_for_each(tmp1,&tcon->openFileList){ netfile = list_entry(tmp1,struct cifsFileInfo, diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 537ac70edfe5..c666769a875d 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -446,7 +446,7 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) ifr = ifc.ifc_req; ifr32 = compat_ptr(ifc32.ifcbuf); for (i = 0, j = 0; - i + sizeof (struct ifreq32) < ifc32.ifc_len && j < ifc.ifc_len; + i + sizeof (struct ifreq32) <= ifc32.ifc_len && j < ifc.ifc_len; i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { if (copy_in_user(ifr32, ifr, sizeof (struct ifreq32))) return -EFAULT; diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 7fe85415ae7c..8ad52f5bf255 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -36,7 +36,7 @@ static DECLARE_MUTEX(read_mutex); /* These two macros may change in future, to provide better st_ino semantics. */ -#define CRAMINO(x) ((x)->offset?(x)->offset<<2:1) +#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1) #define OFFSET(x) ((x)->i_ino) @@ -66,8 +66,36 @@ static int cramfs_iget5_test(struct inode *inode, void *opaque) static int cramfs_iget5_set(struct inode *inode, void *opaque) { + static struct timespec zerotime; struct cramfs_inode *cramfs_inode = opaque; + inode->i_mode = cramfs_inode->mode; + inode->i_uid = cramfs_inode->uid; + inode->i_size = cramfs_inode->size; + inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; + inode->i_blksize = PAGE_CACHE_SIZE; + inode->i_gid = cramfs_inode->gid; + /* Struct copy intentional */ + inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; inode->i_ino = CRAMINO(cramfs_inode); + /* inode->i_nlink is left 1 - arguably wrong for directories, + but it's the best we can do without reading the directory + contents. 1 yields the right result in GNU find, even + without -noleaf option. */ + if (S_ISREG(inode->i_mode)) { + inode->i_fop = &generic_ro_fops; + inode->i_data.a_ops = &cramfs_aops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &cramfs_dir_inode_operations; + inode->i_fop = &cramfs_directory_operations; + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &page_symlink_inode_operations; + inode->i_data.a_ops = &cramfs_aops; + } else { + inode->i_size = 0; + inode->i_blocks = 0; + init_special_inode(inode, inode->i_mode, + old_decode_dev(cramfs_inode->size)); + } return 0; } @@ -77,37 +105,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), cramfs_iget5_test, cramfs_iget5_set, cramfs_inode); - static struct timespec zerotime; - if (inode && (inode->i_state & I_NEW)) { - inode->i_mode = cramfs_inode->mode; - inode->i_uid = cramfs_inode->uid; - inode->i_size = cramfs_inode->size; - inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; - inode->i_blksize = PAGE_CACHE_SIZE; - inode->i_gid = cramfs_inode->gid; - /* Struct copy intentional */ - inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; - inode->i_ino = CRAMINO(cramfs_inode); - /* inode->i_nlink is left 1 - arguably wrong for directories, - but it's the best we can do without reading the directory - contents. 1 yields the right result in GNU find, even - without -noleaf option. */ - if (S_ISREG(inode->i_mode)) { - inode->i_fop = &generic_ro_fops; - inode->i_data.a_ops = &cramfs_aops; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &cramfs_dir_inode_operations; - inode->i_fop = &cramfs_directory_operations; - } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = &page_symlink_inode_operations; - inode->i_data.a_ops = &cramfs_aops; - } else { - inode->i_size = 0; - inode->i_blocks = 0; - init_special_inode(inode, inode->i_mode, - old_decode_dev(cramfs_inode->size)); - } unlock_new_inode(inode); } return inode; diff --git a/fs/dcache.c b/fs/dcache.c index a173bba32666..11dc83092d4a 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1736,7 +1736,7 @@ void __init vfs_caches_init(unsigned long mempages) SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, filp_ctor, filp_dtor); + SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); dcache_init(mempages); inode_init(mempages); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 3fc4238e9703..0384e539b88f 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1624,15 +1624,14 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page, * For "nobh" option, we can only work if we don't need to * read-in the page - otherwise we create buffers to do the IO. */ - if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH)) { - if (PageUptodate(page)) { - kaddr = kmap_atomic(page, KM_USER0); - memset(kaddr + offset, 0, length); - flush_dcache_page(page); - kunmap_atomic(kaddr, KM_USER0); - set_page_dirty(page); - goto unlock; - } + if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) && + ext3_should_writeback_data(inode) && PageUptodate(page)) { + kaddr = kmap_atomic(page, KM_USER0); + memset(kaddr + offset, 0, length); + flush_dcache_page(page); + kunmap_atomic(kaddr, KM_USER0); + set_page_dirty(page); + goto unlock; } if (!page_has_buffers(page)) diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 8bd8ac077704..b8f5cd1e540d 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -2141,7 +2141,8 @@ retry: * We have a transaction open. All is sweetness. It also sets * i_size in generic_commit_write(). */ - err = page_symlink(inode, symname, l); + err = __page_symlink(inode, symname, l, + mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); if (err) { ext3_dec_count(handle, inode); ext3_mark_inode_dirty(handle, inode); diff --git a/fs/fifo.c b/fs/fifo.c index 923371b753ab..d13fcd3ec803 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -34,10 +34,7 @@ static int fifo_open(struct inode *inode, struct file *filp) { int ret; - ret = -ERESTARTSYS; - if (mutex_lock_interruptible(PIPE_MUTEX(*inode))) - goto err_nolock_nocleanup; - + mutex_lock(PIPE_MUTEX(*inode)); if (!inode->i_pipe) { ret = -ENOMEM; if(!pipe_new(inode)) @@ -140,8 +137,6 @@ err: err_nocleanup: mutex_unlock(PIPE_MUTEX(*inode)); - -err_nolock_nocleanup: return ret; } diff --git a/fs/file_table.c b/fs/file_table.c index 768b58167543..44fabeaa9415 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -5,6 +5,7 @@ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ +#include #include #include #include @@ -19,41 +20,20 @@ #include #include #include +#include +#include + +#include /* sysctl tunables... */ struct files_stat_struct files_stat = { .max_files = NR_FILE }; -EXPORT_SYMBOL(files_stat); /* Needed by unix.o */ - /* public. Not pretty! */ - __cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); +__cacheline_aligned_in_smp DEFINE_SPINLOCK(files_lock); -static DEFINE_SPINLOCK(filp_count_lock); - -/* slab constructors and destructors are called from arbitrary - * context and must be fully threaded - use a local spinlock - * to protect files_stat.nr_files - */ -void filp_ctor(void *objp, struct kmem_cache *cachep, unsigned long cflags) -{ - if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == - SLAB_CTOR_CONSTRUCTOR) { - unsigned long flags; - spin_lock_irqsave(&filp_count_lock, flags); - files_stat.nr_files++; - spin_unlock_irqrestore(&filp_count_lock, flags); - } -} - -void filp_dtor(void *objp, struct kmem_cache *cachep, unsigned long dflags) -{ - unsigned long flags; - spin_lock_irqsave(&filp_count_lock, flags); - files_stat.nr_files--; - spin_unlock_irqrestore(&filp_count_lock, flags); -} +static struct percpu_counter nr_files __cacheline_aligned_in_smp; static inline void file_free_rcu(struct rcu_head *head) { @@ -63,9 +43,45 @@ static inline void file_free_rcu(struct rcu_head *head) static inline void file_free(struct file *f) { + percpu_counter_dec(&nr_files); call_rcu(&f->f_u.fu_rcuhead, file_free_rcu); } +/* + * Return the total number of open files in the system + */ +static int get_nr_files(void) +{ + return percpu_counter_read_positive(&nr_files); +} + +/* + * Return the maximum number of open files in the system + */ +int get_max_files(void) +{ + return files_stat.max_files; +} +EXPORT_SYMBOL_GPL(get_max_files); + +/* + * Handle nr_files sysctl + */ +#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) +int proc_nr_files(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + files_stat.nr_files = get_nr_files(); + return proc_dointvec(table, write, filp, buffer, lenp, ppos); +} +#else +int proc_nr_files(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + return -ENOSYS; +} +#endif + /* Find an unused file structure and return a pointer to it. * Returns NULL, if there are no more free file structures or * we run out of memory. @@ -78,14 +94,20 @@ struct file *get_empty_filp(void) /* * Privileged users can go above max_files */ - if (files_stat.nr_files >= files_stat.max_files && - !capable(CAP_SYS_ADMIN)) - goto over; + if (get_nr_files() >= files_stat.max_files && !capable(CAP_SYS_ADMIN)) { + /* + * percpu_counters are inaccurate. Do an expensive check before + * we go and fail. + */ + if (percpu_counter_sum(&nr_files) >= files_stat.max_files) + goto over; + } f = kmem_cache_alloc(filp_cachep, GFP_KERNEL); if (f == NULL) goto fail; + percpu_counter_inc(&nr_files); memset(f, 0, sizeof(*f)); if (security_file_alloc(f)) goto fail_sec; @@ -101,10 +123,10 @@ struct file *get_empty_filp(void) over: /* Ran out of filps - report that */ - if (files_stat.nr_files > old_max) { + if (get_nr_files() > old_max) { printk(KERN_INFO "VFS: file-max limit %d reached\n", - files_stat.max_files); - old_max = files_stat.nr_files; + get_max_files()); + old_max = get_nr_files(); } goto fail; @@ -276,4 +298,5 @@ void __init files_init(unsigned long mempages) if (files_stat.max_files < NR_FILE) files_stat.max_files = NR_FILE; files_defer_init(); + percpu_counter_init(&nr_files); } diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index b635e167a3fa..d4d0c41490cd 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -406,7 +406,8 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info int err = 0, pointed = 0; struct jffs2_eraseblock *jeb; unsigned char *buffer; - uint32_t crc, ofs, retlen, len; + uint32_t crc, ofs, len; + size_t retlen; BUG_ON(tn->csize == 0); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 5f0652df5d47..f1695642d0f7 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -112,7 +112,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r * negative error code on failure. */ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, - struct jffs2_raw_dirent *rd, uint32_t read, struct jffs2_full_dirent **fdp, + struct jffs2_raw_dirent *rd, size_t read, struct jffs2_full_dirent **fdp, uint32_t *latest_mctime, uint32_t *mctime_ver) { struct jffs2_full_dirent *fd; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 3e51dd1da8aa..cf55b221fc2b 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -233,7 +233,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) c->nextblock->dirty_size = 0; } #ifdef CONFIG_JFFS2_FS_WRITEBUFFER - if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) { + if (!jffs2_can_mark_obsolete(c) && c->wbuf_pagesize && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) { /* If we're going to start writing into a block which already contains data, and the end of the data isn't page-aligned, skip a little and align it. */ diff --git a/fs/namei.c b/fs/namei.c index 557dcf395ca1..8dc2b038d5d9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2613,13 +2613,15 @@ void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) } } -int page_symlink(struct inode *inode, const char *symname, int len) +int __page_symlink(struct inode *inode, const char *symname, int len, + gfp_t gfp_mask) { struct address_space *mapping = inode->i_mapping; - struct page *page = grab_cache_page(mapping, 0); + struct page *page; int err = -ENOMEM; char *kaddr; + page = find_or_create_page(mapping, 0, gfp_mask); if (!page) goto fail; err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); @@ -2654,6 +2656,12 @@ fail: return err; } +int page_symlink(struct inode *inode, const char *symname, int len) +{ + return __page_symlink(inode, symname, len, + mapping_gfp_mask(inode->i_mapping)); +} + struct inode_operations page_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = page_follow_link_light, @@ -2672,6 +2680,7 @@ EXPORT_SYMBOL(lookup_one_len); EXPORT_SYMBOL(page_follow_link_light); EXPORT_SYMBOL(page_put_link); EXPORT_SYMBOL(page_readlink); +EXPORT_SYMBOL(__page_symlink); EXPORT_SYMBOL(page_symlink); EXPORT_SYMBOL(page_symlink_inode_operations); EXPORT_SYMBOL(path_lookup); diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index fd741cea5705..636593bf4d17 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -74,6 +74,7 @@ struct mlog_attribute { #define define_mask(_name) { \ .attr = { \ .name = #_name, \ + .owner = THIS_MODULE, \ .mode = S_IRUGO | S_IWUSR, \ }, \ .mask = ML_##_name, \ diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index e8c56a3d9c64..2cadc3009c83 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -256,7 +256,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; } \ } while (0) -#if (BITS_PER_LONG == 32) || defined(CONFIG_X86_64) +#if (BITS_PER_LONG == 32) || defined(CONFIG_X86_64) || (defined(CONFIG_UML_X86) && defined(CONFIG_64BIT)) #define MLFi64 "lld" #define MLFu64 "llu" #define MLFx64 "llx" diff --git a/fs/ocfs2/cluster/nodemanager.c b/fs/ocfs2/cluster/nodemanager.c index cf7828f23361..e1fceb8aa32d 100644 --- a/fs/ocfs2/cluster/nodemanager.c +++ b/fs/ocfs2/cluster/nodemanager.c @@ -756,7 +756,7 @@ static int __init init_o2nm(void) if (!ocfs2_table_header) { printk(KERN_ERR "nodemanager: unable to register sysctl\n"); ret = -ENOMEM; /* or something. */ - goto out; + goto out_o2net; } ret = o2net_register_hb_callbacks(); @@ -780,6 +780,8 @@ out_callbacks: o2net_unregister_hb_callbacks(); out_sysctl: unregister_sysctl_table(ocfs2_table_header); +out_o2net: + o2net_exit(); out: return ret; } diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index d22d4cf08db1..0f60cc0d3985 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -1318,7 +1318,7 @@ static void o2net_start_connect(void *arg) { struct o2net_node *nn = arg; struct o2net_sock_container *sc = NULL; - struct o2nm_node *node = NULL; + struct o2nm_node *node = NULL, *mynode = NULL; struct socket *sock = NULL; struct sockaddr_in myaddr = {0, }, remoteaddr = {0, }; int ret = 0; @@ -1334,6 +1334,12 @@ static void o2net_start_connect(void *arg) goto out; } + mynode = o2nm_get_node_by_num(o2nm_this_node()); + if (mynode == NULL) { + ret = 0; + goto out; + } + spin_lock(&nn->nn_lock); /* see if we already have one pending or have given up */ if (nn->nn_sc || nn->nn_persistent_error) @@ -1361,12 +1367,14 @@ static void o2net_start_connect(void *arg) sock->sk->sk_allocation = GFP_ATOMIC; myaddr.sin_family = AF_INET; + myaddr.sin_addr.s_addr = (__force u32)mynode->nd_ipv4_address; myaddr.sin_port = (__force u16)htons(0); /* any port */ ret = sock->ops->bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr)); if (ret) { - mlog(0, "bind failed: %d\n", ret); + mlog(ML_ERROR, "bind failed with %d at address %u.%u.%u.%u\n", + ret, NIPQUAD(mynode->nd_ipv4_address)); goto out; } @@ -1407,6 +1415,8 @@ out: sc_put(sc); if (node) o2nm_node_put(node); + if (mynode) + o2nm_node_put(mynode); return; } diff --git a/fs/ocfs2/cluster/tcp.h b/fs/ocfs2/cluster/tcp.h index a6f4585501c8..616ff2b8434a 100644 --- a/fs/ocfs2/cluster/tcp.h +++ b/fs/ocfs2/cluster/tcp.h @@ -85,13 +85,10 @@ enum { O2NET_DRIVER_READY, }; -int o2net_init_tcp_sock(struct inode *inode); int o2net_send_message(u32 msg_type, u32 key, void *data, u32 len, u8 target_node, int *status); int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *vec, size_t veclen, u8 target_node, int *status); -int o2net_broadcast_message(u32 msg_type, u32 key, void *data, u32 len, - struct inode *group); int o2net_register_handler(u32 msg_type, u32 key, u32 max_len, o2net_msg_handler_func *func, void *data, @@ -107,7 +104,5 @@ void o2net_disconnect_node(struct o2nm_node *node); int o2net_init(void); void o2net_exit(void); -int o2net_proc_init(struct proc_dir_entry *parent); -void o2net_proc_exit(struct proc_dir_entry *parent); #endif /* O2CLUSTER_TCP_H */ diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h index 23ceaa7127b4..9c772583744a 100644 --- a/fs/ocfs2/dlm/dlmcommon.h +++ b/fs/ocfs2/dlm/dlmcommon.h @@ -37,9 +37,7 @@ #define DLM_THREAD_SHUFFLE_INTERVAL 5 // flush everything every 5 passes #define DLM_THREAD_MS 200 // flush at least every 200 ms -#define DLM_HASH_BITS 7 -#define DLM_HASH_SIZE (1 << DLM_HASH_BITS) -#define DLM_HASH_MASK (DLM_HASH_SIZE - 1) +#define DLM_HASH_BUCKETS (PAGE_SIZE / sizeof(struct hlist_head)) enum dlm_ast_type { DLM_AST = 0, @@ -87,7 +85,7 @@ enum dlm_ctxt_state { struct dlm_ctxt { struct list_head list; - struct list_head *resources; + struct hlist_head *lockres_hash; struct list_head dirty_list; struct list_head purge_list; struct list_head pending_asts; @@ -217,7 +215,7 @@ struct dlm_lock_resource { /* WARNING: Please see the comment in dlm_init_lockres before * adding fields here. */ - struct list_head list; + struct hlist_node hash_node; struct kref refs; /* please keep these next 3 in this order diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c index f339fe27975a..54f61b76ab51 100644 --- a/fs/ocfs2/dlm/dlmdebug.c +++ b/fs/ocfs2/dlm/dlmdebug.c @@ -117,8 +117,8 @@ EXPORT_SYMBOL_GPL(dlm_print_one_lock); void dlm_dump_lock_resources(struct dlm_ctxt *dlm) { struct dlm_lock_resource *res; - struct list_head *iter; - struct list_head *bucket; + struct hlist_node *iter; + struct hlist_head *bucket; int i; mlog(ML_NOTICE, "struct dlm_ctxt: %s, node=%u, key=%u\n", @@ -129,12 +129,10 @@ void dlm_dump_lock_resources(struct dlm_ctxt *dlm) } spin_lock(&dlm->spinlock); - for (i=0; iresources[i]); - list_for_each(iter, bucket) { - res = list_entry(iter, struct dlm_lock_resource, list); + for (i=0; ilockres_hash[i]); + hlist_for_each_entry(res, iter, bucket, hash_node) dlm_print_one_lock_resource(res); - } } spin_unlock(&dlm->spinlock); } diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 6ee30837389c..8f3a9e3106fd 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -77,26 +77,26 @@ static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm); void __dlm_unhash_lockres(struct dlm_lock_resource *lockres) { - list_del_init(&lockres->list); + hlist_del_init(&lockres->hash_node); dlm_lockres_put(lockres); } void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) { - struct list_head *bucket; + struct hlist_head *bucket; struct qstr *q; assert_spin_locked(&dlm->spinlock); q = &res->lockname; q->hash = full_name_hash(q->name, q->len); - bucket = &(dlm->resources[q->hash & DLM_HASH_MASK]); + bucket = &(dlm->lockres_hash[q->hash % DLM_HASH_BUCKETS]); /* get a reference for our hashtable */ dlm_lockres_get(res); - list_add_tail(&res->list, bucket); + hlist_add_head(&res->hash_node, bucket); } struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, @@ -104,9 +104,9 @@ struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, unsigned int len) { unsigned int hash; - struct list_head *iter; + struct hlist_node *iter; struct dlm_lock_resource *tmpres=NULL; - struct list_head *bucket; + struct hlist_head *bucket; mlog_entry("%.*s\n", len, name); @@ -114,11 +114,11 @@ struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, hash = full_name_hash(name, len); - bucket = &(dlm->resources[hash & DLM_HASH_MASK]); + bucket = &(dlm->lockres_hash[hash % DLM_HASH_BUCKETS]); /* check for pre-existing lock */ - list_for_each(iter, bucket) { - tmpres = list_entry(iter, struct dlm_lock_resource, list); + hlist_for_each(iter, bucket) { + tmpres = hlist_entry(iter, struct dlm_lock_resource, hash_node); if (tmpres->lockname.len == len && memcmp(tmpres->lockname.name, name, len) == 0) { dlm_lockres_get(tmpres); @@ -193,8 +193,8 @@ static int dlm_wait_on_domain_helper(const char *domain) static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm) { - if (dlm->resources) - free_page((unsigned long) dlm->resources); + if (dlm->lockres_hash) + free_page((unsigned long) dlm->lockres_hash); if (dlm->name) kfree(dlm->name); @@ -303,10 +303,10 @@ static void dlm_migrate_all_locks(struct dlm_ctxt *dlm) mlog(0, "Migrating locks from domain %s\n", dlm->name); restart: spin_lock(&dlm->spinlock); - for (i=0; iresources[i])) { - res = list_entry(dlm->resources[i].next, - struct dlm_lock_resource, list); + for (i = 0; i < DLM_HASH_BUCKETS; i++) { + while (!hlist_empty(&dlm->lockres_hash[i])) { + res = hlist_entry(dlm->lockres_hash[i].first, + struct dlm_lock_resource, hash_node); /* need reference when manually grabbing lockres */ dlm_lockres_get(res); /* this should unhash the lockres @@ -1191,18 +1191,17 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, goto leave; } - dlm->resources = (struct list_head *) __get_free_page(GFP_KERNEL); - if (!dlm->resources) { + dlm->lockres_hash = (struct hlist_head *) __get_free_page(GFP_KERNEL); + if (!dlm->lockres_hash) { mlog_errno(-ENOMEM); kfree(dlm->name); kfree(dlm); dlm = NULL; goto leave; } - memset(dlm->resources, 0, PAGE_SIZE); - for (i=0; iresources[i]); + for (i=0; ilockres_hash[i]); strcpy(dlm->name, domain); dlm->key = key; diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 2e2e95e69499..847dd3cc4cf5 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -564,7 +564,7 @@ static void dlm_lockres_release(struct kref *kref) /* By the time we're ready to blow this guy away, we shouldn't * be on any lists. */ - BUG_ON(!list_empty(&res->list)); + BUG_ON(!hlist_unhashed(&res->hash_node)); BUG_ON(!list_empty(&res->granted)); BUG_ON(!list_empty(&res->converting)); BUG_ON(!list_empty(&res->blocked)); @@ -605,7 +605,7 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm, init_waitqueue_head(&res->wq); spin_lock_init(&res->spinlock); - INIT_LIST_HEAD(&res->list); + INIT_HLIST_NODE(&res->hash_node); INIT_LIST_HEAD(&res->granted); INIT_LIST_HEAD(&res->converting); INIT_LIST_HEAD(&res->blocked); diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index ed76bda1a534..1e232000f3f7 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -1693,7 +1693,10 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, u8 dead_node, u8 new_master) { int i; - struct list_head *iter, *iter2, *bucket; + struct list_head *iter, *iter2; + struct hlist_node *hash_iter; + struct hlist_head *bucket; + struct dlm_lock_resource *res; mlog_entry_void(); @@ -1717,10 +1720,9 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, * for now we need to run the whole hash, clear * the RECOVERING state and set the owner * if necessary */ - for (i=0; iresources[i]); - list_for_each(iter, bucket) { - res = list_entry (iter, struct dlm_lock_resource, list); + for (i = 0; i < DLM_HASH_BUCKETS; i++) { + bucket = &(dlm->lockres_hash[i]); + hlist_for_each_entry(res, hash_iter, bucket, hash_node) { if (res->state & DLM_LOCK_RES_RECOVERING) { if (res->owner == dead_node) { mlog(0, "(this=%u) res %.*s owner=%u " @@ -1852,10 +1854,10 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm, static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) { - struct list_head *iter; + struct hlist_node *iter; struct dlm_lock_resource *res; int i; - struct list_head *bucket; + struct hlist_head *bucket; struct dlm_lock *lock; @@ -1876,10 +1878,9 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) * can be kicked again to see if any ASTs or BASTs * need to be fired as a result. */ - for (i=0; iresources[i]); - list_for_each(iter, bucket) { - res = list_entry (iter, struct dlm_lock_resource, list); + for (i = 0; i < DLM_HASH_BUCKETS; i++) { + bucket = &(dlm->lockres_hash[i]); + hlist_for_each_entry(res, iter, bucket, hash_node) { /* always prune any $RECOVERY entries for dead nodes, * otherwise hangs can occur during later recovery */ if (dlm_is_recovery_lock(res->lockname.name, diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index b6ba292e9544..e6f207eebab4 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -181,6 +181,12 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode, ret = -EBADR; if (rec_end > OCFS2_I(inode)->ip_clusters) { mlog_errno(ret); + ocfs2_error(inode->i_sb, + "Extent %d at e_blkno %"MLFu64" of inode %"MLFu64" goes past ip_clusters of %u\n", + i, + le64_to_cpu(rec->e_blkno), + OCFS2_I(inode)->ip_blkno, + OCFS2_I(inode)->ip_clusters); goto out_free; } @@ -226,6 +232,12 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode, ret = -EBADR; if (blkno) { mlog_errno(ret); + ocfs2_error(inode->i_sb, + "Multiple extents for (cpos = %u, clusters = %u) on inode %"MLFu64"; e_blkno %"MLFu64" and rec %d at e_blkno %"MLFu64"\n", + cpos, clusters, + OCFS2_I(inode)->ip_blkno, + blkno, i, + le64_to_cpu(rec->e_blkno)); goto out_free; } @@ -238,6 +250,10 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode, */ ret = -EBADR; if (!blkno) { + ocfs2_error(inode->i_sb, + "No record found for (cpos = %u, clusters = %u) on inode %"MLFu64"\n", + cpos, clusters, + OCFS2_I(inode)->ip_blkno); mlog_errno(ret); goto out_free; } @@ -266,6 +282,20 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode, for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { rec = &el->l_recs[i]; + + if ((le32_to_cpu(rec->e_cpos) + le32_to_cpu(rec->e_clusters)) > + OCFS2_I(inode)->ip_clusters) { + ret = -EBADR; + mlog_errno(ret); + ocfs2_error(inode->i_sb, + "Extent %d at e_blkno %"MLFu64" of inode %"MLFu64" goes past ip_clusters of %u\n", + i, + le64_to_cpu(rec->e_blkno), + OCFS2_I(inode)->ip_blkno, + OCFS2_I(inode)->ip_clusters); + return ret; + } + ret = ocfs2_extent_map_insert(inode, rec, le16_to_cpu(el->l_tree_depth)); if (ret) { @@ -526,6 +556,10 @@ static int ocfs2_extent_map_insert(struct inode *inode, OCFS2_I(inode)->ip_map.em_clusters) { ret = -EBADR; mlog_errno(ret); + ocfs2_error(inode->i_sb, + "Zero e_clusters on non-tail extent record at e_blkno %"MLFu64" on inode %"MLFu64"\n", + le64_to_cpu(rec->e_blkno), + OCFS2_I(inode)->ip_blkno); return ret; } @@ -588,12 +622,12 @@ static int ocfs2_extent_map_insert(struct inode *inode, * Existing record in the extent map: * * cpos = 10, len = 10 - * |---------| + * |---------| * * New Record: * * cpos = 10, len = 20 - * |------------------| + * |------------------| * * The passed record is the new on-disk record. The new_clusters value * is how many clusters were added to the file. If the append is a diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 1715bc90e705..8a4048b55fdc 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -933,9 +933,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, struct file *filp = iocb->ki_filp; struct inode *inode = filp->f_dentry->d_inode; loff_t newsize, saved_pos; -#ifdef OCFS2_ORACORE_WORKAROUNDS - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); -#endif mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf, (unsigned int)count, @@ -951,14 +948,6 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, return -EIO; } -#ifdef OCFS2_ORACORE_WORKAROUNDS - /* ugh, work around some applications which open everything O_DIRECT + - * O_APPEND and really don't mean to use O_DIRECT. */ - if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS && - (filp->f_flags & O_APPEND) && (filp->f_flags & O_DIRECT)) - filp->f_flags &= ~O_DIRECT; -#endif - mutex_lock(&inode->i_mutex); /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */ if (filp->f_flags & O_DIRECT) { @@ -1079,27 +1068,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, /* communicate with ocfs2_dio_end_io */ ocfs2_iocb_set_rw_locked(iocb); -#ifdef OCFS2_ORACORE_WORKAROUNDS - if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS && - filp->f_flags & O_DIRECT) { - unsigned int saved_flags = filp->f_flags; - int sector_size = 1 << osb->s_sectsize_bits; - - if ((saved_pos & (sector_size - 1)) || - (count & (sector_size - 1)) || - ((unsigned long)buf & (sector_size - 1))) { - filp->f_flags |= O_SYNC; - filp->f_flags &= ~O_DIRECT; - } - - ret = generic_file_aio_write_nolock(iocb, &local_iov, 1, - &iocb->ki_pos); - - filp->f_flags = saved_flags; - } else -#endif - ret = generic_file_aio_write_nolock(iocb, &local_iov, 1, - &iocb->ki_pos); + ret = generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos); /* buffered aio wouldn't have proper lock coverage today */ BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); @@ -1140,9 +1109,6 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, int ret = 0, rw_level = -1, have_alloc_sem = 0; struct file *filp = iocb->ki_filp; struct inode *inode = filp->f_dentry->d_inode; -#ifdef OCFS2_ORACORE_WORKAROUNDS - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); -#endif mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", filp, buf, (unsigned int)count, @@ -1155,21 +1121,6 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, goto bail; } -#ifdef OCFS2_ORACORE_WORKAROUNDS - if (osb->s_mount_opt & OCFS2_MOUNT_COMPAT_OCFS) { - if (filp->f_flags & O_DIRECT) { - int sector_size = 1 << osb->s_sectsize_bits; - - if ((pos & (sector_size - 1)) || - (count & (sector_size - 1)) || - ((unsigned long)buf & (sector_size - 1)) || - (i_size_read(inode) & (sector_size -1))) { - filp->f_flags &= ~O_DIRECT; - } - } - } -#endif - /* * buffered reads protect themselves in ->readpage(). O_DIRECT reads * need locks to protect pending reads from racing with truncate. diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c index 0bbd22f46c80..cbfd45a97a63 100644 --- a/fs/ocfs2/heartbeat.c +++ b/fs/ocfs2/heartbeat.c @@ -67,6 +67,7 @@ void ocfs2_init_node_maps(struct ocfs2_super *osb) ocfs2_node_map_init(&osb->mounted_map); ocfs2_node_map_init(&osb->recovery_map); ocfs2_node_map_init(&osb->umount_map); + ocfs2_node_map_init(&osb->osb_recovering_orphan_dirs); } static void ocfs2_do_node_down(int node_num, diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 8122489c5762..315472a5c192 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -41,6 +41,7 @@ #include "dlmglue.h" #include "extent_map.h" #include "file.h" +#include "heartbeat.h" #include "inode.h" #include "journal.h" #include "namei.h" @@ -544,6 +545,42 @@ bail: return status; } +/* + * Serialize with orphan dir recovery. If the process doing + * recovery on this orphan dir does an iget() with the dir + * i_mutex held, we'll deadlock here. Instead we detect this + * and exit early - recovery will wipe this inode for us. + */ +static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb, + int slot) +{ + int ret = 0; + + spin_lock(&osb->osb_lock); + if (ocfs2_node_map_test_bit(osb, &osb->osb_recovering_orphan_dirs, slot)) { + mlog(0, "Recovery is happening on orphan dir %d, will skip " + "this inode\n", slot); + ret = -EDEADLK; + goto out; + } + /* This signals to the orphan recovery process that it should + * wait for us to handle the wipe. */ + osb->osb_orphan_wipes[slot]++; +out: + spin_unlock(&osb->osb_lock); + return ret; +} + +static void ocfs2_signal_wipe_completion(struct ocfs2_super *osb, + int slot) +{ + spin_lock(&osb->osb_lock); + osb->osb_orphan_wipes[slot]--; + spin_unlock(&osb->osb_lock); + + wake_up(&osb->osb_wipe_event); +} + static int ocfs2_wipe_inode(struct inode *inode, struct buffer_head *di_bh) { @@ -555,6 +592,11 @@ static int ocfs2_wipe_inode(struct inode *inode, /* We've already voted on this so it should be readonly - no * spinlock needed. */ orphaned_slot = OCFS2_I(inode)->ip_orphaned_slot; + + status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot); + if (status) + return status; + orphan_dir_inode = ocfs2_get_system_file_inode(osb, ORPHAN_DIR_SYSTEM_INODE, orphaned_slot); @@ -597,6 +639,7 @@ bail_unlock_dir: brelse(orphan_dir_bh); bail: iput(orphan_dir_inode); + ocfs2_signal_wipe_completion(osb, orphaned_slot); return status; } @@ -822,7 +865,8 @@ void ocfs2_delete_inode(struct inode *inode) status = ocfs2_wipe_inode(inode, di_bh); if (status < 0) { - mlog_errno(status); + if (status != -EDEADLK) + mlog_errno(status); goto bail_unlock_inode; } diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index d329c9df90ae..4be801f4559b 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -1408,21 +1408,17 @@ bail: return status; } -static int ocfs2_recover_orphans(struct ocfs2_super *osb, - int slot) +static int ocfs2_queue_orphans(struct ocfs2_super *osb, + int slot, + struct inode **head) { - int status = 0; - int have_disk_lock = 0; - struct inode *inode = NULL; - struct inode *iter; + int status; struct inode *orphan_dir_inode = NULL; + struct inode *iter; unsigned long offset, blk, local; struct buffer_head *bh = NULL; struct ocfs2_dir_entry *de; struct super_block *sb = osb->sb; - struct ocfs2_inode_info *oi; - - mlog(0, "Recover inodes from orphan dir in slot %d\n", slot); orphan_dir_inode = ocfs2_get_system_file_inode(osb, ORPHAN_DIR_SYSTEM_INODE, @@ -1430,17 +1426,15 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, if (!orphan_dir_inode) { status = -ENOENT; mlog_errno(status); - goto out; - } + return status; + } mutex_lock(&orphan_dir_inode->i_mutex); status = ocfs2_meta_lock(orphan_dir_inode, NULL, NULL, 0); if (status < 0) { - mutex_unlock(&orphan_dir_inode->i_mutex); mlog_errno(status); goto out; } - have_disk_lock = 1; offset = 0; iter = NULL; @@ -1451,11 +1445,10 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, if (!bh) status = -EINVAL; if (status < 0) { - mutex_unlock(&orphan_dir_inode->i_mutex); if (bh) brelse(bh); mlog_errno(status); - goto out; + goto out_unlock; } local = 0; @@ -1465,11 +1458,10 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, if (!ocfs2_check_dir_entry(orphan_dir_inode, de, bh, local)) { - mutex_unlock(&orphan_dir_inode->i_mutex); status = -EINVAL; mlog_errno(status); brelse(bh); - goto out; + goto out_unlock; } local += le16_to_cpu(de->rec_len); @@ -1504,18 +1496,95 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, mlog(0, "queue orphan %"MLFu64"\n", OCFS2_I(iter)->ip_blkno); - OCFS2_I(iter)->ip_next_orphan = inode; - inode = iter; + /* No locking is required for the next_orphan + * queue as there is only ever a single + * process doing orphan recovery. */ + OCFS2_I(iter)->ip_next_orphan = *head; + *head = iter; } brelse(bh); } - mutex_unlock(&orphan_dir_inode->i_mutex); +out_unlock: ocfs2_meta_unlock(orphan_dir_inode, 0); - have_disk_lock = 0; - +out: + mutex_unlock(&orphan_dir_inode->i_mutex); iput(orphan_dir_inode); - orphan_dir_inode = NULL; + return status; +} + +static int ocfs2_orphan_recovery_can_continue(struct ocfs2_super *osb, + int slot) +{ + int ret; + + spin_lock(&osb->osb_lock); + ret = !osb->osb_orphan_wipes[slot]; + spin_unlock(&osb->osb_lock); + return ret; +} + +static void ocfs2_mark_recovering_orphan_dir(struct ocfs2_super *osb, + int slot) +{ + spin_lock(&osb->osb_lock); + /* Mark ourselves such that new processes in delete_inode() + * know to quit early. */ + ocfs2_node_map_set_bit(osb, &osb->osb_recovering_orphan_dirs, slot); + while (osb->osb_orphan_wipes[slot]) { + /* If any processes are already in the middle of an + * orphan wipe on this dir, then we need to wait for + * them. */ + spin_unlock(&osb->osb_lock); + wait_event_interruptible(osb->osb_wipe_event, + ocfs2_orphan_recovery_can_continue(osb, slot)); + spin_lock(&osb->osb_lock); + } + spin_unlock(&osb->osb_lock); +} + +static void ocfs2_clear_recovering_orphan_dir(struct ocfs2_super *osb, + int slot) +{ + ocfs2_node_map_clear_bit(osb, &osb->osb_recovering_orphan_dirs, slot); +} + +/* + * Orphan recovery. Each mounted node has it's own orphan dir which we + * must run during recovery. Our strategy here is to build a list of + * the inodes in the orphan dir and iget/iput them. The VFS does + * (most) of the rest of the work. + * + * Orphan recovery can happen at any time, not just mount so we have a + * couple of extra considerations. + * + * - We grab as many inodes as we can under the orphan dir lock - + * doing iget() outside the orphan dir risks getting a reference on + * an invalid inode. + * - We must be sure not to deadlock with other processes on the + * system wanting to run delete_inode(). This can happen when they go + * to lock the orphan dir and the orphan recovery process attempts to + * iget() inside the orphan dir lock. This can be avoided by + * advertising our state to ocfs2_delete_inode(). + */ +static int ocfs2_recover_orphans(struct ocfs2_super *osb, + int slot) +{ + int ret = 0; + struct inode *inode = NULL; + struct inode *iter; + struct ocfs2_inode_info *oi; + + mlog(0, "Recover inodes from orphan dir in slot %d\n", slot); + + ocfs2_mark_recovering_orphan_dir(osb, slot); + ret = ocfs2_queue_orphans(osb, slot, &inode); + ocfs2_clear_recovering_orphan_dir(osb, slot); + + /* Error here should be noted, but we want to continue with as + * many queued inodes as we've got. */ + if (ret) + mlog_errno(ret); while (inode) { oi = OCFS2_I(inode); @@ -1541,14 +1610,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, inode = iter; } -out: - if (have_disk_lock) - ocfs2_meta_unlock(orphan_dir_inode, 0); - - if (orphan_dir_inode) - iput(orphan_dir_inode); - - return status; + return ret; } static int ocfs2_wait_on_mount(struct ocfs2_super *osb) diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 8d8e4779df92..e89de9b6e491 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -174,9 +174,6 @@ enum ocfs2_mount_options OCFS2_MOUNT_NOINTR = 1 << 2, /* Don't catch signals */ OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */ OCFS2_MOUNT_DATA_WRITEBACK = 1 << 4, /* No data ordering */ -#ifdef OCFS2_ORACORE_WORKAROUNDS - OCFS2_MOUNT_COMPAT_OCFS = 1 << 30, /* ocfs1 compatibility mode */ -#endif }; #define OCFS2_OSB_SOFT_RO 0x0001 @@ -290,6 +287,10 @@ struct ocfs2_super struct inode *osb_tl_inode; struct buffer_head *osb_tl_bh; struct work_struct osb_truncate_log_wq; + + struct ocfs2_node_map osb_recovering_orphan_dirs; + unsigned int *osb_orphan_wipes; + wait_queue_head_t osb_wipe_event; }; #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index dfb8a5bedfc8..c5b1ac547c15 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -138,7 +138,6 @@ /* Journal limits (in bytes) */ #define OCFS2_MIN_JOURNAL_SIZE (4 * 1024 * 1024) -#define OCFS2_MAX_JOURNAL_SIZE (500 * 1024 * 1024) struct ocfs2_system_inode_info { char *si_name; diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 046824b6b625..8dd3aafec499 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1325,6 +1325,16 @@ static int ocfs2_initialize_super(struct super_block *sb, } mlog(ML_NOTICE, "max_slots for this device: %u\n", osb->max_slots); + init_waitqueue_head(&osb->osb_wipe_event); + osb->osb_orphan_wipes = kcalloc(osb->max_slots, + sizeof(*osb->osb_orphan_wipes), + GFP_KERNEL); + if (!osb->osb_orphan_wipes) { + status = -ENOMEM; + mlog_errno(status); + goto bail; + } + osb->s_feature_compat = le32_to_cpu(OCFS2_RAW_SB(di)->s_feature_compat); osb->s_feature_ro_compat = @@ -1638,6 +1648,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb) if (osb->slot_info) ocfs2_free_slot_info(osb->slot_info); + kfree(osb->osb_orphan_wipes); /* FIXME * This belongs in journal shutdown, but because we have to * allocate osb->journal at the start of ocfs2_initalize_osb(), diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 78010ad60e47..1e4a93835fed 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c @@ -52,6 +52,7 @@ int ibm_partition(struct parsed_partitions *state, struct block_device *bdev) { int blocksize, offset, size; + loff_t i_size; dasd_information_t *info; struct hd_geometry *geo; char type[5] = {0,}; @@ -63,6 +64,13 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) unsigned char *data; Sector sect; + blocksize = bdev_hardsect_size(bdev); + if (blocksize <= 0) + return 0; + i_size = i_size_read(bdev->bd_inode); + if (i_size == 0) + return 0; + if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL) goto out_noinfo; if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) @@ -73,9 +81,6 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) goto out_noioctl; - - if ((blocksize = bdev_hardsect_size(bdev)) <= 0) - goto out_badsect; /* * Get volume label, extract name and type. @@ -111,7 +116,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) } else { printk("CMS1/%8s:", name); offset = (info->label_block + 1); - size = bdev->bd_inode->i_size >> 9; + size = i_size >> 9; } put_partition(state, 1, offset*(blocksize >> 9), size-offset*(blocksize >> 9)); @@ -168,7 +173,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) else printk("(nonl)/%8s:", name); offset = (info->label_block + 1); - size = (bdev->bd_inode->i_size >> 9); + size = i_size >> 9; put_partition(state, 1, offset*(blocksize >> 9), size-offset*(blocksize >> 9)); } @@ -180,7 +185,6 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) return 1; out_readerr: -out_badsect: out_noioctl: kfree(label); out_nolab: diff --git a/fs/pipe.c b/fs/pipe.c index d722579df79a..8aada8e426f4 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -605,7 +605,7 @@ struct file_operations rdwr_fifo_fops = { .fasync = pipe_rdwr_fasync, }; -struct file_operations read_pipe_fops = { +static struct file_operations read_pipe_fops = { .llseek = no_llseek, .read = pipe_read, .readv = pipe_readv, @@ -617,7 +617,7 @@ struct file_operations read_pipe_fops = { .fasync = pipe_read_fasync, }; -struct file_operations write_pipe_fops = { +static struct file_operations write_pipe_fops = { .llseek = no_llseek, .read = bad_pipe_r, .write = pipe_write, @@ -629,7 +629,7 @@ struct file_operations write_pipe_fops = { .fasync = pipe_write_fasync, }; -struct file_operations rdwr_pipe_fops = { +static struct file_operations rdwr_pipe_fops = { .llseek = no_llseek, .read = pipe_read, .readv = pipe_readv, diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 0eaad41f4658..91b7c15ab373 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -204,7 +204,6 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, { pte_t *pte, ptent; spinlock_t *ptl; - unsigned long pfn; struct page *page; pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); @@ -214,12 +213,12 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, continue; mss->resident += PAGE_SIZE; - pfn = pte_pfn(ptent); - if (!pfn_valid(pfn)) + + page = vm_normal_page(vma, addr, ptent); + if (!page) continue; - page = pfn_to_page(pfn); - if (page_count(page) >= 2) { + if (page_mapcount(page) >= 2) { if (pte_dirty(ptent)) mss->shared_dirty += PAGE_SIZE; else @@ -289,7 +288,7 @@ static int show_smap(struct seq_file *m, void *v) struct mem_size_stats mss; memset(&mss, 0, sizeof mss); - if (vma->vm_mm) + if (vma->vm_mm && !is_vm_hugetlb_page(vma)) smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss); return show_map_internal(m, v, &mss); } diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index cde5d48994ae..14bd2246fb6d 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -137,6 +137,7 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * inode->i_gid = dir->i_gid; d_instantiate(dentry, inode); dget(dentry); + dir->i_mtime = dir->i_ctime = CURRENT_TIME; } else iput(inode); } diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index f3473176c83a..be12879bb179 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -1464,13 +1464,11 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t partially overwritten pages, if needed. And lock the pages, so that nobody else can access these until we are done. We get number of actual blocks needed as a result. */ - blocks_to_allocate = - reiserfs_prepare_file_region_for_write(inode, pos, - num_pages, - write_bytes, - prepared_pages); - if (blocks_to_allocate < 0) { - res = blocks_to_allocate; + res = reiserfs_prepare_file_region_for_write(inode, pos, + num_pages, + write_bytes, + prepared_pages); + if (res < 0) { reiserfs_release_claimed_blocks(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - @@ -1478,6 +1476,8 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t break; } + blocks_to_allocate = res; + /* First we correct our estimate of how many blocks we need */ reiserfs_release_claimed_blocks(inode->i_sb, (num_pages << diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index b33d67bba2fd..d60f6238c66a 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -627,11 +627,6 @@ int reiserfs_get_block(struct inode *inode, sector_t block, reiserfs_write_lock(inode->i_sb); version = get_inode_item_key_version(inode); - if (block < 0) { - reiserfs_write_unlock(inode->i_sb); - return -EIO; - } - if (!file_capable(inode, block)) { reiserfs_write_unlock(inode->i_sb); return -EFBIG; @@ -934,12 +929,13 @@ int reiserfs_get_block(struct inode *inode, sector_t block, //pos_in_item * inode->i_sb->s_blocksize, TYPE_INDIRECT, 3); // key type is unimportant + RFALSE(cpu_key_k_offset(&tmp_key) > cpu_key_k_offset(&key), + "green-805: invalid offset"); blocks_needed = 1 + ((cpu_key_k_offset(&key) - cpu_key_k_offset(&tmp_key)) >> inode->i_sb-> s_blocksize_bits); - RFALSE(blocks_needed < 0, "green-805: invalid offset"); if (blocks_needed == 1) { un = &unf_single; diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index b7a179560ab4..5a9d2722fa0a 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2319,8 +2319,7 @@ static int journal_read(struct super_block *p_s_sb) return 1; } jh = (struct reiserfs_journal_header *)(journal->j_header_bh->b_data); - if (le32_to_cpu(jh->j_first_unflushed_offset) >= 0 && - le32_to_cpu(jh->j_first_unflushed_offset) < + if (le32_to_cpu(jh->j_first_unflushed_offset) < SB_ONDISK_JOURNAL_SIZE(p_s_sb) && le32_to_cpu(jh->j_last_flush_trans_id) > 0) { oldest_start = diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index c8123308e060..284f7852de8b 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -247,7 +247,7 @@ static int linear_search_in_dir_item(struct cpu_key *key, /* mark, that this generation number is used */ if (de->de_gen_number_bit_string) set_bit(GET_GENERATION_NUMBER(deh_offset(deh)), - (unsigned long *)de->de_gen_number_bit_string); + de->de_gen_number_bit_string); // calculate pointer to name and namelen de->de_entry_num = i; @@ -431,7 +431,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, struct reiserfs_de_head *deh; INITIALIZE_PATH(path); struct reiserfs_dir_entry de; - int bit_string[MAX_GENERATION_NUMBER / (sizeof(int) * 8) + 1]; + DECLARE_BITMAP(bit_string, MAX_GENERATION_NUMBER + 1); int gen_number; char small_buf[32 + DEH_SIZE]; /* 48 bytes now and we avoid kmalloc if we create file with short name */ @@ -486,7 +486,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, /* find the proper place for the new entry */ memset(bit_string, 0, sizeof(bit_string)); - de.de_gen_number_bit_string = (char *)bit_string; + de.de_gen_number_bit_string = bit_string; retval = reiserfs_find_entry(dir, name, namelen, &path, &de); if (retval != NAME_NOT_FOUND) { if (buffer != small_buf) @@ -508,7 +508,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, } gen_number = - find_first_zero_bit((unsigned long *)bit_string, + find_first_zero_bit(bit_string, MAX_GENERATION_NUMBER + 1); if (gen_number > MAX_GENERATION_NUMBER) { /* there is no free generation number */ diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 395e582ee542..d04cff2273b6 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1045,10 +1045,14 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) } inode->i_uid = le32_to_cpu(fe->uid); - if ( inode->i_uid == -1 ) inode->i_uid = UDF_SB(inode->i_sb)->s_uid; + if (inode->i_uid == -1 || UDF_QUERY_FLAG(inode->i_sb, + UDF_FLAG_UID_IGNORE)) + inode->i_uid = UDF_SB(inode->i_sb)->s_uid; inode->i_gid = le32_to_cpu(fe->gid); - if ( inode->i_gid == -1 ) inode->i_gid = UDF_SB(inode->i_sb)->s_gid; + if (inode->i_gid == -1 || UDF_QUERY_FLAG(inode->i_sb, + UDF_FLAG_GID_IGNORE)) + inode->i_gid = UDF_SB(inode->i_sb)->s_gid; inode->i_nlink = le16_to_cpu(fe->fileLinkCount); if (!inode->i_nlink) @@ -1335,10 +1339,14 @@ udf_update_inode(struct inode *inode, int do_sync) return err; } - if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid) + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET)) + fe->uid = cpu_to_le32(-1); + else if (inode->i_uid != UDF_SB(inode->i_sb)->s_uid) fe->uid = cpu_to_le32(inode->i_uid); - if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid) + if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_FORGET)) + fe->gid = cpu_to_le32(-1); + else if (inode->i_gid != UDF_SB(inode->i_sb)->s_gid) fe->gid = cpu_to_le32(inode->i_gid); udfperms = ((inode->i_mode & S_IRWXO) ) | diff --git a/fs/udf/super.c b/fs/udf/super.c index 4a6f49adc609..368d8f81fe54 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -269,7 +269,7 @@ enum { Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock, Opt_anchor, Opt_volume, Opt_partition, Opt_fileset, Opt_rootdir, Opt_utf8, Opt_iocharset, - Opt_err + Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore }; static match_table_t tokens = { @@ -282,6 +282,10 @@ static match_table_t tokens = { {Opt_adinicb, "adinicb"}, {Opt_shortad, "shortad"}, {Opt_longad, "longad"}, + {Opt_uforget, "uid=forget"}, + {Opt_uignore, "uid=ignore"}, + {Opt_gforget, "gid=forget"}, + {Opt_gignore, "gid=ignore"}, {Opt_gid, "gid=%u"}, {Opt_uid, "uid=%u"}, {Opt_umask, "umask=%o"}, @@ -414,6 +418,18 @@ udf_parse_options(char *options, struct udf_options *uopt) uopt->flags |= (1 << UDF_FLAG_NLS_MAP); break; #endif + case Opt_uignore: + uopt->flags |= (1 << UDF_FLAG_UID_IGNORE); + break; + case Opt_uforget: + uopt->flags |= (1 << UDF_FLAG_UID_FORGET); + break; + case Opt_gignore: + uopt->flags |= (1 << UDF_FLAG_GID_IGNORE); + break; + case Opt_gforget: + uopt->flags |= (1 << UDF_FLAG_GID_FORGET); + break; default: printk(KERN_ERR "udf: bad mount option \"%s\" " "or missing value\n", p); diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 663669810be6..110f8d62616f 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -20,6 +20,10 @@ #define UDF_FLAG_VARCONV 8 #define UDF_FLAG_NLS_MAP 9 #define UDF_FLAG_UTF8 10 +#define UDF_FLAG_UID_FORGET 11 /* save -1 for uid to disk */ +#define UDF_FLAG_UID_IGNORE 12 /* use sb uid instead of on disk uid */ +#define UDF_FLAG_GID_FORGET 13 +#define UDF_FLAG_GID_IGNORE 14 #define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 #define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h index 9387a5e1ffe0..0c2acc944a0a 100644 --- a/include/asm-arm/tlbflush.h +++ b/include/asm-arm/tlbflush.h @@ -340,6 +340,12 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr)); if (tlb_flag(TLB_V6_I_PAGE)) asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr)); + + /* The ARM ARM states that the completion of a TLB maintenance + * operation is only guaranteed by a DSB instruction + */ + if (tlb_flag(TLB_V6_U_PAGE | TLB_V6_D_PAGE | TLB_V6_I_PAGE)) + asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); } /* diff --git a/include/asm-generic/unaligned.h b/include/asm-generic/unaligned.h index 4dc8ddb401c1..09ec447fe2af 100644 --- a/include/asm-generic/unaligned.h +++ b/include/asm-generic/unaligned.h @@ -78,7 +78,7 @@ static inline void __ustw(__u16 val, __u16 *addr) #define __get_unaligned(ptr, size) ({ \ const void *__gu_p = ptr; \ - __typeof__(*(ptr)) val; \ + __u64 val; \ switch (size) { \ case 1: \ val = *(const __u8 *)__gu_p; \ @@ -95,7 +95,7 @@ static inline void __ustw(__u16 val, __u16 *addr) default: \ bad_unaligned_access_length(); \ }; \ - val; \ + (__typeof__(*(ptr)))val; \ }) #define __put_unaligned(val, ptr, size) \ diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h index d30b8571573f..ff9ac8d19eb2 100644 --- a/include/asm-i386/apic.h +++ b/include/asm-i386/apic.h @@ -137,6 +137,8 @@ void switch_APIC_timer_to_ipi(void *cpumask); void switch_ipi_to_APIC_timer(void *cpumask); #define ARCH_APICTIMER_STOPS_ON_C3 1 +extern int timer_over_8254; + #else /* !CONFIG_X86_LOCAL_APIC */ static inline void lapic_shutdown(void) { } diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h index a4a84d5c65d5..862e497c2645 100644 --- a/include/asm-m68k/atomic.h +++ b/include/asm-m68k/atomic.h @@ -55,6 +55,7 @@ static inline int atomic_inc_and_test(atomic_t *v) } #ifdef CONFIG_RMW_INSNS + static inline int atomic_add_return(int i, atomic_t *v) { int t, tmp; @@ -82,7 +83,12 @@ static inline int atomic_sub_return(int i, atomic_t *v) : "g" (i), "2" (atomic_read(v))); return t; } + +#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + #else /* !CONFIG_RMW_INSNS */ + static inline int atomic_add_return(int i, atomic_t * v) { unsigned long flags; @@ -110,6 +116,32 @@ static inline int atomic_sub_return(int i, atomic_t * v) return t; } + +static inline int atomic_cmpxchg(atomic_t *v, int old, int new) +{ + unsigned long flags; + int prev; + + local_irq_save(flags); + prev = atomic_read(v); + if (prev == old) + atomic_set(v, new); + local_irq_restore(flags); + return prev; +} + +static inline int atomic_xchg(atomic_t *v, int new) +{ + unsigned long flags; + int prev; + + local_irq_save(flags); + prev = atomic_read(v); + atomic_set(v, new); + local_irq_restore(flags); + return prev; +} + #endif /* !CONFIG_RMW_INSNS */ #define atomic_dec_return(v) atomic_sub_return(1, (v)) @@ -139,9 +171,6 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v) __asm__ __volatile__("orl %1,%0" : "+m" (*v) : "id" (mask)); } -#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - #define atomic_add_unless(v, a, u) \ ({ \ int c, old; \ diff --git a/include/asm-mips/vga.h b/include/asm-mips/vga.h index ca5cec97e167..34755c0a6398 100644 --- a/include/asm-mips/vga.h +++ b/include/asm-mips/vga.h @@ -26,6 +26,9 @@ * has already done the right job for us. */ +#undef scr_writew +#undef scr_readw + static inline void scr_writew(u16 val, volatile u16 *addr) { *addr = cpu_to_le16(val); diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 90d005bb4d1c..5638518968c3 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -20,6 +20,8 @@ #define PPC_FEATURE_POWER5_PLUS 0x00020000 #define PPC_FEATURE_CELL 0x00010000 #define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 #ifdef __KERNEL__ #ifndef __ASSEMBLY__ diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h index 7dfb408fe2ca..5207758a6dd9 100644 --- a/include/asm-powerpc/eeh.h +++ b/include/asm-powerpc/eeh.h @@ -61,6 +61,7 @@ void __init pci_addr_cache_build(void); * to finish the eeh setup for this device. */ void eeh_add_device_early(struct device_node *); +void eeh_add_device_late(struct pci_dev *dev); void eeh_add_device_tree_early(struct device_node *); void eeh_add_device_tree_late(struct pci_bus *); @@ -117,6 +118,8 @@ static inline void pci_addr_cache_build(void) { } static inline void eeh_add_device_early(struct device_node *dn) { } +static inline void eeh_add_device_late(struct pci_dev *dev) { } + static inline void eeh_remove_device(struct pci_dev *dev) { } static inline void eeh_add_device_tree_early(struct device_node *dn) { } diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h index bda2f217e6fe..6a2af2f6853b 100644 --- a/include/asm-powerpc/kexec.h +++ b/include/asm-powerpc/kexec.h @@ -93,7 +93,8 @@ static inline void crash_setup_regs(struct pt_regs *newregs, "mfxer %0\n" "std %0, 296(%2)\n" : "=&r" (tmp1), "=&r" (tmp2) - : "b" (newregs)); + : "b" (newregs) + : "memory"); } } #else diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h index e9590c06ad92..80a7832d2721 100644 --- a/include/asm-powerpc/pgtable-4k.h +++ b/include/asm-powerpc/pgtable-4k.h @@ -88,4 +88,4 @@ (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))) #define pud_ERROR(e) \ - printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pud_val(e)) + printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h index 237fc2b72974..ffc7462d77ba 100644 --- a/include/asm-powerpc/thread_info.h +++ b/include/asm-powerpc/thread_info.h @@ -37,7 +37,6 @@ struct thread_info { int preempt_count; /* 0 => preemptable, <0 => BUG */ struct restart_block restart_block; - void __user *nvgprs_frame; /* low level flags - has atomic operations done on it */ unsigned long flags ____cacheline_aligned_in_smp; }; @@ -120,7 +119,6 @@ static inline struct thread_info *current_thread_info(void) #define TIF_MEMDIE 10 #define TIF_SECCOMP 11 /* secure computing */ #define TIF_RESTOREALL 12 /* Restore all regs (implies NOERROR) */ -#define TIF_SAVE_NVGPRS 13 /* Save r14-r31 in signal frame */ #define TIF_NOERROR 14 /* Force successful syscall return */ #define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */ @@ -137,15 +135,13 @@ static inline struct thread_info *current_thread_info(void) #define _TIF_SINGLESTEP (1<state == HRTIMER_PENDING; diff --git a/include/linux/kmalloc_sizes.h b/include/linux/kmalloc_sizes.h index d82d4c05c12d..bda23e00ed71 100644 --- a/include/linux/kmalloc_sizes.h +++ b/include/linux/kmalloc_sizes.h @@ -19,8 +19,10 @@ CACHE(32768) CACHE(65536) CACHE(131072) -#ifndef CONFIG_MMU +#if (NR_CPUS > 512) || (MAX_NUMNODES > 256) || !defined(CONFIG_MMU) CACHE(262144) +#endif +#ifndef CONFIG_MMU CACHE(524288) CACHE(1048576) #ifdef CONFIG_LARGE_ALLOCS diff --git a/include/linux/libata.h b/include/linux/libata.h index 2558abac9fb2..d051a823758b 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -152,7 +152,7 @@ enum { ATA_FLAG_PIO_LBA48 = (1 << 13), /* Host DMA engine is LBA28 only */ ATA_FLAG_IRQ_MASK = (1 << 14), /* Mask IRQ in PIO xfers */ - ATA_FLAG_FLUSH_PIO_TASK = (1 << 15), /* Flush PIO task */ + ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */ ATA_FLAG_IN_EH = (1 << 16), /* EH in progress */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ @@ -191,11 +191,19 @@ enum { PORT_DISABLED = 2, /* encoding various smaller bitmaps into a single - * unsigned long bitmap + * unsigned int bitmap */ - ATA_SHIFT_UDMA = 0, - ATA_SHIFT_MWDMA = 8, - ATA_SHIFT_PIO = 11, + ATA_BITS_PIO = 5, + ATA_BITS_MWDMA = 3, + ATA_BITS_UDMA = 8, + + ATA_SHIFT_PIO = 0, + ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_BITS_PIO, + ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_BITS_MWDMA, + + ATA_MASK_PIO = ((1 << ATA_BITS_PIO) - 1) << ATA_SHIFT_PIO, + ATA_MASK_MWDMA = ((1 << ATA_BITS_MWDMA) - 1) << ATA_SHIFT_MWDMA, + ATA_MASK_UDMA = ((1 << ATA_BITS_UDMA) - 1) << ATA_SHIFT_UDMA, /* size of buffer to pad xfers ending on unaligned boundaries */ ATA_DMA_PAD_SZ = 4, @@ -344,7 +352,7 @@ struct ata_device { unsigned long flags; /* ATA_DFLAG_xxx */ unsigned int class; /* ATA_DEV_xxx */ unsigned int devno; /* 0 or 1 */ - u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ + u16 *id; /* IDENTIFY xxx DEVICE data */ u8 pio_mode; u8 dma_mode; u8 xfer_mode; @@ -393,7 +401,8 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; - struct work_struct pio_task; + struct work_struct port_task; + unsigned int hsm_task_state; unsigned long pio_task_timeout; @@ -488,6 +497,8 @@ extern int ata_std_softreset(struct ata_port *ap, int verbose, extern int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); +extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev, + int post_reset); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI @@ -516,6 +527,8 @@ extern int ata_ratelimit(void); extern unsigned int ata_busy_sleep(struct ata_port *ap, unsigned long timeout_pat, unsigned long timeout); +extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), + void *data, unsigned long delay); /* * Default driver ops implementations @@ -545,7 +558,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); extern void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs, unsigned int len); -extern void ata_dev_config(struct ata_port *ap, unsigned int i); extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_stop(struct ata_queued_cmd *qc); @@ -648,10 +660,14 @@ static inline unsigned int ata_tag_valid(unsigned int tag) return (tag < ATA_MAX_QUEUE) ? 1 : 0; } +static inline unsigned int ata_class_present(unsigned int class) +{ + return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI; +} + static inline unsigned int ata_dev_present(const struct ata_device *dev) { - return ((dev->class == ATA_DEV_ATA) || - (dev->class == ATA_DEV_ATAPI)); + return ata_class_present(dev->class); } static inline u8 ata_chk_status(struct ata_port *ap) diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 01f03bc06eff..968b1aa3732c 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -6,6 +6,10 @@ #include #include +struct page; +struct zone; +struct pglist_data; + #ifdef CONFIG_MEMORY_HOTPLUG /* * pgdat resizing functions diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 82b83da25d77..1709b5009d2e 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1752,6 +1752,8 @@ #define PCI_DEVICE_ID_CCD_B00B 0xb00b #define PCI_DEVICE_ID_CCD_B00C 0xb00c #define PCI_DEVICE_ID_CCD_B100 0xb100 +#define PCI_DEVICE_ID_CCD_B700 0xb700 +#define PCI_DEVICE_ID_CCD_B701 0xb701 #define PCI_VENDOR_ID_EXAR 0x13a8 #define PCI_DEVICE_ID_EXAR_XR17C152 0x0152 diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h index bd6708e2c027..682525511c9e 100644 --- a/include/linux/percpu_counter.h +++ b/include/linux/percpu_counter.h @@ -39,6 +39,7 @@ static inline void percpu_counter_destroy(struct percpu_counter *fbc) } void percpu_counter_mod(struct percpu_counter *fbc, long amount); +long percpu_counter_sum(struct percpu_counter *fbc); static inline long percpu_counter_read(struct percpu_counter *fbc) { @@ -92,6 +93,11 @@ static inline long percpu_counter_read_positive(struct percpu_counter *fbc) return fbc->count; } +static inline long percpu_counter_sum(struct percpu_counter *fbc) +{ + return percpu_counter_read_positive(fbc); +} + #endif /* CONFIG_SMP */ static inline void percpu_counter_inc(struct percpu_counter *fbc) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index b87aefa082e2..c2ec6c77874e 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -98,13 +98,17 @@ struct rcu_data { long batch; /* Batch # for current RCU batch */ struct rcu_head *nxtlist; struct rcu_head **nxttail; - long count; /* # of queued items */ + long qlen; /* # of queued callbacks */ struct rcu_head *curlist; struct rcu_head **curtail; struct rcu_head *donelist; struct rcu_head **donetail; + long blimit; /* Upper limit on a processed batch */ int cpu; struct rcu_head barrier; +#ifdef CONFIG_SMP + long last_rs_qlen; /* qlen during the last resched */ +#endif }; DECLARE_PER_CPU(struct rcu_data, rcu_data); diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 7d51149bd793..dad78cecfd20 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -1052,7 +1052,7 @@ struct reiserfs_dir_entry { int de_entrylen; int de_namelen; char *de_name; - char *de_gen_number_bit_string; + unsigned long *de_gen_number_bit_string; __u32 de_dir_id; __u32 de_objectid; diff --git a/include/linux/sched.h b/include/linux/sched.h index ff2e09c953b9..62e6314382f0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -892,7 +892,6 @@ static inline int pid_alive(struct task_struct *p) } extern void free_task(struct task_struct *tsk); -extern void __put_task_struct(struct task_struct *tsk); #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0) extern void __put_task_struct_cb(struct rcu_head *rhp); diff --git a/include/pcmcia/device_id.h b/include/pcmcia/device_id.h index 346d81ece287..e04e0b0d9a25 100644 --- a/include/pcmcia/device_id.h +++ b/include/pcmcia/device_id.h @@ -72,6 +72,15 @@ .prod_id = { (v1), (v2), (v3), (v4) }, \ .prod_id_hash = { (vh1), (vh2), (vh3), (vh4) }, } +#define PCMCIA_DEVICE_MANF_CARD_PROD_ID1(manf, card, v1, vh1) { \ + .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ + PCMCIA_DEV_ID_MATCH_CARD_ID| \ + PCMCIA_DEV_ID_MATCH_PROD_ID1, \ + .manf_id = (manf), \ + .card_id = (card), \ + .prod_id = { (v1), NULL, NULL, NULL }, \ + .prod_id_hash = { (vh1), 0, 0, 0 }, } + /* multi-function devices */ diff --git a/kernel/fork.c b/kernel/fork.c index fbea12d7a943..a8eab86de7f1 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -108,8 +108,10 @@ void free_task(struct task_struct *tsk) } EXPORT_SYMBOL(free_task); -void __put_task_struct(struct task_struct *tsk) +void __put_task_struct_cb(struct rcu_head *rhp) { + struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); + WARN_ON(!(tsk->exit_state & (EXIT_DEAD | EXIT_ZOMBIE))); WARN_ON(atomic_read(&tsk->usage)); WARN_ON(tsk == current); diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 5ae51f1bc7c8..14bc9cfa6399 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -505,6 +505,41 @@ ktime_t hrtimer_get_remaining(const struct hrtimer *timer) return rem; } +#ifdef CONFIG_NO_IDLE_HZ +/** + * hrtimer_get_next_event - get the time until next expiry event + * + * Returns the delta to the next expiry event or KTIME_MAX if no timer + * is pending. + */ +ktime_t hrtimer_get_next_event(void) +{ + struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); + ktime_t delta, mindelta = { .tv64 = KTIME_MAX }; + unsigned long flags; + int i; + + for (i = 0; i < MAX_HRTIMER_BASES; i++, base++) { + struct hrtimer *timer; + + spin_lock_irqsave(&base->lock, flags); + if (!base->first) { + spin_unlock_irqrestore(&base->lock, flags); + continue; + } + timer = rb_entry(base->first, struct hrtimer, node); + delta.tv64 = timer->expires.tv64; + spin_unlock_irqrestore(&base->lock, flags); + delta = ktime_sub(delta, base->get_time()); + if (delta.tv64 < mindelta.tv64) + mindelta.tv64 = delta.tv64; + } + if (mindelta.tv64 < 0) + mindelta.tv64 = 0; + return mindelta; +} +#endif + /** * hrtimer_init - initialize a timer to the given clock * diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 0cf8146bd585..8cf15a569fcd 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -67,7 +67,43 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L }; /* Fake initialization required by compiler */ static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; -static int maxbatch = 10000; +static int blimit = 10; +static int qhimark = 10000; +static int qlowmark = 100; +#ifdef CONFIG_SMP +static int rsinterval = 1000; +#endif + +static atomic_t rcu_barrier_cpu_count; +static struct semaphore rcu_barrier_sema; +static struct completion rcu_barrier_completion; + +#ifdef CONFIG_SMP +static void force_quiescent_state(struct rcu_data *rdp, + struct rcu_ctrlblk *rcp) +{ + int cpu; + cpumask_t cpumask; + set_need_resched(); + if (unlikely(rdp->qlen - rdp->last_rs_qlen > rsinterval)) { + rdp->last_rs_qlen = rdp->qlen; + /* + * Don't send IPI to itself. With irqs disabled, + * rdp->cpu is the current cpu. + */ + cpumask = rcp->cpumask; + cpu_clear(rdp->cpu, cpumask); + for_each_cpu_mask(cpu, cpumask) + smp_send_reschedule(cpu); + } +} +#else +static inline void force_quiescent_state(struct rcu_data *rdp, + struct rcu_ctrlblk *rcp) +{ + set_need_resched(); +} +#endif /** * call_rcu - Queue an RCU callback for invocation after a grace period. @@ -92,17 +128,13 @@ void fastcall call_rcu(struct rcu_head *head, rdp = &__get_cpu_var(rcu_data); *rdp->nxttail = head; rdp->nxttail = &head->next; - - if (unlikely(++rdp->count > 10000)) - set_need_resched(); - + if (unlikely(++rdp->qlen > qhimark)) { + rdp->blimit = INT_MAX; + force_quiescent_state(rdp, &rcu_ctrlblk); + } local_irq_restore(flags); } -static atomic_t rcu_barrier_cpu_count; -static struct semaphore rcu_barrier_sema; -static struct completion rcu_barrier_completion; - /** * call_rcu_bh - Queue an RCU for invocation after a quicker grace period. * @head: structure to be used for queueing the RCU updates. @@ -131,12 +163,12 @@ void fastcall call_rcu_bh(struct rcu_head *head, rdp = &__get_cpu_var(rcu_bh_data); *rdp->nxttail = head; rdp->nxttail = &head->next; - rdp->count++; -/* - * Should we directly call rcu_do_batch() here ? - * if (unlikely(rdp->count > 10000)) - * rcu_do_batch(rdp); - */ + + if (unlikely(++rdp->qlen > qhimark)) { + rdp->blimit = INT_MAX; + force_quiescent_state(rdp, &rcu_bh_ctrlblk); + } + local_irq_restore(flags); } @@ -199,10 +231,12 @@ static void rcu_do_batch(struct rcu_data *rdp) next = rdp->donelist = list->next; list->func(list); list = next; - rdp->count--; - if (++count >= maxbatch) + rdp->qlen--; + if (++count >= rdp->blimit) break; } + if (rdp->blimit == INT_MAX && rdp->qlen <= qlowmark) + rdp->blimit = blimit; if (!rdp->donelist) rdp->donetail = &rdp->donelist; else @@ -473,6 +507,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp, rdp->quiescbatch = rcp->completed; rdp->qs_pending = 0; rdp->cpu = cpu; + rdp->blimit = blimit; } static void __devinit rcu_online_cpu(int cpu) @@ -567,7 +602,12 @@ void synchronize_kernel(void) synchronize_rcu(); } -module_param(maxbatch, int, 0); +module_param(blimit, int, 0); +module_param(qhimark, int, 0); +module_param(qlowmark, int, 0); +#ifdef CONFIG_SMP +module_param(rsinterval, int, 0); +#endif EXPORT_SYMBOL_GPL(rcu_batches_completed); EXPORT_SYMBOL(call_rcu); /* WARNING: GPL-only in April 2006. */ EXPORT_SYMBOL(call_rcu_bh); /* WARNING: GPL-only in April 2006. */ diff --git a/kernel/sched.c b/kernel/sched.c index 12d291bf3379..4d46e90f59c3 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -178,13 +178,6 @@ static unsigned int task_timeslice(task_t *p) #define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran) \ < (long long) (sd)->cache_hot_time) -void __put_task_struct_cb(struct rcu_head *rhp) -{ - __put_task_struct(container_of(rhp, struct task_struct, rcu)); -} - -EXPORT_SYMBOL_GPL(__put_task_struct_cb); - /* * These are the runqueue data structures: */ @@ -4028,6 +4021,8 @@ static inline void __cond_resched(void) */ if (unlikely(preempt_count())) return; + if (unlikely(system_state != SYSTEM_RUNNING)) + return; do { add_preempt_count(PREEMPT_ACTIVE); schedule(); @@ -4333,6 +4328,7 @@ void __devinit init_idle(task_t *idle, int cpu) runqueue_t *rq = cpu_rq(cpu); unsigned long flags; + idle->timestamp = sched_clock(); idle->sleep_avg = 0; idle->array = NULL; idle->prio = MAX_PRIO; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index acf6c1550f27..32b48e8ee36e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -50,6 +50,9 @@ #include #include +extern int proc_nr_files(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos); + #if defined(CONFIG_SYSCTL) /* External variables not in a header file. */ @@ -667,7 +670,7 @@ static ctl_table kern_table[] = { .data = &acpi_video_flags, .maxlen = sizeof (unsigned long), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_doulongvec_minmax, }, #endif #ifdef CONFIG_IA64 @@ -943,7 +946,7 @@ static ctl_table fs_table[] = { .data = &files_stat, .maxlen = 3*sizeof(int), .mode = 0444, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_nr_files, }, { .ctl_name = FS_MAXFILE, diff --git a/kernel/timer.c b/kernel/timer.c index fe3a9a9f8328..bf7c4193b936 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -489,9 +489,21 @@ unsigned long next_timer_interrupt(void) struct list_head *list; struct timer_list *nte; unsigned long expires; + unsigned long hr_expires = MAX_JIFFY_OFFSET; + ktime_t hr_delta; tvec_t *varray[4]; int i, j; + hr_delta = hrtimer_get_next_event(); + if (hr_delta.tv64 != KTIME_MAX) { + struct timespec tsdelta; + tsdelta = ktime_to_timespec(hr_delta); + hr_expires = timespec_to_jiffies(&tsdelta); + if (hr_expires < 3) + return hr_expires + jiffies; + } + hr_expires += jiffies; + base = &__get_cpu_var(tvec_bases); spin_lock(&base->t_base.lock); expires = base->timer_jiffies + (LONG_MAX >> 1); @@ -542,6 +554,10 @@ found: } } spin_unlock(&base->t_base.lock); + + if (time_before(hr_expires, expires)) + return hr_expires; + return expires; } #endif @@ -925,6 +941,8 @@ static inline void update_times(void) void do_timer(struct pt_regs *regs) { jiffies_64++; + /* prevent loading jiffies before storing new jiffies_64 value. */ + barrier(); update_times(); softlockup_tick(regs); } @@ -1351,10 +1369,10 @@ static inline u64 time_interpolator_get_cycles(unsigned int src) return x(); case TIME_SOURCE_MMIO64 : - return readq((void __iomem *) time_interpolator->addr); + return readq_relaxed((void __iomem *)time_interpolator->addr); case TIME_SOURCE_MMIO32 : - return readl((void __iomem *) time_interpolator->addr); + return readl_relaxed((void __iomem *)time_interpolator->addr); default: return get_cycles(); } diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a918f77f02f3..1fe76d963ac2 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -130,6 +130,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) onlined_pages++; } zone->present_pages += onlined_pages; + zone->zone_pgdat->node_present_pages += onlined_pages; setup_per_zone_pages_min(); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 5643cfed6b0f..954981b14303 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -197,7 +197,7 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) return policy; } -static void gather_stats(struct page *, void *); +static void gather_stats(struct page *, void *, int pte_dirty); static void migrate_page_add(struct page *page, struct list_head *pagelist, unsigned long flags); @@ -239,7 +239,7 @@ static int check_pte_range(struct vm_area_struct *vma, pmd_t *pmd, continue; if (flags & MPOL_MF_STATS) - gather_stats(page, private); + gather_stats(page, private, pte_dirty(*pte)); else if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) migrate_page_add(page, private, flags); else @@ -1753,66 +1753,145 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) struct numa_maps { unsigned long pages; unsigned long anon; - unsigned long mapped; + unsigned long active; + unsigned long writeback; unsigned long mapcount_max; + unsigned long dirty; + unsigned long swapcache; unsigned long node[MAX_NUMNODES]; }; -static void gather_stats(struct page *page, void *private) +static void gather_stats(struct page *page, void *private, int pte_dirty) { struct numa_maps *md = private; int count = page_mapcount(page); - if (count) - md->mapped++; - - if (count > md->mapcount_max) - md->mapcount_max = count; - md->pages++; + if (pte_dirty || PageDirty(page)) + md->dirty++; + + if (PageSwapCache(page)) + md->swapcache++; + + if (PageActive(page)) + md->active++; + + if (PageWriteback(page)) + md->writeback++; if (PageAnon(page)) md->anon++; + if (count > md->mapcount_max) + md->mapcount_max = count; + md->node[page_to_nid(page)]++; cond_resched(); } +#ifdef CONFIG_HUGETLB_PAGE +static void check_huge_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end, + struct numa_maps *md) +{ + unsigned long addr; + struct page *page; + + for (addr = start; addr < end; addr += HPAGE_SIZE) { + pte_t *ptep = huge_pte_offset(vma->vm_mm, addr & HPAGE_MASK); + pte_t pte; + + if (!ptep) + continue; + + pte = *ptep; + if (pte_none(pte)) + continue; + + page = pte_page(pte); + if (!page) + continue; + + gather_stats(page, md, pte_dirty(*ptep)); + } +} +#else +static inline void check_huge_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end, + struct numa_maps *md) +{ +} +#endif + int show_numa_map(struct seq_file *m, void *v) { struct task_struct *task = m->private; struct vm_area_struct *vma = v; struct numa_maps *md; + struct file *file = vma->vm_file; + struct mm_struct *mm = vma->vm_mm; int n; char buffer[50]; - if (!vma->vm_mm) + if (!mm) return 0; md = kzalloc(sizeof(struct numa_maps), GFP_KERNEL); if (!md) return 0; - check_pgd_range(vma, vma->vm_start, vma->vm_end, - &node_online_map, MPOL_MF_STATS, md); + mpol_to_str(buffer, sizeof(buffer), + get_vma_policy(task, vma, vma->vm_start)); - if (md->pages) { - mpol_to_str(buffer, sizeof(buffer), - get_vma_policy(task, vma, vma->vm_start)); + seq_printf(m, "%08lx %s", vma->vm_start, buffer); - seq_printf(m, "%08lx %s pages=%lu mapped=%lu maxref=%lu", - vma->vm_start, buffer, md->pages, - md->mapped, md->mapcount_max); - - if (md->anon) - seq_printf(m," anon=%lu",md->anon); - - for_each_online_node(n) - if (md->node[n]) - seq_printf(m, " N%d=%lu", n, md->node[n]); - - seq_putc(m, '\n'); + if (file) { + seq_printf(m, " file="); + seq_path(m, file->f_vfsmnt, file->f_dentry, "\n\t= "); + } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { + seq_printf(m, " heap"); + } else if (vma->vm_start <= mm->start_stack && + vma->vm_end >= mm->start_stack) { + seq_printf(m, " stack"); } + + if (is_vm_hugetlb_page(vma)) { + check_huge_range(vma, vma->vm_start, vma->vm_end, md); + seq_printf(m, " huge"); + } else { + check_pgd_range(vma, vma->vm_start, vma->vm_end, + &node_online_map, MPOL_MF_STATS, md); + } + + if (!md->pages) + goto out; + + if (md->anon) + seq_printf(m," anon=%lu",md->anon); + + if (md->dirty) + seq_printf(m," dirty=%lu",md->dirty); + + if (md->pages != md->anon && md->pages != md->dirty) + seq_printf(m, " mapped=%lu", md->pages); + + if (md->mapcount_max > 1) + seq_printf(m, " mapmax=%lu", md->mapcount_max); + + if (md->swapcache) + seq_printf(m," swapcache=%lu", md->swapcache); + + if (md->active < md->pages && !is_vm_hugetlb_page(vma)) + seq_printf(m," active=%lu", md->active); + + if (md->writeback) + seq_printf(m," writeback=%lu", md->writeback); + + for_each_online_node(n) + if (md->node[n]) + seq_printf(m, " N%d=%lu", n, md->node[n]); +out: + seq_putc(m, '\n'); kfree(md); if (m->count < m->size) diff --git a/mm/oom_kill.c b/mm/oom_kill.c index c86c737d2433..78747afad6b0 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -355,6 +355,7 @@ retry: } out: + read_unlock(&tasklist_lock); cpuset_unlock(); if (mm) mmput(mm); @@ -364,5 +365,5 @@ out: * retry to allocate memory unless "p" is current */ if (!test_thread_flag(TIF_MEMDIE)) - schedule_timeout_interruptible(1); + schedule_timeout_uninterruptible(1); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 791690d7d3fa..234bd4895d14 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -590,21 +590,20 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, } #ifdef CONFIG_NUMA -/* Called from the slab reaper to drain remote pagesets */ -void drain_remote_pages(void) +/* + * Called from the slab reaper to drain pagesets on a particular node that + * belong to the currently executing processor. + */ +void drain_node_pages(int nodeid) { - struct zone *zone; - int i; + int i, z; unsigned long flags; local_irq_save(flags); - for_each_zone(zone) { + for (z = 0; z < MAX_NR_ZONES; z++) { + struct zone *zone = NODE_DATA(nodeid)->node_zones + z; struct per_cpu_pageset *pset; - /* Do not drain local pagesets */ - if (zone->zone_pgdat->node_id == numa_node_id()) - continue; - pset = zone_pcp(zone, smp_processor_id()); for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) { struct per_cpu_pages *pcp; diff --git a/mm/rmap.c b/mm/rmap.c index d8ce5ff61454..67f0e20b101f 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -537,9 +537,6 @@ void page_add_new_anon_rmap(struct page *page, */ void page_add_file_rmap(struct page *page) { - BUG_ON(PageAnon(page)); - BUG_ON(!pfn_valid(page_to_pfn(page))); - if (atomic_inc_and_test(&page->_mapcount)) __inc_page_state(nr_mapped); } diff --git a/mm/slab.c b/mm/slab.c index add05d808a4a..d0bd7f07ab04 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -789,6 +789,47 @@ static void __slab_error(const char *function, struct kmem_cache *cachep, char * dump_stack(); } +#ifdef CONFIG_NUMA +/* + * Special reaping functions for NUMA systems called from cache_reap(). + * These take care of doing round robin flushing of alien caches (containing + * objects freed on different nodes from which they were allocated) and the + * flushing of remote pcps by calling drain_node_pages. + */ +static DEFINE_PER_CPU(unsigned long, reap_node); + +static void init_reap_node(int cpu) +{ + int node; + + node = next_node(cpu_to_node(cpu), node_online_map); + if (node == MAX_NUMNODES) + node = 0; + + __get_cpu_var(reap_node) = node; +} + +static void next_reap_node(void) +{ + int node = __get_cpu_var(reap_node); + + /* + * Also drain per cpu pages on remote zones + */ + if (node != numa_node_id()) + drain_node_pages(node); + + node = next_node(node, node_online_map); + if (unlikely(node >= MAX_NUMNODES)) + node = first_node(node_online_map); + __get_cpu_var(reap_node) = node; +} + +#else +#define init_reap_node(cpu) do { } while (0) +#define next_reap_node(void) do { } while (0) +#endif + /* * Initiate the reap timer running on the target CPU. We run at around 1 to 2Hz * via the workqueue/eventd. @@ -806,6 +847,7 @@ static void __devinit start_cpu_timer(int cpu) * at that time. */ if (keventd_up() && reap_work->func == NULL) { + init_reap_node(cpu); INIT_WORK(reap_work, cache_reap, NULL); schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu); } @@ -884,6 +926,23 @@ static void __drain_alien_cache(struct kmem_cache *cachep, } } +/* + * Called from cache_reap() to regularly drain alien caches round robin. + */ +static void reap_alien(struct kmem_cache *cachep, struct kmem_list3 *l3) +{ + int node = __get_cpu_var(reap_node); + + if (l3->alien) { + struct array_cache *ac = l3->alien[node]; + if (ac && ac->avail) { + spin_lock_irq(&ac->lock); + __drain_alien_cache(cachep, ac, node); + spin_unlock_irq(&ac->lock); + } + } +} + static void drain_alien_cache(struct kmem_cache *cachep, struct array_cache **alien) { int i = 0; @@ -902,6 +961,7 @@ static void drain_alien_cache(struct kmem_cache *cachep, struct array_cache **al #else #define drain_alien_cache(cachep, alien) do { } while (0) +#define reap_alien(cachep, l3) do { } while (0) static inline struct array_cache **alloc_alien_cache(int node, int limit) { @@ -1124,6 +1184,7 @@ void __init kmem_cache_init(void) struct cache_sizes *sizes; struct cache_names *names; int i; + int order; for (i = 0; i < NUM_INIT_LISTS; i++) { kmem_list3_init(&initkmem_list3[i]); @@ -1167,11 +1228,15 @@ void __init kmem_cache_init(void) cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, cache_line_size()); - cache_estimate(0, cache_cache.buffer_size, cache_line_size(), 0, - &left_over, &cache_cache.num); + for (order = 0; order < MAX_ORDER; order++) { + cache_estimate(order, cache_cache.buffer_size, + cache_line_size(), 0, &left_over, &cache_cache.num); + if (cache_cache.num) + break; + } if (!cache_cache.num) BUG(); - + cache_cache.gfporder = order; cache_cache.colour = left_over / cache_cache.colour_off; cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) + sizeof(struct slab), cache_line_size()); @@ -1628,36 +1693,44 @@ static inline size_t calculate_slab_order(struct kmem_cache *cachep, size_t size, size_t align, unsigned long flags) { size_t left_over = 0; + int gfporder; - for (;; cachep->gfporder++) { + for (gfporder = 0 ; gfporder <= MAX_GFP_ORDER; gfporder++) { unsigned int num; size_t remainder; - if (cachep->gfporder > MAX_GFP_ORDER) { - cachep->num = 0; - break; - } - - cache_estimate(cachep->gfporder, size, align, flags, - &remainder, &num); + cache_estimate(gfporder, size, align, flags, &remainder, &num); if (!num) continue; + /* More than offslab_limit objects will cause problems */ - if (flags & CFLGS_OFF_SLAB && cachep->num > offslab_limit) + if ((flags & CFLGS_OFF_SLAB) && num > offslab_limit) break; + /* Found something acceptable - save it away */ cachep->num = num; + cachep->gfporder = gfporder; left_over = remainder; + /* + * A VFS-reclaimable slab tends to have most allocations + * as GFP_NOFS and we really don't want to have to be allocating + * higher-order pages when we are unable to shrink dcache. + */ + if (flags & SLAB_RECLAIM_ACCOUNT) + break; + /* * Large number of objects is good, but very large slabs are * currently bad for the gfp()s. */ - if (cachep->gfporder >= slab_break_gfp_order) + if (gfporder >= slab_break_gfp_order) break; - if ((left_over * 8) <= (PAGE_SIZE << cachep->gfporder)) - /* Acceptable internal fragmentation */ + /* + * Acceptable internal fragmentation? + */ + if ((left_over * 8) <= (PAGE_SIZE << gfporder)) break; } return left_over; @@ -1869,17 +1942,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, size = ALIGN(size, align); - if ((flags & SLAB_RECLAIM_ACCOUNT) && size <= PAGE_SIZE) { - /* - * A VFS-reclaimable slab tends to have most allocations - * as GFP_NOFS and we really don't want to have to be allocating - * higher-order pages when we are unable to shrink dcache. - */ - cachep->gfporder = 0; - cache_estimate(cachep->gfporder, size, align, flags, - &left_over, &cachep->num); - } else - left_over = calculate_slab_order(cachep, size, align, flags); + left_over = calculate_slab_order(cachep, size, align, flags); if (!cachep->num) { printk("kmem_cache_create: couldn't create cache %s.\n", name); @@ -2554,7 +2617,7 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) "slab: Internal list corruption detected in cache '%s'(%d), slabp %p(%d). Hexdump:\n", cachep->name, cachep->num, slabp, slabp->inuse); for (i = 0; - i < sizeof(slabp) + cachep->num * sizeof(kmem_bufctl_t); + i < sizeof(*slabp) + cachep->num * sizeof(kmem_bufctl_t); i++) { if ((i % 16) == 0) printk("\n%03x:", i); @@ -3494,8 +3557,7 @@ static void cache_reap(void *unused) check_irq_on(); l3 = searchp->nodelists[numa_node_id()]; - if (l3->alien) - drain_alien_cache(searchp, l3->alien); + reap_alien(searchp, l3); spin_lock_irq(&l3->list_lock); drain_array_locked(searchp, cpu_cache_get(searchp), 0, @@ -3545,7 +3607,7 @@ static void cache_reap(void *unused) } check_irq_on(); mutex_unlock(&cache_chain_mutex); - drain_remote_pages(); + next_reap_node(); /* Setup the next iteration */ schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC); } diff --git a/mm/swap.c b/mm/swap.c index cce3dda59c59..e9ec06d845e8 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -489,13 +489,34 @@ void percpu_counter_mod(struct percpu_counter *fbc, long amount) if (count >= FBC_BATCH || count <= -FBC_BATCH) { spin_lock(&fbc->lock); fbc->count += count; + *pcount = 0; spin_unlock(&fbc->lock); - count = 0; + } else { + *pcount = count; } - *pcount = count; put_cpu(); } EXPORT_SYMBOL(percpu_counter_mod); + +/* + * Add up all the per-cpu counts, return the result. This is a more accurate + * but much slower version of percpu_counter_read_positive() + */ +long percpu_counter_sum(struct percpu_counter *fbc) +{ + long ret; + int cpu; + + spin_lock(&fbc->lock); + ret = fbc->count; + for_each_cpu(cpu) { + long *pcount = per_cpu_ptr(fbc->counters, cpu); + ret += *pcount; + } + spin_unlock(&fbc->lock); + return ret < 0 ? 0 : ret; +} +EXPORT_SYMBOL(percpu_counter_sum); #endif /* diff --git a/mm/vmscan.c b/mm/vmscan.c index b0af7593d01e..7ccf763bb30b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1883,7 +1883,8 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) if (!(gfp_mask & __GFP_WAIT) || zone->all_unreclaimable || - atomic_read(&zone->reclaim_in_progress) > 0) + atomic_read(&zone->reclaim_in_progress) > 0 || + (p->flags & PF_MEMALLOC)) return 0; node_id = zone->zone_pgdat->node_id; diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 93ad59a28ef5..31d98b57e1de 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -39,25 +39,19 @@ static DECLARE_WAIT_QUEUE_HEAD(sigd_sleep); static void sigd_put_skb(struct sk_buff *skb) { #ifdef WAIT_FOR_DEMON - static unsigned long silence; DECLARE_WAITQUEUE(wait,current); add_wait_queue(&sigd_sleep,&wait); while (!sigd) { set_current_state(TASK_UNINTERRUPTIBLE); - if (time_after(jiffies, silence) || silence == 0) { - printk(KERN_INFO "atmsvc: waiting for signaling demon " - "...\n"); - silence = (jiffies+30*HZ)|1; - } + DPRINTK("atmsvc: waiting for signaling demon...\n"); schedule(); } current->state = TASK_RUNNING; remove_wait_queue(&sigd_sleep,&wait); #else if (!sigd) { - if (net_ratelimit()) - printk(KERN_WARNING "atmsvc: no signaling demon\n"); + DPRINTK("atmsvc: no signaling demon\n"); kfree_skb(skb); return; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 7fa3a5a9971f..f36b35edd60c 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -81,26 +81,27 @@ static void port_carrier_check(void *arg) { struct net_device *dev = arg; struct net_bridge_port *p; + struct net_bridge *br; rtnl_lock(); p = dev->br_port; if (!p) goto done; + br = p->br; - if (netif_carrier_ok(p->dev)) { - u32 cost = port_cost(p->dev); + if (netif_carrier_ok(dev)) + p->path_cost = port_cost(dev); - spin_lock_bh(&p->br->lock); - if (p->state == BR_STATE_DISABLED) { - p->path_cost = cost; - br_stp_enable_port(p); + if (br->dev->flags & IFF_UP) { + spin_lock_bh(&br->lock); + if (netif_carrier_ok(dev)) { + if (p->state == BR_STATE_DISABLED) + br_stp_enable_port(p); + } else { + if (p->state != BR_STATE_DISABLED) + br_stp_disable_port(p); } - spin_unlock_bh(&p->br->lock); - } else { - spin_lock_bh(&p->br->lock); - if (p->state != BR_STATE_DISABLED) - br_stp_disable_port(p); - spin_unlock_bh(&p->br->lock); + spin_unlock_bh(&br->lock); } done: rtnl_unlock(); @@ -168,6 +169,7 @@ static void del_nbp(struct net_bridge_port *p) rcu_assign_pointer(dev->br_port, NULL); + kobject_uevent(&p->kobj, KOBJ_REMOVE); kobject_del(&p->kobj); call_rcu(&p->rcu, destroy_nbp_rcu); @@ -276,8 +278,9 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, br_init_port(p); p->state = BR_STATE_DISABLED; INIT_WORK(&p->carrier_check, port_carrier_check, dev); - kobject_init(&p->kobj); + br_stp_port_timer_init(p); + kobject_init(&p->kobj); kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR); p->kobj.ktype = &brport_ktype; p->kobj.parent = &(dev->class_dev.kobj); diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 35cf3a074087..23dea1422c9a 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -39,8 +39,6 @@ void br_init_port(struct net_bridge_port *p) p->state = BR_STATE_BLOCKING; p->topology_change_ack = 0; p->config_pending = 0; - - br_stp_port_timer_init(p); } /* called under bridge lock */ diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index aa68e0ab274d..35d1d347541c 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -2,7 +2,7 @@ * net/dccp/ccids/ccid3.c * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. - * Copyright (c) 2005 Ian McDonald + * Copyright (c) 2005-6 Ian McDonald * * An implementation of the DCCP protocol * @@ -1033,9 +1033,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) p_prev = hcrx->ccid3hcrx_p; /* Calculate loss event rate */ - if (!list_empty(&hcrx->ccid3hcrx_li_hist)) + if (!list_empty(&hcrx->ccid3hcrx_li_hist)) { + u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); + /* Scaling up by 1000000 as fixed decimal */ - hcrx->ccid3hcrx_p = 1000000 / dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); + if (i_mean != 0) + hcrx->ccid3hcrx_p = 1000000 / i_mean; + } if (hcrx->ccid3hcrx_p > p_prev) { ccid3_hc_rx_send_feedback(sk); diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 36339eb39e17..08f80e2ea2aa 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -524,7 +524,7 @@ ipq_rcv_skb(struct sk_buff *skb) write_unlock_bh(&queue_lock); status = ipq_receive_peer(NLMSG_DATA(nlh), type, - skblen - NLMSG_LENGTH(0)); + nlmsglen - NLMSG_LENGTH(0)); if (status < 0) RCV_SKB_FAIL(status); diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 5027bbe6415e..af0635084df8 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -522,7 +522,7 @@ ipq_rcv_skb(struct sk_buff *skb) write_unlock_bh(&queue_lock); status = ipq_receive_peer(NLMSG_DATA(nlh), type, - skblen - NLMSG_LENGTH(0)); + nlmsglen - NLMSG_LENGTH(0)); if (status < 0) RCV_SKB_FAIL(status); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1b5989b1b670..c323cc6a28b0 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -547,7 +547,7 @@ static struct sock * unix_create1(struct socket *sock) struct sock *sk = NULL; struct unix_sock *u; - if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files) + if (atomic_read(&unix_nr_socks) >= 2*get_max_files()) goto out; sk = sk_alloc(PF_UNIX, GFP_KERNEL, &unix_proto, 1); diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index be97caf664bb..c164b230ad6f 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -246,7 +246,7 @@ static int do_ccw_entry(const char *filename, id->cu_model); ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, id->dev_type); - ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, + ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL, id->dev_model); return 1; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b7773bf68efa..b65c201e9ff5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1262,7 +1262,7 @@ static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) rc = task_has_perm(parent, child, PROCESS__PTRACE); /* Save the SID of the tracing process for later use in apply_creds. */ - if (!rc) + if (!(child->ptrace & PT_PTRACED) && !rc) csec->ptrace_sid = psec->sid; return rc; } diff --git a/sound/core/control.c b/sound/core/control.c index abd62f943726..0c29679a8576 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -959,17 +959,15 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, kctl.private_free = snd_ctl_elem_user_free; _kctl = snd_ctl_new(&kctl, access); if (_kctl == NULL) { - kfree(_kctl->private_data); + kfree(ue); return -ENOMEM; } _kctl->private_data = ue; for (idx = 0; idx < _kctl->count; idx++) _kctl->vd[idx].owner = file; err = snd_ctl_add(card, _kctl); - if (err < 0) { - snd_ctl_free_one(_kctl); + if (err < 0) return err; - } down_write(&card->controls_rwsem); card->user_ctl_count++;