Merge branch 'upstream'
authorJeff Garzik <jeff@garzik.org>
Sun, 12 Mar 2006 00:21:17 +0000 (19:21 -0500)
committerJeff Garzik <jeff@garzik.org>
Sun, 12 Mar 2006 00:21:17 +0000 (19:21 -0500)
278 files changed:
CREDITS
Documentation/dvb/bt8xx.txt
Documentation/feature-removal-schedule.txt
Documentation/kernel-parameters.txt
Documentation/video4linux/CARDLIST.saa7134
MAINTAINERS
Makefile
arch/alpha/kernel/irq.c
arch/arm/Kconfig
arch/arm/kernel/time.c
arch/arm/mach-ixp4xx/nas100d-power.c
arch/arm/mm/tlb-v6.S
arch/h8300/kernel/process.c
arch/i386/kernel/Makefile
arch/i386/kernel/acpi/Makefile
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/cpu/common.c
arch/i386/kernel/efi.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/machine_kexec.c
arch/i386/kernel/nmi.c
arch/i386/kernel/setup.c
arch/i386/kernel/time.c
arch/ia64/configs/gensparse_defconfig
arch/ia64/kernel/cyclone.c
arch/ia64/kernel/ivt.S
arch/ia64/kernel/mca_drv.c
arch/ia64/sn/kernel/sn2/sn2_smp.c
arch/ia64/sn/kernel/tiocx.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/arc/arc_con.c
arch/mips/kernel/irq-mv6434x.c
arch/mips/kernel/time.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/mm/tlbex.c
arch/mips/momentum/jaguar_atx/prom.c
arch/mips/momentum/jaguar_atx/setup.c
arch/mips/momentum/ocelot_c/irq.c
arch/mips/momentum/ocelot_c/prom.c
arch/mips/momentum/ocelot_c/setup.c
arch/mips/pci/pci-ocelot-c.c
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/kernel/systbl.S
arch/powerpc/kernel/traps.c
arch/powerpc/platforms/powermac/pfunc_base.c
arch/powerpc/platforms/powermac/pfunc_core.c
arch/powerpc/platforms/powermac/smp.c
arch/ppc/kernel/asm-offsets.c
arch/ppc/kernel/entry.S
arch/s390/lib/spinlock.c
arch/s390/lib/uaccess.S
arch/s390/lib/uaccess64.S
arch/sh/Kconfig
arch/sparc64/kernel/sys32.S
arch/sparc64/kernel/una_asm.S
arch/sparc64/lib/U1copy_from_user.S
arch/sparc64/lib/U1copy_to_user.S
arch/sparc64/lib/U3copy_from_user.S
arch/sparc64/lib/U3copy_to_user.S
arch/sparc64/lib/bzero.S
arch/sparc64/lib/copy_in_user.S
arch/sparc64/lib/csum_copy_from_user.S
arch/sparc64/lib/csum_copy_to_user.S
arch/sparc64/lib/strlen_user.S
arch/sparc64/lib/strncpy_from_user.S
arch/sparc64/solaris/entry64.S
arch/v850/kernel/process.c
arch/x86_64/kernel/machine_kexec.c
arch/xtensa/Kconfig
arch/xtensa/kernel/process.c
block/ll_rw_blk.c
drivers/atm/fore200e.c
drivers/block/DAC960.c
drivers/char/hw_random.c
drivers/char/mmtimer.c
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/edac/Kconfig
drivers/edac/edac_mc.c
drivers/firmware/dcdbas.c
drivers/ide/legacy/ide-cs.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/input/mouse/psmouse-base.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hfc_usb.c
drivers/isdn/i4l/isdn_tty.c
drivers/macintosh/windfarm_core.c
drivers/macintosh/windfarm_cpufreq_clamp.c
drivers/macintosh/windfarm_lm75_sensor.c
drivers/macintosh/windfarm_max6690_sensor.c
drivers/macintosh/windfarm_pid.c
drivers/macintosh/windfarm_pm112.c
drivers/md/raid1.c
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/bt8xx/bt878.c
drivers/media/dvb/bt8xx/dst.c
drivers/media/dvb/dvb-core/demux.h
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dvb-usb-init.c
drivers/media/dvb/dvb-usb/dvb-usb.h
drivers/media/dvb/frontends/Kconfig
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/mt312.h
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110_hw.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/video/cpia.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/saa7115.c
drivers/media/video/saa7134/saa7134-alsa.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/tda8290.c
drivers/media/video/tuner-core.c
drivers/media/video/videocodec.h
drivers/media/video/zr36050.c
drivers/media/video/zr36060.c
drivers/media/video/zr36120_i2c.c
drivers/misc/ibmasm/ibmasm.h
drivers/mmc/au1xmmc.c
drivers/mtd/redboot.c
drivers/net/chelsio/espi.c
drivers/net/e1000/e1000.h
drivers/net/e1000/e1000_main.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/s2io.c
drivers/net/tg3.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/parport/parport_serial.c
drivers/pcmcia/ds.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_proc.c
drivers/s390/cio/chsc.c
drivers/s390/net/smsgiucv.c
drivers/scsi/ahci.c
drivers/scsi/ata_piix.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/libata.h
drivers/scsi/sata_promise.c
drivers/scsi/sata_sil.c
drivers/scsi/sata_sil24.c
drivers/scsi/sr_ioctl.c
drivers/serial/ioc4_serial.c
drivers/serial/ip22zilog.c
drivers/serial/serial_core.c
drivers/serial/sn_console.c
drivers/usb/serial/usb-serial.c
drivers/video/arcfb.c
drivers/video/aty/aty128fb.c
drivers/video/aty/radeon_monitor.c
drivers/video/backlight/backlight.c
drivers/video/backlight/lcd.c
drivers/video/imsttfb.c
drivers/video/intelfb/intelfbdrv.c
drivers/video/kyro/STG4000VTG.c
drivers/video/neofb.c
drivers/video/s1d13xxxfb.c
drivers/video/savage/savagefb_driver.c
drivers/video/tdfxfb.c
fs/9p/9p.c
fs/9p/fid.c
fs/9p/fid.h
fs/9p/trans_fd.c
fs/9p/v9fs.c
fs/9p/v9fs_vfs.h
fs/9p/vfs_dentry.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/misc.c
fs/compat_ioctl.c
fs/cramfs/inode.c
fs/dcache.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/fifo.c
fs/file_table.c
fs/jffs2/nodelist.c
fs/jffs2/readinode.c
fs/jffs2/scan.c
fs/namei.c
fs/ocfs2/cluster/masklog.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/cluster/nodemanager.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/cluster/tcp.h
fs/ocfs2/dlm/dlmcommon.h
fs/ocfs2/dlm/dlmdebug.c
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/extent_map.c
fs/ocfs2/file.c
fs/ocfs2/heartbeat.c
fs/ocfs2/inode.c
fs/ocfs2/journal.c
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_fs.h
fs/ocfs2/super.c
fs/partitions/ibm.c
fs/pipe.c
fs/proc/task_mmu.c
fs/ramfs/inode.c
fs/reiserfs/file.c
fs/reiserfs/inode.c
fs/reiserfs/journal.c
fs/reiserfs/namei.c
fs/udf/inode.c
fs/udf/super.c
fs/udf/udf_sb.h
include/asm-arm/tlbflush.h
include/asm-generic/unaligned.h
include/asm-i386/apic.h
include/asm-m68k/atomic.h
include/asm-mips/vga.h
include/asm-powerpc/cputable.h
include/asm-powerpc/eeh.h
include/asm-powerpc/kexec.h
include/asm-powerpc/pgtable-4k.h
include/asm-powerpc/thread_info.h
include/asm-s390/system.h
include/asm-sparc64/futex.h
include/asm-sparc64/uaccess.h
include/linux/compat_ioctl.h
include/linux/file.h
include/linux/fs.h
include/linux/gfp.h
include/linux/hrtimer.h
include/linux/kmalloc_sizes.h
include/linux/libata.h
include/linux/memory_hotplug.h
include/linux/pci_ids.h
include/linux/percpu_counter.h
include/linux/rcupdate.h
include/linux/reiserfs_fs.h
include/linux/sched.h
include/pcmcia/device_id.h
kernel/fork.c
kernel/hrtimer.c
kernel/rcupdate.c
kernel/sched.c
kernel/sysctl.c
kernel/timer.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/oom_kill.c
mm/page_alloc.c
mm/rmap.c
mm/slab.c
mm/swap.c
mm/vmscan.c
net/atm/signaling.c
net/bridge/br_if.c
net/bridge/br_stp_if.c
net/dccp/ccids/ccid3.c
net/ipv4/netfilter/ip_queue.c
net/ipv6/netfilter/ip6_queue.c
net/unix/af_unix.c
scripts/mod/file2alias.c
security/selinux/hooks.c
sound/core/control.c

diff --git a/CREDITS b/CREDITS
index 6957ef4..64511e2 100644 (file)
--- 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
index df6c054..52ed462 100644 (file)
@@ -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
index be5ae60..81bc513 100644 (file)
@@ -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 <gregkh@suse.de>
+
+---------------------------
+
+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 <ralf@linux-mips.org>
index 7520539..fc99075 100644 (file)
@@ -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: <full_path>
                        Run specified binary instead of /init from the ramdisk,
index 8a35259..da4fb89 100644 (file)
@@ -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]
index 9c592aa..3d7d30d 100644 (file)
@@ -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
index 46eea76..65a0337 100644 (file)
--- 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)
 
 # ---------------------------------------------------------------------------
index 9006063..da677f8 100644 (file)
@@ -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();
 }
index 15dc1a0..9f80fa5 100644 (file)
@@ -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"
index d7d932c..d6bd435 100644 (file)
@@ -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));
        }
 }
 
index 2bec69b..99d333d 100644 (file)
@@ -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);
 }
 
index 6f76b89..fd6adde 100644 (file)
@@ -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
index ed79ae2..dd344f1 100644 (file)
@@ -45,6 +45,9 @@
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
 asmlinkage void ret_from_fork(void);
 
 /*
index 53bb9a7..65656c0 100644 (file)
@@ -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
index d51c731..7e9ac99 100644 (file)
@@ -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
 
index 79577f0..f1a2194 100644 (file)
@@ -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);
 
index f1b9d2a..2e3b643 100644 (file)
@@ -7,14 +7,22 @@
 #include <linux/pci.h>
 #include <asm/pci-direct.h>
 #include <asm/acpi.h>
+#include <asm/apic.h>
 
 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;
 }
 
index 4ecd4b3..e6bd095 100644 (file)
@@ -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 */
index e3e42fd..c9cad7b 100644 (file)
@@ -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();
 
index 235822b..39d9a5f 100644 (file)
@@ -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
index a912fed..f73d737 100644 (file)
@@ -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
 }
index 63f39a7..be87c5e 100644 (file)
@@ -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;
        }
index 51e513b..ab62a9f 100644 (file)
@@ -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.
index a14d594..9d30747 100644 (file)
@@ -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;
index 184678f..744fd2f 100644 (file)
@@ -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
index 6ade379..e00b215 100644 (file)
@@ -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");
 
index 9f80569..dcd906f 100644 (file)
@@ -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
        /*
index 8fd93af..e883d85 100644 (file)
@@ -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.
index 24eefb2..b2e1e74 100644 (file)
@@ -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);
index 8a56f8b..99cb28e 100644 (file)
@@ -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);
 
index 767de84..3a0f89d 100644 (file)
@@ -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
index 38c0f33..fe9da16 100644 (file)
@@ -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
 
index 51785a6..bc32fe6 100644 (file)
@@ -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);
 }
index 0ac067f..0613f1f 100644 (file)
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <asm/ptrace.h>
-#include <linux/sched.h>
 #include <linux/kernel_stat.h>
+#include <linux/mv643xx.h>
+#include <linux/sched.h>
+
+#include <asm/ptrace.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <linux/mv643xx.h>
+#include <asm/marvell.h>
 
 static unsigned int irq_base;
 
index 7050b4f..42c94c7 100644 (file)
@@ -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);
index ff699db..2ad0ced 100644 (file)
@@ -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)
 
index 0f94858..ac4f4bf 100644 (file)
@@ -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);
index aae7a80..1cadaa9 100644 (file)
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
+#include <linux/mv643xx.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
-#include <asm/mv64340.h>
 #include <asm/pmon.h>
 
 #include "jaguar_atx_fpga.h"
index 301d672..2699917 100644 (file)
@@ -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 <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/vmalloc.h>
+#include <linux/mv643xx.h>
+
 #include <asm/time.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
@@ -64,7 +66,6 @@
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/tlbflush.h>
-#include <asm/mv64340.h>
 
 #include "jaguar_atx_fpga.h"
 
index 300fe8e..a5764bc 100644 (file)
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/bitops.h>
+#include <linux/mv643xx.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
-#include <asm/mv64340.h>
 #include <asm/system.h>
 
 extern asmlinkage void ocelot_handle_int(void);
index 5b68097..e923644 100644 (file)
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
+#include <linux/mv643xx.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
-#include <asm/mv64340.h>
 #include <asm/pmon.h>
 
 #include "ocelot_c_fpga.h"
index 15998d8..bd02e60 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/pm.h>
 #include <linux/timex.h>
 #include <linux/vmalloc.h>
+#include <linux/mv643xx.h>
 
 #include <asm/time.h>
 #include <asm/bootinfo.h>
@@ -64,9 +65,9 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
+#include <asm/marvell.h>
 #include <linux/bootmem.h>
 #include <linux/blkdev.h>
-#include <asm/mv64340.h>
 #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);
index 1d84d36..027759f 100644 (file)
@@ -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 <linux/types.h>
 #include <linux/pci.h>
-#include <asm/mv64340.h>
+#include <linux/mv643xx.h>
 
 #include <linux/init.h>
 
+#include <asm/marvell.h>
+
 /*
  * We assume the address ranges have already been setup appropriately by
  * the firmware.  PMON in case of the Ocelot C does that.
index 840aad4..c9a660e 100644 (file)
@@ -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));
index 1069645..e4e8137 100644 (file)
@@ -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,
index f20a672..4827ca1 100644 (file)
@@ -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)
-
-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
+       b       ret_from_except_full
 
-       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:
index 388f861..24be0cf 100644 (file)
@@ -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)
index 11f2cd5..9b65029 100644 (file)
@@ -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
 
index d34fe53..813c2cd 100644 (file)
@@ -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;
index 400793c..bcb8357 100644 (file)
@@ -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();
 }
index bd837b5..d7a4e81 100644 (file)
@@ -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(&regs->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;
 
index 497a5d3..4324f8a 100644 (file)
@@ -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(&regs->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, &current->thread.fpr, FP_REGS_SIZE);
        err |= __put_user(signr, &sc->signal);
index 8a9f994..1ad55f0 100644 (file)
@@ -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)
index 7509aa6..98660ae 100644 (file)
@@ -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)) {
index 4ffd2a9..9b7150f 100644 (file)
@@ -9,7 +9,12 @@
 #include <asm/pmac_feature.h>
 #include <asm/pmac_pfunc.h>
 
+#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)
 {
index 356a739..4baa75b 100644 (file)
 #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
index 0df2cdc..6d64a9b 100644 (file)
@@ -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)
index 7964bf6..77e4dc7 100644 (file)
@@ -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));
index a48b950..3a28159 100644 (file)
@@ -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)
-
-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
+       b       ret_from_except_full
 
-       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:
index 60f80a4..b9b7958 100644 (file)
@@ -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;
        }
index 88fc94f..5d59e26 100644 (file)
@@ -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
index 5021978..19b41a3 100644 (file)
@@ -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
index e73621d..e9b275d 100644 (file)
@@ -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)"
index 60b5937..c4a1cef 100644 (file)
@@ -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
index 1f5b5b7..be183fe 100644 (file)
@@ -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
index 93146a8..3192b0b 100644 (file)
@@ -9,7 +9,7 @@
        .align 4;               \
 99:    retl;                   \
         mov    1, %o0;         \
-       .section __ex_table;    \
+       .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
        .text;                  \
index 1fccc52..d1210ff 100644 (file)
@@ -9,7 +9,7 @@
        .align 4;               \
 99:    retl;                   \
         mov    1, %o0;         \
-       .section __ex_table;    \
+       .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
        .text;                  \
index df600b6..f5bfc8d 100644 (file)
@@ -9,7 +9,7 @@
        .align 4;               \
 99:    retl;                   \
         mov    1, %o0;         \
-       .section __ex_table;    \
+       .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
        .text;                  \
index f337f22..2334f11 100644 (file)
@@ -9,7 +9,7 @@
        .align 4;               \
 99:    retl;                   \
         mov    1, %o0;         \
-       .section __ex_table;    \
+       .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
        .text;                  \
index 21a933f..1d2abcf 100644 (file)
@@ -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;                  \
index 816076c..650af3f 100644 (file)
@@ -13,7 +13,7 @@
        .align 4;               \
 99:    retl;                   \
         mov 1, %o0;            \
-       .section __ex_table;    \
+       .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
        .text;                  \
index 817ebda..a22eddb 100644 (file)
@@ -9,7 +9,7 @@
        .align 4;               \
 99:    retl;                   \
         mov    -1, %o0;        \
-       .section __ex_table;    \
+       .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
        .text;                  \
index c2f9463..d5b12f4 100644 (file)
@@ -9,7 +9,7 @@
        .align 4;               \
 99:    retl;                   \
         mov    -1, %o0;        \
-       .section __ex_table;    \
+       .section __ex_table,"a";\
        .align 4;               \
        .word 98b, 99b;         \
        .text;                  \
index 9ed54ba..114ed11 100644 (file)
@@ -85,7 +85,7 @@ __strnlen_user:
         retl
          clr    %o0
 
-       .section __ex_table,#alloc
+       .section __ex_table,"a"
        .align  4
 
        .word   10b, 30b
index e126465..b2f499f 100644 (file)
@@ -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
index eb314ed..f170324 100644 (file)
@@ -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
 
index eb90993..621111d 100644 (file)
@@ -30,6 +30,9 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
 extern void ret_from_fork (void);
 
 
index 89fab51..25ac8a3 100644 (file)
@@ -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"
                );
 }
 
index 7ee4a14..e90ef5d 100644 (file)
@@ -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"
index f1f5966..64a649e 100644 (file)
@@ -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
 
index 03d9c82..0ef2971 100644 (file)
@@ -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;
-
-       /*
-        * 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);
+       int dma = 0;
+
+       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);
index 14f6a62..05983a3 100644 (file)
@@ -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;
index 6ede1f3..37b8cda 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/timer.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/random.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #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) {
index b3bc2e3..29dc87e 100644 (file)
@@ -131,7 +131,9 @@ enum {
        rng_hw_none,
        rng_hw_intel,
        rng_hw_amd,
+#ifdef __i386__
        rng_hw_via,
+#endif
        rng_hw_geode,
 };
 
index c923781..1b05fa6 100644 (file)
@@ -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
index 649677b..5fdf185 100644 (file)
   *
   * (C) 2000,2001,2002,2003,2004 Omnikey AG
   *
-  * (C) 2005 Harald Welte <laforge@gnumonks.org>
+  * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
   *    - 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);
index 46eb371..466e33b 100644 (file)
@@ -3,12 +3,13 @@
  *
  * (c) 2000-2004 Omnikey AG (http://www.omnikey.com/)
  *
- * (C) 2005 Harald Welte <laforge@gnumonks.org>
+ * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
  *     - 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);
index 18a4556..52f3eb4 100644 (file)
@@ -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:
+
+         <http://bluesmoke.sourceforge.net/>
+
+         and:
+
+         <http://buttersideup.com/edacwiki>
+
+         There is also a mailing list for the EDAC project, which can
+         be found via the sourceforge page.
+
 
 comment "Reporting subsystems"
        depends on EDAC
index b10ee46..262e445 100644 (file)
@@ -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<id> attribute f*/
+#if 0
 MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
+#endif
 
 /* csrow<id> 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,
 };
 
index 8ed6ddb..4652512 100644 (file)
@@ -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);
index 4c2af90..6213bd3 100644 (file)
@@ -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),
index 2d2d4ac..960dae5 100644 (file)
@@ -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;
 
index 19b1b01..ad62174 100644 (file)
@@ -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).");
 
index 8159bce..df9d652 100644 (file)
@@ -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},
index 4866fc3..91d25ac 100644 (file)
@@ -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"},
index ca5b4a3..262c441 100644 (file)
@@ -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 "<unkown ERROR>";
+       return "<unknown ERROR>";
 }
 
 
@@ -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;
index 3936336..aeaa1db 100644 (file)
@@ -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;
index bb8d5ef..6c0ba04 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 
+#include <asm/prom.h>
+
 #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;
 }
index 607dbac..81337cd 100644 (file)
@@ -8,6 +8,8 @@
 #include <linux/wait.h>
 #include <linux/cpufreq.h>
 
+#include <asm/prom.h>
+
 #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;
index 906d3ec..423bfa2 100644 (file)
@@ -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);
 }
 
index 5b9ad6c..8e99d40 100644 (file)
@@ -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);
 }
 
index 0842432..f10efb2 100644 (file)
@@ -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 <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("PID algorithm for PowerMacs thermal control");
+MODULE_LICENSE("GPL");
index c2a4e68..ef66bf2 100644 (file)
@@ -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
index d39f584..5d88329 100644 (file)
@@ -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);
 
index 390cc3a..9c7f122 100644 (file)
@@ -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;
index 34c3189..356f447 100644 (file)
@@ -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" },
index 3a2ff1c..0310e3d 100644 (file)
@@ -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,
index 9f02582..0c1d87c 100644 (file)
@@ -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
index f327fac..162f979 100644 (file)
@@ -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,
index 716f8bf..ce34a55 100644 (file)
@@ -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)) {
index 5e5d21a..d4909e5 100644 (file)
@@ -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.
  *
index 76b6a2a..c676b1e 100644 (file)
@@ -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.
index ec4e641..d3aea83 100644 (file)
@@ -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 <obi@linuxtv.org>");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(mt312_attach);
-EXPORT_SYMBOL(vp310_attach);
+EXPORT_SYMBOL(vp310_mt312_attach);
index b3a53a7..074d844 100644 (file)
@@ -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
index 6122ba7..eb15676 100644 (file)
@@ -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;
index d36369e..7c6ccb9 100644 (file)
@@ -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,
index b2e63e9..0bb6e74 100644 (file)
@@ -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",
index 617e4f6..d54bbcd 100644 (file)
@@ -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;
 
index 9f59541..85d964b 100644 (file)
@@ -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;
index 08ffd1f..5588b9a 100644 (file)
@@ -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,
index 048d000..ffd87ce 100644 (file)
@@ -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,
index a7a6ab9..7df5e08 100644 (file)
@@ -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)
index 5a35d3b..6bc63a4 100644 (file)
@@ -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);
index 1a536e8..9db8e13 100644 (file)
@@ -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);
 
index 7b4fb28..a796a4e 100644 (file)
@@ -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;
 }
 
index e7ee619..b6101bf 100644 (file)
@@ -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;
index 156ae57..b1239ac 100644 (file)
@@ -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
index bd0cd28..6699725 100644 (file)
@@ -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);
index 28fa31a..d8dd003 100644 (file)
@@ -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);
index 6bfe84d..21fde43 100644 (file)
@@ -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));
index 1cef238..6aba419 100644 (file)
@@ -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);
 }
 
 
index 227c39a..8d84b04 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
@@ -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);
index d01b6a9..8815c8d 100644 (file)
@@ -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;
index 2306425..e824aca 100644 (file)
@@ -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;
index 27c7730..99baf0e 100644 (file)
@@ -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;
 
index 31e3329..5b7d0f4 100644 (file)
@@ -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 */
 
index 01ddfc8..aa55813 100644 (file)
@@ -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),
index 49b597c..b7f00d6 100644 (file)
@@ -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;
index e8e92c8..1554562 100644 (file)
@@ -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;
 
index 8bc0b52..f8f4503 100644 (file)
@@ -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(
index 166de35..1084525 100644 (file)
@@ -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,
index 0a424a4..bb96ce1 100644 (file)
@@ -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;
        }
index af1d5b4..33157c8 100644 (file)
@@ -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;
index 65dc844..fce2835 100644 (file)
@@ -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;
index 0592354..7cb0b9e 100644 (file)
@@ -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 <linux/module.h>
 #include <linux/wait.h>
index 2d5da3c..1aa3c26 100644 (file)
@@ -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 ");
index 8cf9905..f4183d6 100644 (file)
@@ -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);
index d6469ba..72118ee 100644 (file)
@@ -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");
index 1c2ab3d..00dfdef 100644 (file)
@@ -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);
index c662bf5..9327b62 100644 (file)
@@ -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;
-
-       /* 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.
-        */
+       DPRINTK("ata%u: ENTER, pcs=0x%x base=%d\n", ap->id, pcs, base);
 
-       for (i = 0; i < 4; i++) {
-               mask = (PIIX_PORT_ENABLED << i);
+       /* 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;
+       }
 
-               if ((orig_mask & mask) == mask)
-                       if (combined || (i == ap->hard_port_no))
-                               return 1;
+       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);
        }
 
-       return 0;
+       /* 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)
index 9132698..5060a1a 100644 (file)
@@ -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
  *
- *     Determine string which represents the highest speed
- *     (highest bit in @udma_mask).
+ *     Return matching XFER_* value for @xfer_mask.  Only the highest
+ *     bit of @xfer_mask is considered.
  *
  *     LOCKING:
  *     None.
  *
  *     RETURNS:
- *     Constant C string representing highest speed listed in
- *     @udma_mask, or the constant C string "<n/a>".
+ *     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;
 
-static const char *ata_mode_string(unsigned int mask)
+       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)
 {
-       int i;
+       const struct ata_xfer_ent *ent;
 
-       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;
+       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;
+}
 
-       return "<n/a>";
+/**
+ *     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;
 
-out:
-       return xfer_mode_str[i];
+       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 @modemask).
+ *
+ *     LOCKING:
+ *     None.
+ *
+ *     RETURNS:
+ *     Constant C string representing highest speed listed in
+ *     @mode_mask, or the constant C string "<n/a>".
+ */
+static const char *ata_mode_string(unsigned int xfer_mask)
+{
+       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 "<n/a>";
 }
 
 /**
@@ -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);
+       return ata_pack_xfermask(pio_mask, mwdma_mask, udma_mask);
 }
 
-static inline void
-ata_queue_delayed_pio_task(struct ata_port *ap, unsigned long delay)
+/**
+ *     ata_port_queue_task - Queue port_task
+ *     @ap: The ata_port to queue port_task for
+ *
+ *     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)
 {
-       if (!(ap->flags & ATA_FLAG_FLUSH_PIO_TASK))
-               queue_delayed_work(ata_wq, &ap->pio_task, 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_flush_pio_tasks - Flush pio_task
- *     @ap: the target ata_port
+ *     ata_port_flush_task - Flush port_task
+ *     @ap: The ata_port to flush port_task for
  *
- *     After this function completes, pio_task is
- *     guranteed not to be running or scheduled.
+ *     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
- *
- *     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.
+ *     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
+ *
+ *     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;
 
-       if (ap->ops->probe_reset) {
-               unsigned int classes[ATA_MAX_DEVICES];
-               int rc;
+       ata_port_probe(ap);
 
-               ata_port_probe(ap);
+       /* reset */
+       if (ap->ops->probe_reset) {
+               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++) {
+                       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);
+       }
 
+       /* read IDENTIFY page and configure devices */
        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);
+               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) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+       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);
+       int i;
 
        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);
+
+               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, u8 xfer_mode,
-                           unsigned int xfer_shift)
+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 = 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) || !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 */
-       rc = ata_host_set_pio(ap);
-       if (rc)
-               goto err_out;
+       /* 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);
 
-       /* step 2: choose the best data xfer mode */
-       xfer_mode = xfer_shift = 0;
-       rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift);
+               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 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)
+{
+       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)
 {
-       printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, disabling DMA\n",
-               ap->id, dev->devno);
+       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);
index d0bd94a..ccedb45 100644 (file)
@@ -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));
index d822eba..f4c48c9 100644 (file)
@@ -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);
index 7fa807d..e5862ad 100644 (file)
@@ -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,
index cdf800e..4f2a67e 100644 (file)
 #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;
index 5c5822e..8fb6242 100644 (file)
@@ -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);
index 5d02ff4..b65462f 100644 (file)
@@ -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;
index f3763d2..a37579c 100644 (file)
@@ -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);
 }
 
 /**
index 419dd3c..193722d 100644 (file)
@@ -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;
 
index 95fb493..cc1faa3 100644 (file)
@@ -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);
index 43e67d6..60ea4a3 100644 (file)
@@ -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");
 
index 4dd6865..b5c96e7 100644 (file)
@@ -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)
index df8e566..4660428 100644 (file)
@@ -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;
 
index bfc8a93..620c9a9 100644 (file)
@@ -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;
 
index 7f9838d..98c05bc 100644 (file)
@@ -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;
index bd39bbd..151fda8 100644 (file)
@@ -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;
index 9e32485..86908a6 100644 (file)
@@ -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;
index ad416ae..7db4254 100644 (file)
@@ -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;
        }
 
index 6b8bd3c..995b47c 100644 (file)
@@ -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);
+       }
 
-                       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;
                }
-               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;
        }
+
        return 0;
 }
 
index 3690b04..bd38970 100644 (file)
@@ -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);
index a2e201d..b961d56 100644 (file)
@@ -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;
 }
 
index e5d0f92..feec47b 100644 (file)
@@ -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);
 
index ab727ea..10e6b3a 100644 (file)
@@ -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);
index 3e7baf4..5e5328d 100644 (file)
@@ -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;
 }
 
index 1a6d087..f86a28d 100644 (file)
@@ -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);
index eda4497..c4d13bf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * V9FS FID Management
  *
- *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ *  Copyright (C) 2005, 2006 by Eric Van Hensbergen <ericvh@gmail.com>
  *
  *  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;
-}
index 84c673a..1fc2dd0 100644 (file)
@@ -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);
index 1a28ef9..5b2ce21 100644 (file)
@@ -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);
index ef33865..6135249 100644 (file)
@@ -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");
        }
index 69cf290..a759278 100644 (file)
@@ -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);
index 2dd806d..12c9cc9 100644 (file)
 #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,
 };
index c7e14d9..de3a129 100644 (file)
 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;
+               goto put_fid;
+       }
+
+       vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
+       if (vfid == NULL) {
+               dprintk(DEBUG_ERROR, "out of memory\n");
+               goto clunk_fid;
                }
 
-               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;
+       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;
+       }
 
-               if (file->f_flags & O_EXCL)
-                       open_mode |= V9FS_OEXCL;
+       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);
 
-               if (v9ses->extended) {
-                       if (file->f_flags & O_TRUNC)
-                               open_mode |= V9FS_OTRUNC;
+       return 0;
 
-                       if (file->f_flags & O_APPEND)
-                               open_mode |= V9FS_OAPPEND;
-               }
+destroy_vfid:
+       v9fs_fid_destroy(vfid);
 
-               result = v9fs_t_open(v9ses, newfid, open_mode, &fcall);
-               if (result < 0) {
-                       PRINT_FCALL_ERROR("open failed", fcall);
-                       kfree(fcall);
-                       return result;
-               }
+clunk_fid:
+       v9fs_t_clunk(v9ses, fid);
 
-               iounit = fcall->params.ropen.iounit;
+put_fid:
+       v9fs_put_idpool(fid, &v9ses->fidpool);
                kfree(fcall);
-       } else {
-               /* create case */
-               newfid = v9fid->fid;
-               iounit = v9fid->iounit;
-               v9fid->fidcreate = 0;
-       }
-
-       file->private_data = v9fid;
-
-       v9fid->rdir_pos = 0;
-       v9fid->rdir_fcall = NULL;
-       v9fid->fidopen = 1;
-       v9fid->filp = file;
-       v9fid->iounit = iounit;
 
-       return 0;
+       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;
 }
 
index 63e5b03..3ad8455 100644 (file)
@@ -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;
+       return 0;
 
-       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;
-               }
+error:
+       if (fid >= 0)
+               v9fs_put_idpool(fid, &v9ses->fidpool);
 
-               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);
-       }
+       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;
 
-       /* walk to the newly created file and put the fid in the dentry */
-       wfidno = v9fs_get_idpool(&v9ses->fidpool);
-       if (wfidno < 0) {
+       nfid = v9fs_get_idpool(&v9ses->fidpool);
+       if (nfid < 0) {
                eprintk(KERN_WARNING, "no free fids available\n");
-               return -ENOSPC;
+               return ERR_PTR(-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;
+       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 (!v9fs_fid_create(file_dentry, v9ses, wfidno, 0)) {
-               v9fs_put_idpool(wfidno, &v9ses->fidpool);
-
-               goto CleanUpFid;
+       err = v9fs_fid_insert(ret, dentry);
+       if (err < 0) {
+               v9fs_fid_destroy(ret);
+               goto clunk_fid;
        }
 
-       if ((perm & V9FS_DMSYMLINK) || (perm & V9FS_DMLINK) ||
-           (perm & V9FS_DMNAMEDPIPE) || (perm & V9FS_DMSOCKET) ||
-           (perm & V9FS_DMDEVICE))
-               return 0;
+       return ret;
 
-       result = v9fs_t_stat(v9ses, wfidno, &fcall);
-       if (result < 0) {
-               PRINT_FCALL_ERROR("stat error", fcall);
-               goto CleanUpFid;
-       }
+clunk_fid:
+       v9fs_t_clunk(v9ses, nfid);
 
+error:
+       kfree(fcall);
+       return ERR_PTR(err);
+}
 
-       file_inode = v9fs_get_inode(sb,
-               p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode));
+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;
 
-       if ((!file_inode) || IS_ERR(file_inode)) {
-               dprintk(DEBUG_ERROR, "create inode failed\n");
-               result = -EBADF;
-               goto CleanUpFid;
+       ret = NULL;
+       err = v9fs_t_stat(v9ses, fid, &fcall);
+       if (err) {
+               PRINT_FCALL_ERROR("stat error", fcall);
+               goto error;
        }
 
-       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);
+       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;
+       }
 
-       return 0;
+       v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb);
+       kfree(fcall);
+       return ret;
 
-      CleanUpFid:
+error:
        kfree(fcall);
-       fcall = NULL;
+       if (ret)
+               iput(ret);
 
-       if (newfid >= 0) {
-               err = v9fs_t_clunk(v9ses, newfid);
-               if (err < 0)
-                       dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
-       }
-       if (wfidno >= 0) {
-               err = v9fs_t_clunk(v9ses, wfidno);
-               if (err < 0)
-                       dprintk(DEBUG_ERROR, "clunk failed: %d\n", err);
-       }
-       return result;
+       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? */
+       kfree(fcall);
+       dentry->d_op = &v9fs_dentry_operations;
+       d_instantiate(dentry, inode);
+       return 0;
 
-free_mem:
+error:
        kfree(fcall);
-       return retval;
+       if (vfid)
+               v9fs_fid_destroy(vfid);
+
+       if (inode)
+               iput(inode);
+
+       return err;
+
 }
 
 /**
index 2c4fa75..d05318f 100644 (file)
@@ -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);
index 3c03aad..7b25463 100644 (file)
@@ -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);
index ef5ae6f..2a0c1f4 100644 (file)
@@ -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,
index 812c6bb..432ba15 100644 (file)
@@ -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,
index 537ac70..c666769 100644 (file)
@@ -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;
index 7fe8541..8ad52f5 100644 (file)
@@ -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;
index a173bba..11dc830 100644 (file)
@@ -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);
index 3fc4238..0384e53 100644 (file)
@@ -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))
index 8bd8ac0..b8f5cd1 100644 (file)
@@ -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);
index 923371b..d13fcd3 100644 (file)
--- 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;
 }
 
index 768b581..44fabea 100644 (file)
@@ -5,6 +5,7 @@
  *  Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/capability.h>
 #include <linux/cdev.h>
 #include <linux/fsnotify.h>
+#include <linux/sysctl.h>
+#include <linux/percpu_counter.h>
+
+#include <asm/atomic.h>
 
 /* 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);
+static struct percpu_counter nr_files __cacheline_aligned_in_smp;
 
-/* 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)
+static inline void file_free_rcu(struct rcu_head *head)
 {
-       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);
-       }
+       struct file *f =  container_of(head, struct file, f_u.fu_rcuhead);
+       kmem_cache_free(filp_cachep, f);
 }
 
-void filp_dtor(void *objp, struct kmem_cache *cachep, unsigned long dflags)
+static inline void file_free(struct file *f)
 {
-       unsigned long flags;
-       spin_lock_irqsave(&filp_count_lock, flags);
-       files_stat.nr_files--;
-       spin_unlock_irqrestore(&filp_count_lock, flags);
+       percpu_counter_dec(&nr_files);
+       call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
 }
 
-static inline void file_free_rcu(struct rcu_head *head)
+/*
+ * Return the total number of open files in the system
+ */
+static int get_nr_files(void)
 {
-       struct file *f =  container_of(head, struct file, f_u.fu_rcuhead);
-       kmem_cache_free(filp_cachep, f);
+       return percpu_counter_read_positive(&nr_files);
 }
 
-static inline void file_free(struct file *f)
+/*
+ * Return the maximum number of open files in the system
+ */
+int get_max_files(void)
 {
-       call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
+       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
@@ -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);
 } 
index b635e16..d4d0c41 100644 (file)
@@ -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);
 
index 5f0652d..f169564 100644 (file)
@@ -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;
index 3e51dd1..cf55b22 100644 (file)
@@ -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. */
index 557dcf3..8dc2b03 100644 (file)
@@ -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);
index fd741ce..636593b 100644 (file)
@@ -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,                     \
index e8c56a3..2cadc30 100644 (file)
@@ -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"
index cf7828f..e1fceb8 100644 (file)
@@ -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;
 }
index d22d4cf..0f60cc0 100644 (file)
@@ -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;
 }
index a6f4585..616ff2b 100644 (file)
@@ -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 */
index 23ceaa7..9c77258 100644 (file)
@@ -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
index f339fe2..54f61b7 100644 (file)
@@ -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; i<DLM_HASH_SIZE; i++) {
-               bucket = &(dlm->resources[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)
                        dlm_print_one_lock_resource(res);
-               }
        }
        spin_unlock(&dlm->spinlock);
 }
index 6ee3083..8f3a9e3 100644 (file)
@@ -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; i<DLM_HASH_SIZE; i++) {
-               while (!list_empty(&dlm->resources[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; i<DLM_HASH_SIZE; i++)
-               INIT_LIST_HEAD(&dlm->resources[i]);
+       for (i=0; i<DLM_HASH_BUCKETS; i++)
+               INIT_HLIST_HEAD(&dlm->lockres_hash[i]);
 
        strcpy(dlm->name, domain);
        dlm->key = key;
index 2e2e95e..847dd3c 100644 (file)
@@ -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);
index ed76bda..1e23200 100644 (file)
@@ -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; i<DLM_HASH_SIZE; i++) {
-               bucket = &(dlm->resources[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; i<DLM_HASH_SIZE; i++) {
-               bucket = &(dlm->resources[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,
index b6ba292..e6f207e 100644 (file)
@@ -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
index 1715bc9..8a4048b 100644 (file)
@@ -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.
index 0bbd22f..cbfd45a 100644 (file)
@@ -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,
index 8122489..315472a 100644 (file)
@@ -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;
        }
 
index d329c9d..4be801f 100644 (file)
@@ -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)
index 8d8e477..e89de9b 100644 (file)
@@ -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)
index dfb8a5b..c5b1ac5 100644 (file)
 
 /* 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;
index 046824b..8dd3aaf 100644 (file)
@@ -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(),
index 78010ad..1e4a938 100644 (file)
@@ -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:
index d722579..8aada8e 100644 (file)
--- 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,
index 0eaad41..91b7c15 100644 (file)
@@ -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);
 }
index cde5d48..14bd224 100644 (file)
@@ -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);
        }
index f347317..be12879 100644 (file)
@@ -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 <<
index b33d67b..d60f623 100644 (file)
@@ -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;
index b7a1795..5a9d272 100644 (file)
@@ -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 =
index c812330..284f785 100644 (file)
@@ -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 */
index 395e582..d04cff2 100644 (file)
@@ -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)     ) |
index 4a6f49a..368d8f8 100644 (file)
@@ -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);
index 6636698..110f8d6 100644 (file)
 #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
index 9387a5e..0c2acc9 100644 (file)
@@ -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));
 }
 
 /*
index 4dc8ddb..09ec447 100644 (file)
@@ -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)                \
index d30b857..ff9ac8d 100644 (file)
@@ -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) { }
 
index a4a84d5..862e497 100644 (file)
@@ -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;                                             \
index ca5cec9..34755c0 100644 (file)
@@ -26,6 +26,9 @@
  *  <linux/vt_buffer.h> 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);
index 90d005b..5638518 100644 (file)
@@ -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__
index 7dfb408..5207758 100644 (file)
@@ -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) { }
index bda2f21..6a2af2f 100644 (file)
@@ -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
index e9590c0..80a7832 100644 (file)
@@ -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))
index 237fc2b..ffc7462 100644 (file)
@@ -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<<TIF_SINGLESTEP)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_RESTOREALL                (1<<TIF_RESTOREALL)
-#define _TIF_SAVE_NVGPRS       (1<<TIF_SAVE_NVGPRS)
 #define _TIF_NOERROR           (1<<TIF_NOERROR)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SYSCALL_T_OR_A    (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK    (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
-                                _TIF_NEED_RESCHED | _TIF_RESTOREALL | \
-                                _TIF_RESTORE_SIGMASK)
-#define _TIF_PERSYSCALL_MASK   (_TIF_RESTOREALL|_TIF_NOERROR|_TIF_SAVE_NVGPRS)
+                                _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
+#define _TIF_PERSYSCALL_MASK   (_TIF_RESTOREALL|_TIF_NOERROR)
 
 #endif /* __KERNEL__ */
 
index b2e65e8..6a89dbb 100644 (file)
@@ -118,6 +118,8 @@ static inline void sched_cacheflush(void)
 extern void account_vtime(struct task_struct *);
 extern void account_tick_vtime(struct task_struct *);
 extern void account_system_vtime(struct task_struct *);
+#else
+#define account_vtime(x) do { /* empty */ } while (0)
 #endif
 
 #define finish_arch_switch(prev) do {                                       \
index 0caf601..34c4b43 100644 (file)
@@ -20,7 +20,7 @@
        "4:     ba      3b\n"                           \
        "        mov    %5, %0\n"                       \
        "       .previous\n"                            \
-       "       .section __ex_table,#alloc\n"           \
+       "       .section __ex_table,\"a\"\n"            \
        "       .align  4\n"                            \
        "       .word   1b, 4b\n"                       \
        "       .word   2b, 4b\n"                       \
index 203e8ee..c91d1e3 100644 (file)
@@ -136,7 +136,7 @@ __asm__ __volatile__(                                                       \
        "b      2b\n\t"                                                 \
        " mov   %3, %0\n\n\t"                                           \
        ".previous\n\t"                                                 \
-       ".section __ex_table,#alloc\n\t"                                \
+       ".section __ex_table,\"a\"\n\t"                                 \
        ".align 4\n\t"                                                  \
        ".word  1b, 3b\n\t"                                             \
        ".previous\n\n\t"                                               \
@@ -148,7 +148,7 @@ if (__builtin_constant_p(ret) && ret == -EFAULT)                    \
 __asm__ __volatile__(                                                  \
        "/* Put user asm ret, inline. */\n"                             \
 "1:\t" "st"#size "a %1, [%2] %%asi\n\n\t"                              \
-       ".section __ex_table,#alloc\n\t"                                \
+       ".section __ex_table,\"a\"\n\t"                                 \
        ".align 4\n\t"                                                  \
        ".word  1b, __ret_efault\n\n\t"                                 \
        ".previous\n\n\t"                                               \
@@ -163,7 +163,7 @@ __asm__ __volatile__(                                                       \
        "ret\n\t"                                                       \
        " restore %%g0, %3, %%o0\n\n\t"                                 \
        ".previous\n\t"                                                 \
-       ".section __ex_table,#alloc\n\t"                                \
+       ".section __ex_table,\"a\"\n\t"                                 \
        ".align 4\n\t"                                                  \
        ".word  1b, 3b\n\n\t"                                           \
        ".previous\n\n\t"                                               \
@@ -206,7 +206,7 @@ __asm__ __volatile__(                                                       \
        "b      2b\n\t"                                                 \
        " mov   %3, %0\n\n\t"                                           \
        ".previous\n\t"                                                 \
-       ".section __ex_table,#alloc\n\t"                                \
+       ".section __ex_table,\"a\"\n\t"                                 \
        ".align 4\n\t"                                                  \
        ".word  1b, 3b\n\n\t"                                           \
        ".previous\n\t"                                                 \
@@ -218,7 +218,7 @@ if (__builtin_constant_p(retval) && retval == -EFAULT)                      \
 __asm__ __volatile__(                                                  \
        "/* Get user asm ret, inline. */\n"                             \
 "1:\t" "ld"#size "a [%1] %%asi, %0\n\n\t"                              \
-       ".section __ex_table,#alloc\n\t"                                \
+       ".section __ex_table,\"a\"\n\t"                                 \
        ".align 4\n\t"                                                  \
        ".word  1b,__ret_efault\n\n\t"                                  \
        ".previous\n\t"                                                 \
@@ -233,7 +233,7 @@ __asm__ __volatile__(                                                       \
        "ret\n\t"                                                       \
        " restore %%g0, %2, %%o0\n\n\t"                                 \
        ".previous\n\t"                                                 \
-       ".section __ex_table,#alloc\n\t"                                \
+       ".section __ex_table,\"a\"\n\t"                                 \
        ".align 4\n\t"                                                  \
        ".word  1b, 3b\n\n\t"                                           \
        ".previous\n\t"                                                 \
index 8fad50f..ae7dfb7 100644 (file)
@@ -696,6 +696,8 @@ COMPATIBLE_IOCTL(MEMLOCK)
 COMPATIBLE_IOCTL(MEMUNLOCK)
 COMPATIBLE_IOCTL(MEMGETREGIONCOUNT)
 COMPATIBLE_IOCTL(MEMGETREGIONINFO)
+COMPATIBLE_IOCTL(MEMGETBADBLOCK)
+COMPATIBLE_IOCTL(MEMSETBADBLOCK)
 /* NBD */
 ULONG_IOCTL(NBD_SET_SOCK)
 ULONG_IOCTL(NBD_SET_BLKSIZE)
index 418b610..9901b85 100644 (file)
@@ -60,8 +60,6 @@ extern void put_filp(struct file *);
 extern int get_unused_fd(void);
 extern void FASTCALL(put_unused_fd(unsigned int fd));
 struct kmem_cache;
-extern void filp_ctor(void * objp, struct kmem_cache *cachep, unsigned long cflags);
-extern void filp_dtor(void * objp, struct kmem_cache *cachep, unsigned long dflags);
 
 extern struct file ** alloc_fd_array(int);
 extern void free_fd_array(struct file **, int);
index e059da9..128d008 100644 (file)
@@ -35,6 +35,7 @@ struct files_stat_struct {
        int max_files;          /* tunable */
 };
 extern struct files_stat_struct files_stat;
+extern int get_max_files(void);
 
 struct inodes_stat_t {
        int nr_inodes;
@@ -1418,9 +1419,6 @@ extern int is_bad_inode(struct inode *);
 extern struct file_operations read_fifo_fops;
 extern struct file_operations write_fifo_fops;
 extern struct file_operations rdwr_fifo_fops;
-extern struct file_operations read_pipe_fops;
-extern struct file_operations write_pipe_fops;
-extern struct file_operations rdwr_pipe_fops;
 
 extern int fs_may_remount_ro(struct super_block *);
 
@@ -1666,6 +1664,8 @@ extern int vfs_follow_link(struct nameidata *, const char *);
 extern int page_readlink(struct dentry *, char __user *, int);
 extern void *page_follow_link_light(struct dentry *, struct nameidata *);
 extern void page_put_link(struct dentry *, struct nameidata *, void *);
+extern int __page_symlink(struct inode *inode, const char *symname, int len,
+               gfp_t gfp_mask);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
 extern struct inode_operations page_symlink_inode_operations;
 extern int generic_readlink(struct dentry *, char __user *, int);
index 20f9148..7851e6b 100644 (file)
@@ -157,9 +157,9 @@ extern void FASTCALL(free_cold_page(struct page *page));
 
 void page_alloc_init(void);
 #ifdef CONFIG_NUMA
-void drain_remote_pages(void);
+void drain_node_pages(int node);
 #else
-static inline void drain_remote_pages(void) { };
+static inline void drain_node_pages(int node) { };
 #endif
 
 #endif /* __LINUX_GFP_H */
index 6361544..6401c31 100644 (file)
@@ -116,6 +116,10 @@ extern int hrtimer_try_to_cancel(struct hrtimer *timer);
 extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
 extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
 
+#ifdef CONFIG_NO_IDLE_HZ
+extern ktime_t hrtimer_get_next_event(void);
+#endif
+
 static inline int hrtimer_active(const struct hrtimer *timer)
 {
        return timer->state == HRTIMER_PENDING;
index d82d4c0..bda23e0 100644 (file)
        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
index 2558aba..d051a82 100644 (file)
@@ -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)
index 01f03bc..968b1aa 100644 (file)
@@ -6,6 +6,10 @@
 #include <linux/mmzone.h>
 #include <linux/notifier.h>
 
+struct page;
+struct zone;
+struct pglist_data;
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * pgdat resizing functions
index 82b83da..1709b50 100644 (file)
 #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
index bd6708e..6825255 100644 (file)
@@ -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)
index b87aefa..c2ec6c7 100644 (file)
@@ -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);
index 7d51149..dad78ce 100644 (file)
@@ -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;
index ff2e09c..62e6314 100644 (file)
@@ -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);
index 346d81e..e04e0b0 100644 (file)
        .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 */
 
index fbea12d..a8eab86 100644 (file)
@@ -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);
index 5ae51f1..14bc9cf 100644 (file)
@@ -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
  *
index 0cf8146..8cf15a5 100644 (file)
@@ -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. */
index 12d291b..4d46e90 100644 (file)
@@ -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;
index acf6c15..32b48e8 100644 (file)
@@ -50,6 +50,9 @@
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
+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,
index fe3a9a9..bf7c419 100644 (file)
@@ -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();
        }
index a918f77..1fe76d9 100644 (file)
@@ -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();
 
index 5643cfe..954981b 100644 (file)
@@ -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++;
+       md->pages++;
+       if (pte_dirty || PageDirty(page))
+               md->dirty++;
 
-       if (count > md->mapcount_max)
-               md->mapcount_max = count;
+       if (PageSwapCache(page))
+               md->swapcache++;
 
-       md->pages++;
+       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 (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 (md->anon)
-                       seq_printf(m," anon=%lu",md->anon);
+       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);
+       }
 
-               for_each_online_node(n)
-                       if (md->node[n])
-                               seq_printf(m, " N%d=%lu", n, md->node[n]);
+       if (!md->pages)
+               goto out;
 
-               seq_putc(m, '\n');
-       }
+       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)
index c86c737..78747af 100644 (file)
@@ -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);
 }
index 791690d..234bd48 100644 (file)
@@ -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;
index d8ce5ff..67f0e20 100644 (file)
--- 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);
 }
index add05d8..d0bd7f0 100644 (file)
--- 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);
 }
index cce3dda..e9ec06d 100644 (file)
--- 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
 
 /*
index b0af759..7ccf763 100644 (file)
@@ -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;
index 93ad59a..31d98b5 100644 (file)
@@ -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;
        }
index 7fa3a5a..f36b35e 100644 (file)
@@ -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;
-
-       if (netif_carrier_ok(p->dev)) {
-               u32 cost = port_cost(p->dev);
-
-               spin_lock_bh(&p->br->lock);
-               if (p->state == BR_STATE_DISABLED) {
-                       p->path_cost = cost;
-                       br_stp_enable_port(p);
+       br = p->br;
+
+       if (netif_carrier_ok(dev))
+               p->path_cost = port_cost(dev);
+
+       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);
index 35cf3a0..23dea14 100644 (file)
@@ -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 */
index aa68e0a..35d1d34 100644 (file)
@@ -2,7 +2,7 @@
  *  net/dccp/ccids/ccid3.c
  *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com>
  *
  *  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);
index 36339eb..08f80e2 100644 (file)
@@ -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);
                
index 5027bbe..af06350 100644 (file)
@@ -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);
                
index 1b5989b..c323cc6 100644 (file)
@@ -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);
index be97caf..c164b23 100644 (file)
@@ -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;
 }
index b7773bf..b65c201 100644 (file)
@@ -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;
 }
index abd62f9..0c29679 100644 (file)
@@ -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++;