Merge branch 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 24 May 2007 16:17:12 +0000 (09:17 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 24 May 2007 16:17:12 +0000 (09:17 -0700)
* 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6:
  NFS: Fix nfs_direct_dirty_pages()
  NFS: Fix handful of compiler warnings in direct.c
  NFS: Avoid a deadlock situation on write

78 files changed:
Documentation/CodingStyle
Documentation/HOWTO
Documentation/block/capability.txt [new file with mode: 0644]
Documentation/dontdiff
Documentation/i386/boot.txt
Documentation/initrd.txt
Documentation/kernel-parameters.txt
Documentation/memory-barriers.txt
Documentation/spi/spi-summary
MAINTAINERS
arch/i386/Kconfig
arch/i386/mach-generic/bigsmp.c
arch/um/os-Linux/start_up.c
arch/x86_64/Kconfig
arch/x86_64/kernel/k8.c
block/genhd.c
drivers/block/floppy.c
drivers/char/cyclades.c
drivers/crypto/geode-aes.c
drivers/crypto/geode-aes.h
drivers/hwmon/applesmc.c
drivers/isdn/hardware/eicon/capifunc.c
drivers/isdn/hardware/eicon/message.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/hfc_usb.c
drivers/isdn/hisax/hisax_fcpcipnp.c
drivers/isdn/hisax/st5481_init.c
drivers/isdn/hisax/st5481_usb.c
drivers/md/bitmap.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/raid0.c
drivers/message/i2o/driver.c
drivers/misc/phantom.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/card/queue.h
drivers/spi/mpc52xx_psc_spi.c
drivers/spi/omap_uwire.c
drivers/spi/spidev.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-fsl.h
drivers/video/Kconfig
drivers/video/imxfb.c
drivers/video/pm2fb.c
drivers/video/pm3fb.c
drivers/video/ps3fb.c
drivers/video/w100fb.c
fs/compat.c
fs/ecryptfs/file.c
fs/ecryptfs/mmap.c
fs/exec.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/inode.c
fs/reiserfs/dir.c
fs/signalfd.c
include/asm-i386/atomic.h
include/asm-i386/local.h
include/linux/capability.h
include/linux/freezer.h
include/linux/genhd.h
include/linux/raid/bitmap.h
include/linux/sched.h
kernel/exit.c
kernel/fork.c
kernel/irq/spurious.c
kernel/kthread.c
kernel/power/process.c
kernel/power/swap.c
kernel/sched.c
kernel/signal.c
kernel/time/tick-broadcast.c
kernel/time/tick-sched.c
kernel/workqueue.c
lib/Kconfig.debug
mm/page_alloc.c
mm/slub.c

index afc2867..b49b92e 100644 (file)
@@ -495,29 +495,40 @@ re-formatting you may want to take a look at the man page.  But
 remember: "indent" is not a fix for bad programming.
 
 
-               Chapter 10: Configuration-files
+               Chapter 10: Kconfig configuration files
 
-For configuration options (arch/xxx/Kconfig, and all the Kconfig files),
-somewhat different indentation is used.
+For all of the Kconfig* configuration files throughout the source tree,
+the indentation is somewhat different.  Lines under a "config" definition
+are indented with one tab, while help text is indented an additional two
+spaces.  Example:
 
-Help text is indented with 2 spaces.
-
-if CONFIG_EXPERIMENTAL
-       tristate CONFIG_BOOM
-       default n
-       help
-         Apply nitroglycerine inside the keyboard (DANGEROUS)
-       bool CONFIG_CHEER
-       depends on CONFIG_BOOM
-       default y
+config AUDIT
+       bool "Auditing support"
+       depends on NET
        help
-         Output nice messages when you explode
-endif
+         Enable auditing infrastructure that can be used with another
+         kernel subsystem, such as SELinux (which requires this for
+         logging of avc messages output).  Does not do system-call
+         auditing without CONFIG_AUDITSYSCALL.
+
+Features that might still be considered unstable should be defined as
+dependent on "EXPERIMENTAL":
+
+config SLUB
+       depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT
+       bool "SLUB (Unqueued Allocator)"
+       ...
+
+while seriously dangerous features (such as write support for certain
+filesystems) should advertise this prominently in their prompt string:
+
+config ADFS_FS_RW
+       bool "ADFS write support (DANGEROUS)"
+       depends on ADFS_FS
+       ...
 
-Generally, CONFIG_EXPERIMENTAL should surround all options not considered
-stable. All options that are known to trash data (experimental write-
-support for file-systems, for instance) should be denoted (DANGEROUS), other
-experimental options should be denoted (EXPERIMENTAL).
+For full documentation on the configuration files, see the file
+Documentation/kbuild/kconfig-language.txt.
 
 
                Chapter 11: Data structures
index 48123db..ced9207 100644 (file)
@@ -396,26 +396,6 @@ bugme-janitor mailing list (every change in the bugzilla is mailed here)
 
 
 
-Managing bug reports
---------------------
-
-One of the best ways to put into practice your hacking skills is by fixing
-bugs reported by other people. Not only you will help to make the kernel
-more stable, you'll learn to fix real world problems and you will improve
-your skills, and other developers will be aware of your presence. Fixing
-bugs is one of the best ways to get merits among other developers, because
-not many people like wasting time fixing other people's bugs.
-
-To work in the already reported bug reports, go to http://bugzilla.kernel.org.
-If you want to be advised of the future bug reports, you can subscribe to the
-bugme-new mailing list (only new bug reports are mailed here) or to the
-bugme-janitor mailing list (every change in the bugzilla is mailed here)
-
-       http://lists.osdl.org/mailman/listinfo/bugme-new
-       http://lists.osdl.org/mailman/listinfo/bugme-janitors
-
-
-
 Mailing lists
 -------------
 
diff --git a/Documentation/block/capability.txt b/Documentation/block/capability.txt
new file mode 100644 (file)
index 0000000..2f17294
--- /dev/null
@@ -0,0 +1,15 @@
+Generic Block Device Capability
+===============================================================================
+This file documents the sysfs file block/<disk>/capability
+
+capability is a hex word indicating which capabilities a specific disk
+supports.  For more information on bits not listed here, see
+include/linux/genhd.h
+
+Capability                             Value
+-------------------------------------------------------------------------------
+GENHD_FL_MEDIA_CHANGE_NOTIFY           4
+       When this bit is set, the disk supports Asynchronous Notification
+       of media change events.  These events will be broadcast to user
+       space via kernel uevent.
+
index 64e9f6c..595a5ea 100644 (file)
 *.grp
 *.gz
 *.html
+*.i
 *.jpeg
 *.ko
 *.log
 *.lst
+*.moc
 *.mod.c
 *.o
 *.orig
@@ -25,6 +27,9 @@
 *.s
 *.sgml
 *.so
+*.symtypes
+*.tab.c
+*.tab.h
 *.tex
 *.ver
 *.xml
 *_vga16.c
 *cscope*
 *~
+*.9
+*.9.gz
 .*
 .cscope
 53c700_d.h
+53c7xx_d.h
+53c7xx_u.h
 53c8xx_d.h*
 BitKeeper
 COPYING
@@ -70,9 +79,11 @@ bzImage*
 classlist.h*
 comp*.log
 compile.h*
+conf
 config
 config-*
 config_data.h*
+config_data.gz*
 conmakehash
 consolemap_deftbl.c*
 crc32table.h*
@@ -81,18 +92,23 @@ defkeymap.c*
 devlist.h*
 docproc
 dummy_sym.c*
+elf2ecoff
 elfconfig.h*
 filelist
 fixdep
 fore200e_mkfirm
 fore200e_pca_fw.c*
+gconf
 gen-devlist
 gen-kdb_cmds.c*
 gen_crc32table
 gen_init_cpio
 genksyms
 gentbl
+*_gray256.c
 ikconfig.h*
+initramfs_data.cpio
+initramfs_data.cpio.gz
 initramfs_list
 kallsyms
 kconfig
@@ -100,19 +116,30 @@ kconfig.tk
 keywords.c*
 ksym.c*
 ksym.h*
+kxgettext
+lkc_defs.h
 lex.c*
+lex.*.c
+lk201-map.c
 logo_*.c
 logo_*_clut224.c
 logo_*_mono.c
 lxdialog
 mach-types
 mach-types.h
+machtypes.h
 make_times_h
 map
 maui_boot.h
+mconf
+miboot*
 mk_elfconfig
+mkboot
+mkbugboot
 mkdep
+mkprep
 mktables
+mktree
 modpost
 modversions.h*
 offset.h
@@ -120,18 +147,28 @@ offsets.h
 oui.c*
 parse.c*
 parse.h*
+patches*
+pca200e.bin
+pca200e_ecd.bin2
+piggy.gz
+piggyback
 pnmtologo
 ppc_defs.h*
 promcon_tbl.c*
 pss_boot.h
+qconf
 raid6altivec*.c
 raid6int*.c
 raid6tables.c
+relocs
+series
 setup
 sim710_d.h*
+sImage
 sm_tbl*
 split-include
 tags
+tftpboot.img
 times.h*
 tkparse
 trix_boot.h
@@ -139,8 +176,11 @@ utsrelease.h*
 version.h*
 vmlinux
 vmlinux-*
+vmlinux.aout
 vmlinux.lds
 vsyscall.lds
 wanxlfw.inc
 uImage
-zImage
+unifdef
+zImage*
+zconf.hash.c
index 66fa67f..35985b3 100644 (file)
@@ -2,7 +2,7 @@
                     ----------------------------
 
                    H. Peter Anvin <hpa@zytor.com>
-                       Last update 2007-05-16
+                       Last update 2007-05-23
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -202,6 +202,8 @@ All general purpose boot loaders should write the fields marked
 nonstandard address should fill in the fields marked (reloc); other
 boot loaders can ignore those fields.
 
+The byte order of all fields is littleendian (this is x86, after all.)
+
 Field name:    setup_secs
 Type:          read
 Offset/size:   0x1f1/1
@@ -280,14 +282,16 @@ Type:             read
 Offset/size:   0x206/2
 Protocol:      2.00+
 
-  Contains the boot protocol version, e.g. 0x0204 for version 2.04.
+  Contains the boot protocol version, in (major << 8)+minor format,
+  e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
+  10.17.
 
 Field name:    readmode_swtch
 Type:          modify (optional)
 Offset/size:   0x208/4
 Protocol:      2.00+
 
-  Boot loader hook (see separate chapter.)
+  Boot loader hook (see ADVANCED BOOT LOADER HOOKS below.)
 
 Field name:    start_sys
 Type:          read
@@ -304,10 +308,17 @@ Protocol: 2.00+
   If set to a nonzero value, contains a pointer to a NUL-terminated
   human-readable kernel version number string, less 0x200.  This can
   be used to display the kernel version to the user.  This value
-  should be less than (0x200*setup_sects).  For example, if this value
-  is set to 0x1c00, the kernel version number string can be found at
-  offset 0x1e00 in the kernel file.  This is a valid value if and only
-  if the "setup_sects" field contains the value 14 or higher.
+  should be less than (0x200*setup_sects).
+
+  For example, if this value is set to 0x1c00, the kernel version
+  number string can be found at offset 0x1e00 in the kernel file.
+  This is a valid value if and only if the "setup_sects" field
+  contains the value 15 or higher, as:
+
+       0x1c00  < 15*0x200 (= 0x1e00) but
+       0x1c00 >= 14*0x200 (= 0x1c00)
+
+       0x1c00 >> 9 = 14, so the minimum value for setup_secs is 15.
 
 Field name:    type_of_loader
 Type:          write (obligatory)
@@ -377,7 +388,7 @@ Protocol:   2.00+
 
   This field can be modified for two purposes:
 
-  1. as a boot loader hook (see separate chapter.)
+  1. as a boot loader hook (see ADVANCED BOOT LOADER HOOKS below.)
 
   2. if a bootloader which does not install a hook loads a
      relocatable kernel at a nonstandard address it will have to modify
@@ -715,7 +726,7 @@ switched off, especially if the loaded kernel has the floppy driver as
 a demand-loaded module!
 
 
-**** ADVANCED BOOT TIME HOOKS
+**** ADVANCED BOOT LOADER HOOKS
 
 If the boot loader runs in a particularly hostile environment (such as
 LOADLIN, which runs under DOS) it may be impossible to follow the
@@ -740,4 +751,5 @@ IMPORTANT: All the hooks are required to preserve %esp, %ebp, %esi and
        set them up to BOOT_DS (0x18) yourself.
 
        After completing your hook, you should jump to the address
-       that was in this field before your boot loader overwrote it.
+       that was in this field before your boot loader overwrote it
+       (relocated, if appropriate.)
index 15f1b35..d3dc505 100644 (file)
@@ -27,16 +27,20 @@ When using initrd, the system typically boots as follows:
   1) the boot loader loads the kernel and the initial RAM disk
   2) the kernel converts initrd into a "normal" RAM disk and
      frees the memory used by initrd
-  3) initrd is mounted read-write as root
-  4) /linuxrc is executed (this can be any valid executable, including
+  3) if the root device is not /dev/ram0, the old (deprecated)
+     change_root procedure is followed. see the "Obsolete root change
+     mechanism" section below.
+  4) root device is mounted. if it is /dev/ram0, the initrd image is
+     then mounted as root
+  5) /sbin/init is executed (this can be any valid executable, including
      shell scripts; it is run with uid 0 and can do basically everything
-     init can do)
-  5) linuxrc mounts the "real" root file system
-  6) linuxrc places the root file system at the root directory using the
+     init can do).
+  6) init mounts the "real" root file system
+  7) init places the root file system at the root directory using the
      pivot_root system call
-  7) the usual boot sequence (e.g. invocation of /sbin/init) is performed
-     on the root file system
-  8) the initrd file system is removed
+  8) init execs the /sbin/init on the new root filesystem, performing
+     the usual boot sequence
+  9) the initrd file system is removed
 
 Note that changing the root directory does not involve unmounting it.
 It is therefore possible to leave processes running on initrd during that
@@ -70,7 +74,7 @@ initrd adds the following new options:
   root=/dev/ram0
 
     initrd is mounted as root, and the normal boot procedure is followed,
-    with the RAM disk still mounted as root.
+    with the RAM disk mounted as root.
 
 Compressed cpio images
 ----------------------
@@ -137,11 +141,11 @@ We'll describe the loopback device method:
     # mkdir /mnt/dev
     # mknod /mnt/dev/console c 5 1
  5) copy all the files that are needed to properly use the initrd
-    environment. Don't forget the most important file, /linuxrc
-    Note that /linuxrc's permissions must include "x" (execute).
+    environment. Don't forget the most important file, /sbin/init
+    Note that /sbin/init's permissions must include "x" (execute).
  6) correct operation the initrd environment can frequently be tested
     even without rebooting with the command
-    # chroot /mnt /linuxrc
+    # chroot /mnt /sbin/init
     This is of course limited to initrds that do not interfere with the
     general system state (e.g. by reconfiguring network interfaces,
     overwriting mounted devices, trying to start already running demons,
@@ -154,7 +158,7 @@ We'll describe the loopback device method:
     # gzip -9 initrd
 
 For experimenting with initrd, you may want to take a rescue floppy and
-only add a symbolic link from /linuxrc to /bin/sh. Alternatively, you
+only add a symbolic link from /sbin/init to /bin/sh. Alternatively, you
 can try the experimental newlib environment [2] to create a small
 initrd.
 
@@ -163,15 +167,14 @@ boot loaders support initrd. Since the boot process is still compatible
 with an older mechanism, the following boot command line parameters
 have to be given:
 
-  root=/dev/ram0 init=/linuxrc rw
+  root=/dev/ram0 rw
 
 (rw is only necessary if writing to the initrd file system.)
 
 With LOADLIN, you simply execute
 
      LOADLIN <kernel> initrd=<disk_image>
-e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0
-       init=/linuxrc rw
+e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 rw
 
 With LILO, you add the option INITRD=<path> to either the global section
 or to the section of the respective kernel in /etc/lilo.conf, and pass
@@ -179,7 +182,7 @@ the options using APPEND, e.g.
 
   image = /bzImage
     initrd = /boot/initrd.gz
-    append = "root=/dev/ram0 init=/linuxrc rw"
+    append = "root=/dev/ram0 rw"
 
 and run /sbin/lilo
 
@@ -191,7 +194,7 @@ Now you can boot and enjoy using initrd.
 Changing the root device
 ------------------------
 
-When finished with its duties, linuxrc typically changes the root device
+When finished with its duties, init typically changes the root device
 and proceeds with starting the Linux system on the "real" root device.
 
 The procedure involves the following steps:
@@ -217,7 +220,7 @@ must exist before calling pivot_root. Example:
 # mkdir initrd
 # pivot_root . initrd
 
-Now, the linuxrc process may still access the old root via its
+Now, the init process may still access the old root via its
 executable, shared libraries, standard input/output/error, and its
 current root directory. All these references are dropped by the
 following command:
@@ -249,10 +252,6 @@ disk can be freed:
 It is also possible to use initrd with an NFS-mounted root, see the
 pivot_root(8) man page for details.
 
-Note: if linuxrc or any program exec'ed from it terminates for some
-reason, the old change_root mechanism is invoked (see section "Obsolete
-root change mechanism").
-
 
 Usage scenarios
 ---------------
@@ -264,15 +263,15 @@ as follows:
   1) system boots from floppy or other media with a minimal kernel
      (e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and
      loads initrd
-  2) /linuxrc determines what is needed to (1) mount the "real" root FS
+  2) /sbin/init determines what is needed to (1) mount the "real" root FS
      (i.e. device type, device drivers, file system) and (2) the
      distribution media (e.g. CD-ROM, network, tape, ...). This can be
      done by asking the user, by auto-probing, or by using a hybrid
      approach.
-  3) /linuxrc loads the necessary kernel modules
-  4) /linuxrc creates and populates the root file system (this doesn't
+  3) /sbin/init loads the necessary kernel modules
+  4) /sbin/init creates and populates the root file system (this doesn't
      have to be a very usable system yet)
-  5) /linuxrc invokes pivot_root to change the root file system and
+  5) /sbin/init invokes pivot_root to change the root file system and
      execs - via chroot - a program that continues the installation
   6) the boot loader is installed
   7) the boot loader is configured to load an initrd with the set of
@@ -291,7 +290,7 @@ different hardware configurations in a single administrative domain. In
 such cases, it is desirable to generate only a small set of kernels
 (ideally only one) and to keep the system-specific part of configuration
 information as small as possible. In this case, a common initrd could be
-generated with all the necessary modules. Then, only /linuxrc or a file
+generated with all the necessary modules. Then, only /sbin/init or a file
 read by it would have to be different.
 
 A third scenario are more convenient recovery disks, because information
@@ -337,6 +336,25 @@ This old, deprecated mechanism is commonly called "change_root", while
 the new, supported mechanism is called "pivot_root".
 
 
+Mixed change_root and pivot_root mechanism
+------------------------------------------
+
+In case you did not want to use root=/dev/ram0 to trig the pivot_root mechanism,
+you may create both /linuxrc and /sbin/init in your initrd image.
+
+/linuxrc would contain only the following:
+
+#! /bin/sh
+mount -n -t proc proc /proc
+echo 0x0100 >/proc/sys/kernel/real-root-dev
+umount -n /proc
+
+Once linuxrc exited, the kernel would mount again your initrd as root,
+this time executing /sbin/init. Again, it would be duty of this init
+to build the right environment (maybe using the root= device passed on
+the cmdline) before the final execution of the real /sbin/init.
+
+
 Resources
 ---------
 
index 09220a1..aae2282 100644 (file)
@@ -396,6 +396,26 @@ and is between 256 and 4096 characters. It is defined in the file
                        clocksource is not available, it defaults to PIT.
                        Format: { pit | tsc | cyclone | pmtmr }
 
+       clocksource=    [GENERIC_TIME] Override the default clocksource
+                       Format: <string>
+                       Override the default clocksource and use the clocksource
+                       with the name specified.
+                       Some clocksource names to choose from, depending on
+                       the platform:
+                       [all] jiffies (this is the base, fallback clocksource)
+                       [ACPI] acpi_pm
+                       [ARM] imx_timer1,OSTS,netx_timer,mpu_timer2,
+                               pxa_timer,timer3,32k_counter,timer0_1
+                       [AVR32] avr32
+                       [IA-32] pit,hpet,tsc,vmi-timer;
+                               scx200_hrt on Geode; cyclone on IBM x440
+                       [MIPS] MIPS
+                       [PARISC] cr16
+                       [S390] tod
+                       [SH] SuperH
+                       [SPARC64] tick
+                       [X86-64] hpet,tsc
+
        code_bytes      [IA32] How many bytes of object code to print in an
                        oops report.
                        Range: 0 - 8192
@@ -1807,10 +1827,6 @@ and is between 256 and 4096 characters. It is defined in the file
 
        time            Show timing data prefixed to each printk message line
 
-       clocksource=    [GENERIC_TIME] Override the default clocksource
-                       Override the default clocksource and use the clocksource
-                       with the name specified.
-
        tipar.timeout=  [HW,PPT]
                        Set communications timeout in tenths of a second
                        (default 15).
index 58408dd..650657c 100644 (file)
@@ -24,7 +24,7 @@ Contents:
  (*) Explicit kernel barriers.
 
      - Compiler barrier.
-     - The CPU memory barriers.
+     - CPU memory barriers.
      - MMIO write barrier.
 
  (*) Implicit kernel memory barriers.
@@ -265,7 +265,7 @@ Memory barriers are such interventions.  They impose a perceived partial
 ordering over the memory operations on either side of the barrier.
 
 Such enforcement is important because the CPUs and other devices in a system
-can use a variety of tricks to improve performance - including reordering,
+can use a variety of tricks to improve performance, including reordering,
 deferral and combination of memory operations; speculative loads; speculative
 branch prediction and various types of caching.  Memory barriers are used to
 override or suppress these tricks, allowing the code to sanely control the
@@ -457,7 +457,7 @@ sequence, Q must be either &A or &B, and that:
        (Q == &A) implies (D == 1)
        (Q == &B) implies (D == 4)
 
-But! CPU 2's perception of P may be updated _before_ its perception of B, thus
+But!  CPU 2's perception of P may be updated _before_ its perception of B, thus
 leading to the following situation:
 
        (Q == &B) and (D == 2) ????
@@ -573,7 +573,7 @@ Basically, the read barrier always has to be there, even though it can be of
 the "weaker" type.
 
 [!] Note that the stores before the write barrier would normally be expected to
-match the loads after the read barrier or data dependency barrier, and vice
+match the loads after the read barrier or the data dependency barrier, and vice
 versa:
 
        CPU 1                           CPU 2
@@ -588,7 +588,7 @@ versa:
 EXAMPLES OF MEMORY BARRIER SEQUENCES
 ------------------------------------
 
-Firstly, write barriers act as partial orderings on store operations.
+Firstly, write barriers act as partial orderings on store operations.
 Consider the following sequence of events:
 
        CPU 1
@@ -608,15 +608,15 @@ STORE B, STORE C } all occurring before the unordered set of { STORE D, STORE E
        +-------+       :      :
        |       |       +------+
        |       |------>| C=3  |     }     /\
-       |       |  :    +------+     }-----  \  -----> Events perceptible
-       |       |  :    | A=1  |     }        \/       to rest of system
+       |       |  :    +------+     }-----  \  -----> Events perceptible to
+       |       |  :    | A=1  |     }        \/       the rest of the system
        |       |  :    +------+     }
        | CPU 1 |  :    | B=2  |     }
        |       |       +------+     }
        |       |   wwwwwwwwwwwwwwww }   <--- At this point the write barrier
        |       |       +------+     }        requires all stores prior to the
        |       |  :    | E=5  |     }        barrier to be committed before
-       |       |  :    +------+     }        further stores may be take place.
+       |       |  :    +------+     }        further stores may take place
        |       |------>| D=4  |     }
        |       |       +------+
        +-------+       :      :
@@ -626,7 +626,7 @@ STORE B, STORE C } all occurring before the unordered set of { STORE D, STORE E
                           V
 
 
-Secondly, data dependency barriers act as partial orderings on data-dependent
+Secondly, data dependency barriers act as partial orderings on data-dependent
 loads.  Consider the following sequence of events:
 
        CPU 1                   CPU 2
@@ -975,7 +975,7 @@ compiler from moving the memory accesses either side of it to the other side:
 
        barrier();
 
-This a general barrier - lesser varieties of compiler barrier do not exist.
+This is a general barrier - lesser varieties of compiler barrier do not exist.
 
 The compiler barrier has no direct effect on the CPU, which may then reorder
 things however it wishes.
@@ -997,7 +997,7 @@ The Linux kernel has eight basic CPU memory barriers:
 All CPU memory barriers unconditionally imply compiler barriers.
 
 SMP memory barriers are reduced to compiler barriers on uniprocessor compiled
-systems because it is assumed that a CPU will be appear to be self-consistent,
+systems because it is assumed that a CPU will appear to be self-consistent,
 and will order overlapping accesses correctly with respect to itself.
 
 [!] Note that SMP memory barriers _must_ be used to control the ordering of
@@ -1146,9 +1146,9 @@ for each construct.  These operations all imply certain barriers:
 Therefore, from (1), (2) and (4) an UNLOCK followed by an unconditional LOCK is
 equivalent to a full barrier, but a LOCK followed by an UNLOCK is not.
 
-[!] Note: one of the consequence of LOCKs and UNLOCKs being only one-way
-    barriers is that the effects instructions outside of a critical section may
-    seep into the inside of the critical section.
+[!] Note: one of the consequences of LOCKs and UNLOCKs being only one-way
+    barriers is that the effects of instructions outside of a critical section
+    may seep into the inside of the critical section.
 
 A LOCK followed by an UNLOCK may not be assumed to be full memory barrier
 because it is possible for an access preceding the LOCK to happen after the
@@ -1239,7 +1239,7 @@ three CPUs; then should the following sequence of events occur:
        UNLOCK M                        UNLOCK Q
        *D = d;                         *H = h;
 
-Then there is no guarantee as to what order CPU #3 will see the accesses to *A
+Then there is no guarantee as to what order CPU 3 will see the accesses to *A
 through *H occur in, other than the constraints imposed by the separate locks
 on the separate CPUs. It might, for example, see:
 
@@ -1269,12 +1269,12 @@ However, if the following occurs:
                                        UNLOCK M        [2]
                                        *H = h;
 
-CPU #3 might see:
+CPU 3 might see:
 
        *E, LOCK M [1], *C, *B, *A, UNLOCK M [1],
                LOCK M [2], *H, *F, *G, UNLOCK M [2], *D
 
-But assuming CPU #1 gets the lock first, it won't see any of:
+But assuming CPU 1 gets the lock first, CPU 3 won't see any of:
 
        *B, *C, *D, *F, *G or *H preceding LOCK M [1]
        *A, *B or *C following UNLOCK M [1]
@@ -1327,12 +1327,12 @@ spinlock, for example:
                                        mmiowb();
                                        spin_unlock(Q);
 
-this will ensure that the two stores issued on CPU #1 appear at the PCI bridge
-before either of the stores issued on CPU #2.
+this will ensure that the two stores issued on CPU 1 appear at the PCI bridge
+before either of the stores issued on CPU 2.
 
 
-Furthermore, following a store by a load to the same device obviates the need
-for an mmiowb(), because the load forces the store to complete before the load
+Furthermore, following a store by a load from the same device obviates the need
+for the mmiowb(), because the load forces the store to complete before the load
 is performed:
 
        CPU 1                           CPU 2
@@ -1363,7 +1363,7 @@ circumstances in which reordering definitely _could_ be a problem:
 
  (*) Atomic operations.
 
- (*) Accessing devices (I/O).
+ (*) Accessing devices.
 
  (*) Interrupts.
 
@@ -1399,7 +1399,7 @@ To wake up a particular waiter, the up_read() or up_write() functions have to:
  (1) read the next pointer from this waiter's record to know as to where the
      next waiter record is;
 
- (4) read the pointer to the waiter's task structure;
+ (2) read the pointer to the waiter's task structure;
 
  (3) clear the task pointer to tell the waiter it has been given the semaphore;
 
@@ -1407,7 +1407,7 @@ To wake up a particular waiter, the up_read() or up_write() functions have to:
 
  (5) release the reference held on the waiter's task struct.
 
-In otherwords, it has to perform this sequence of events:
+In other words, it has to perform this sequence of events:
 
        LOAD waiter->list.next;
        LOAD waiter->task;
@@ -1502,7 +1502,7 @@ operations and adjusting reference counters towards object destruction, and as
 such the implicit memory barrier effects are necessary.
 
 
-The following operation are potential problems as they do _not_ imply memory
+The following operations are potential problems as they do _not_ imply memory
 barriers, but might be used for implementing such things as UNLOCK-class
 operations:
 
@@ -1517,7 +1517,7 @@ With these the appropriate explicit memory barrier should be used if necessary
 
 The following also do _not_ imply memory barriers, and so may require explicit
 memory barriers under some circumstances (smp_mb__before_atomic_dec() for
-instance)):
+instance):
 
        atomic_add();
        atomic_sub();
@@ -1641,8 +1641,8 @@ functions:
      indeed have special I/O space access cycles and instructions, but many
      CPUs don't have such a concept.
 
-     The PCI bus, amongst others, defines an I/O space concept - which on such
-     CPUs as i386 and x86_64 cpus readily maps to the CPU's concept of I/O
+     The PCI bus, amongst others, defines an I/O space concept which - on such
+     CPUs as i386 and x86_64 - readily maps to the CPU's concept of I/O
      space.  However, it may also be mapped as a virtual I/O space in the CPU's
      memory map, particularly on those CPUs that don't support alternate I/O
      spaces.
@@ -1664,7 +1664,7 @@ functions:
      i386 architecture machines, for example, this is controlled by way of the
      MTRR registers.
 
-     Ordinarily, these will be guaranteed to be fully ordered and uncombined,,
+     Ordinarily, these will be guaranteed to be fully ordered and uncombined,
      provided they're not accessing a prefetchable device.
 
      However, intermediary hardware (such as a PCI bridge) may indulge in
@@ -1689,7 +1689,7 @@ functions:
 
  (*) ioreadX(), iowriteX()
 
-     These will perform as appropriate for the type of access they're actually
+     These will perform appropriately for the type of access they're actually
      doing, be it inX()/outX() or readX()/writeX().
 
 
@@ -1705,7 +1705,7 @@ of arch-specific code.
 
 This means that it must be considered that the CPU will execute its instruction
 stream in any order it feels like - or even in parallel - provided that if an
-instruction in the stream depends on the an earlier instruction, then that
+instruction in the stream depends on an earlier instruction, then that
 earlier instruction must be sufficiently complete[*] before the later
 instruction may proceed; in other words: provided that the appearance of
 causality is maintained.
@@ -1795,8 +1795,8 @@ eventually become visible on all CPUs, there's no guarantee that they will
 become apparent in the same order on those other CPUs.
 
 
-Consider dealing with a system that has pair of CPUs (1 & 2), each of which has
-a pair of parallel data caches (CPU 1 has A/B, and CPU 2 has C/D):
+Consider dealing with a system that has a pair of CPUs (1 & 2), each of which
+has a pair of parallel data caches (CPU 1 has A/B, and CPU 2 has C/D):
 
                    :
                    :                          +--------+
@@ -1835,7 +1835,7 @@ Imagine the system has the following properties:
 
  (*) the coherency queue is not flushed by normal loads to lines already
      present in the cache, even though the contents of the queue may
-     potentially effect those loads.
+     potentially affect those loads.
 
 Imagine, then, that two writes are made on the first CPU, with a write barrier
 between them to guarantee that they will appear to reach that CPU's caches in
@@ -1845,7 +1845,7 @@ the requisite order:
        =============== =============== =======================================
                                        u == 0, v == 1 and p == &u, q == &u
        v = 2;
-       smp_wmb();                      Make sure change to v visible before
+       smp_wmb();                      Make sure change to v is visible before
                                         change to p
        <A:modify v=2>                  v is now in cache A exclusively
        p = &v;
@@ -1853,7 +1853,7 @@ the requisite order:
 
 The write memory barrier forces the other CPUs in the system to perceive that
 the local CPU's caches have apparently been updated in the correct order.  But
-now imagine that the second CPU that wants to read those values:
+now imagine that the second CPU wants to read those values:
 
        CPU 1           CPU 2           COMMENT
        =============== =============== =======================================
@@ -1861,7 +1861,7 @@ now imagine that the second CPU that wants to read those values:
                        q = p;
                        x = *q;
 
-The above pair of reads may then fail to happen in expected order, as the
+The above pair of reads may then fail to happen in the expected order, as the
 cacheline holding p may get updated in one of the second CPU's caches whilst
 the update to the cacheline holding v is delayed in the other of the second
 CPU's caches by some other cache event:
@@ -1916,7 +1916,7 @@ access depends on a read, not all do, so it may not be relied on.
 
 Other CPUs may also have split caches, but must coordinate between the various
 cachelets for normal memory accesses.  The semantics of the Alpha removes the
-need for coordination in absence of memory barriers.
+need for coordination in the absence of memory barriers.
 
 
 CACHE COHERENCY VS DMA
@@ -1931,10 +1931,10 @@ invalidate them as well).
 
 In addition, the data DMA'd to RAM by a device may be overwritten by dirty
 cache lines being written back to RAM from a CPU's cache after the device has
-installed its own data, or cache lines simply present in a CPUs cache may
-simply obscure the fact that RAM has been updated, until at such time as the
-cacheline is discarded from the CPU's cache and reloaded.  To deal with this,
-the appropriate part of the kernel must invalidate the overlapping bits of the
+installed its own data, or cache lines present in the CPU's cache may simply
+obscure the fact that RAM has been updated, until at such time as the cacheline
+is discarded from the CPU's cache and reloaded.  To deal with this, the
+appropriate part of the kernel must invalidate the overlapping bits of the
 cache on each CPU.
 
 See Documentation/cachetlb.txt for more information on cache management.
@@ -1944,7 +1944,7 @@ CACHE COHERENCY VS MMIO
 -----------------------
 
 Memory mapped I/O usually takes place through memory locations that are part of
-a window in the CPU's memory space that have different properties assigned than
+a window in the CPU's memory space that has different properties assigned than
 the usual RAM directed window.
 
 Amongst these properties is usually the fact that such accesses bypass the
@@ -1960,7 +1960,7 @@ THE THINGS CPUS GET UP TO
 =========================
 
 A programmer might take it for granted that the CPU will perform memory
-operations in exactly the order specified, so that if a CPU is, for example,
+operations in exactly the order specified, so that if the CPU is, for example,
 given the following piece of code to execute:
 
        a = *A;
@@ -1969,7 +1969,7 @@ given the following piece of code to execute:
        d = *D;
        *E = e;
 
-They would then expect that the CPU will complete the memory operation for each
+they would then expect that the CPU will complete the memory operation for each
 instruction before moving on to the next one, leading to a definite sequence of
 operations as seen by external observers in the system:
 
@@ -1986,8 +1986,8 @@ assumption doesn't hold because:
  (*) loads may be done speculatively, and the result discarded should it prove
      to have been unnecessary;
 
- (*) loads may be done speculatively, leading to the result having being
-     fetched at the wrong time in the expected sequence of events;
+ (*) loads may be done speculatively, leading to the result having been fetched
+     at the wrong time in the expected sequence of events;
 
  (*) the order of the memory accesses may be rearranged to promote better use
      of the CPU buses and caches;
@@ -2069,12 +2069,12 @@ AND THEN THERE'S THE ALPHA
 
 The DEC Alpha CPU is one of the most relaxed CPUs there is.  Not only that,
 some versions of the Alpha CPU have a split data cache, permitting them to have
-two semantically related cache lines updating at separate times.  This is where
+two semantically-related cache lines updated at separate times.  This is where
 the data dependency barrier really becomes necessary as this synchronises both
 caches with the memory coherence system, thus making it seem like pointer
 changes vs new data occur in the right order.
 
-The Alpha defines the Linux's kernel's memory barrier model.
+The Alpha defines the Linux kernel's memory barrier model.
 
 See the subsection on "Cache Coherency" above.
 
index 795fbb4..76ea6c8 100644 (file)
@@ -1,26 +1,30 @@
 Overview of Linux kernel SPI support
 ====================================
 
-02-Dec-2005
+21-May-2007
 
 What is SPI?
 ------------
 The "Serial Peripheral Interface" (SPI) is a synchronous four wire serial
 link used to connect microcontrollers to sensors, memory, and peripherals.
+It's a simple "de facto" standard, not complicated enough to acquire a
+standardization body.  SPI uses a master/slave configuration.
 
 The three signal wires hold a clock (SCK, often on the order of 10 MHz),
 and parallel data lines with "Master Out, Slave In" (MOSI) or "Master In,
 Slave Out" (MISO) signals.  (Other names are also used.)  There are four
 clocking modes through which data is exchanged; mode-0 and mode-3 are most
 commonly used.  Each clock cycle shifts data out and data in; the clock
-doesn't cycle except when there is data to shift.
+doesn't cycle except when there is a data bit to shift.  Not all data bits
+are used though; not every protocol uses those full duplex capabilities.
 
-SPI masters may use a "chip select" line to activate a given SPI slave
+SPI masters use a fourth "chip select" line to activate a given SPI slave
 device, so those three signal wires may be connected to several chips
-in parallel.  All SPI slaves support chipselects.  Some devices have
+in parallel.  All SPI slaves support chipselects; they are usually active
+low signals, labeled nCSx for slave 'x' (e.g. nCS0).  Some devices have
 other signals, often including an interrupt to the master.
 
-Unlike serial busses like USB or SMBUS, even low level protocols for
+Unlike serial busses like USB or SMBus, even low level protocols for
 SPI slave functions are usually not interoperable between vendors
 (except for commodities like SPI memory chips).
 
@@ -33,6 +37,11 @@ SPI slave functions are usually not interoperable between vendors
   - Some devices may use eight bit words.  Others may different word
     lengths, such as streams of 12-bit or 20-bit digital samples.
 
+  - Words are usually sent with their most significant bit (MSB) first,
+    but sometimes the least significant bit (LSB) goes first instead.
+
+  - Sometimes SPI is used to daisy-chain devices, like shift registers.
+
 In the same way, SPI slaves will only rarely support any kind of automatic
 discovery/enumeration protocol.  The tree of slave devices accessible from
 a given SPI master will normally be set up manually, with configuration
@@ -44,6 +53,14 @@ half-duplex SPI, for request/response protocols), SSP ("Synchronous
 Serial Protocol"), PSP ("Programmable Serial Protocol"), and other
 related protocols.
 
+Some chips eliminate a signal line by combining MOSI and MISO, and
+limiting themselves to half-duplex at the hardware level.  In fact
+some SPI chips have this signal mode as a strapping option.  These
+can be accessed using the same programming interface as SPI, but of
+course they won't handle full duplex transfers.  You may find such
+chips described as using "three wire" signaling: SCK, data, nCSx.
+(That data line is sometimes called MOMI or SISO.)
+
 Microcontrollers often support both master and slave sides of the SPI
 protocol.  This document (and Linux) currently only supports the master
 side of SPI interactions.
@@ -74,6 +91,32 @@ interfaces with SPI modes.  Given SPI support, they could use MMC or SD
 cards without needing a special purpose MMC/SD/SDIO controller.
 
 
+I'm confused.  What are these four SPI "clock modes"?
+-----------------------------------------------------
+It's easy to be confused here, and the vendor documentation you'll
+find isn't necessarily helpful.  The four modes combine two mode bits:
+
+ - CPOL indicates the initial clock polarity.  CPOL=0 means the
+   clock starts low, so the first (leading) edge is rising, and
+   the second (trailing) edge is falling.  CPOL=1 means the clock
+   starts high, so the first (leading) edge is falling.
+
+ - CPHA indicates the clock phase used to sample data; CPHA=0 says
+   sample on the leading edge, CPHA=1 means the trailing edge.
+
+   Since the signal needs to stablize before it's sampled, CPHA=0
+   implies that its data is written half a clock before the first
+   clock edge.  The chipselect may have made it become available.
+
+Chip specs won't always say "uses SPI mode X" in as many words,
+but their timing diagrams will make the CPOL and CPHA modes clear.
+
+In the SPI mode number, CPOL is the high order bit and CPHA is the
+low order bit.  So when a chip's timing diagram shows the clock
+starting low (CPOL=0) and data stabilized for sampling during the
+trailing clock edge (CPHA=1), that's SPI mode 1.
+
+
 How do these driver programming interfaces work?
 ------------------------------------------------
 The <linux/spi/spi.h> header file includes kerneldoc, as does the
index 22ab401..953291d 100644 (file)
@@ -332,6 +332,9 @@ L:  linux-usb-devel@lists.sourceforge.net
 W:     http://www.linux-usb.org/SpeedTouch/
 S:     Maintained
 
+ALCHEMY AU1XX0 MMC DRIVER
+S:     Orphan
+
 ALI1563 I2C DRIVER
 P:     Rudolf Marek
 M:     r.marek@assembler.cz
@@ -418,6 +421,12 @@ P: Ian Molton
 M:     spyro@f2s.com
 S:     Maintained
 
+ARM PRIMECELL MMCI PL180/1 DRIVER
+P:     Russell King
+M:     rmk@arm.linux.org.uk
+L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+S:     Maintained
+
 ARM/ADI ROADRUNNER MACHINE SUPPORT
 P:     Lennert Buytenhek
 M:     kernel@wantstofly.org
@@ -649,6 +658,9 @@ L:  linux-atm-general@lists.sourceforge.net (subscribers-only)
 W:     http://linux-atm.sourceforge.net
 S:     Maintained
 
+ATMEL AT91 MCI DRIVER
+S:     Orphan
+
 ATMEL MACB ETHERNET DRIVER
 P:     Haavard Skinnemoen
 M:     hskinnemoen@atmel.com
@@ -2380,6 +2392,13 @@ M:       stelian@popies.net
 W:     http://popies.net/meye/
 S:     Maintained
 
+MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
+P:     Pavel Pisa
+M:     ppisa@pikron.com
+L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:     http://mmc.drzeus.cx/wiki/Controllers/Freescale/SDHC
+S:     Maintained
+
 MOUSE AND MISC DEVICES [GENERAL]
 P:     Alessandro Rubini
 M:     rubini@ipvvis.unipv.it
@@ -2900,6 +2919,9 @@ M:        nico@cam.org
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
+PXA MMCI DRIVER
+S:     Orphan
+
 QLOGIC QLA2XXX FC-SCSI DRIVER
 P:     Andrew Vasquez
 M:     linux-driver@qlogic.com
@@ -3416,6 +3438,13 @@ P:      Alex Dubov
 M:      oakad@yahoo.com
 S:      Maintained
 
+TI OMAP MMC INTERFACE DRIVER
+P:     Carlos Aguiar, Anderson Briglia and Syed Khasim
+M:     linux-omap-open-source@linux.omap.com 
+W:     http://linux.omap.com
+W:     http://www.muru.com/linux/omap/
+S:     Maintained
+
 TI OMAP RANDOM NUMBER GENERATOR SUPPORT
 P:     Deepak Saxena
 M:     dsaxena@plexity.net
index c2d54b8..8770a5d 100644 (file)
@@ -891,7 +891,7 @@ config PHYSICAL_ALIGN
          Don't change this unless you know what you are doing.
 
 config HOTPLUG_CPU
-       bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+       bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
        depends on SMP && HOTPLUG && EXPERIMENTAL && !X86_VOYAGER
        ---help---
          Say Y here to experiment with turning CPUs off and on, and to
index e932d34..58a477b 100644 (file)
@@ -21,7 +21,7 @@
 
 static int dmi_bigsmp; /* can be set by dmi scanners */
 
-static __init int hp_ht_bigsmp(struct dmi_system_id *d)
+static int hp_ht_bigsmp(struct dmi_system_id *d)
 {
 #ifdef CONFIG_X86_GENERICARCH
        printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
@@ -31,7 +31,7 @@ static __init int hp_ht_bigsmp(struct dmi_system_id *d)
 }
 
 
-static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
+static struct dmi_system_id bigsmp_dmi_table[] = {
        { hp_ht_bigsmp, "HP ProLiant DL760 G2", {
                DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
                DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
@@ -45,7 +45,7 @@ static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
 };
 
 
-static int __init probe_bigsmp(void)
+static int probe_bigsmp(void)
 { 
        if (def_to_bigsmp)
                dmi_bigsmp = 1;
index 79471f8..3fc13fa 100644 (file)
@@ -144,9 +144,7 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
                int exit_with = WEXITSTATUS(status);
                if (exit_with == 2)
                        non_fatal("check_ptrace : child exited with status 2. "
-                                 "Serious trouble happening! Try updating "
-                                 "your host skas patch!\nDisabling SYSEMU "
-                                 "support.");
+                                 "\nDisabling SYSEMU support.\n");
                non_fatal("check_ptrace : child exited with exitcode %d, while "
                          "expecting %d; status 0x%x\n", exit_with,
                          exitcode, status);
@@ -209,6 +207,7 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
 static void __init check_sysemu(void)
 {
        void *stack;
+       unsigned long regs[MAX_REG_NR];
        int pid, n, status, count=0;
 
        non_fatal("Checking syscall emulation patch for ptrace...");
@@ -225,11 +224,20 @@ static void __init check_sysemu(void)
                fatal("check_sysemu : expected SIGTRAP, got status = %d",
                      status);
 
-       n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
-                  os_getpid());
-       if(n < 0)
-               fatal_perror("check_sysemu : failed to modify system call "
-                            "return");
+       if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+               fatal_perror("check_sysemu : PTRACE_GETREGS failed");
+       if(PT_SYSCALL_NR(regs) != __NR_getpid){
+               non_fatal("check_sysemu got system call number %d, "
+                         "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid);
+               goto fail;
+       }
+
+       n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
+       if(n < 0){
+               non_fatal("check_sysemu : failed to modify system call "
+                         "return");
+               goto fail;
+       }
 
        if (stop_ptraced_child(pid, stack, 0, 0) < 0)
                goto fail_stopped;
index 145bb82..5ce9443 100644 (file)
@@ -428,12 +428,15 @@ config NR_CPUS
          memory in the static kernel configuration.
 
 config HOTPLUG_CPU
-       bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+       bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
        depends on SMP && HOTPLUG && EXPERIMENTAL
        help
                Say Y here to experiment with turning CPUs off and on.  CPUs
                can be controlled through /sys/devices/system/cpu/cpu#.
-               Say N if you want to disable CPU hotplug.
+               This is also required for suspend/hibernation on SMP systems.
+
+               Say N if you want to disable CPU hotplug and don't need to
+               suspend.
 
 config ARCH_ENABLE_MEMORY_HOTPLUG
        def_bool y
index bc11b32..7377ccb 100644 (file)
@@ -39,10 +39,10 @@ int cache_k8_northbridges(void)
 {
        int i;
        struct pci_dev *dev;
+
        if (num_k8_northbridges)
                return 0;
 
-       num_k8_northbridges = 0;
        dev = NULL;
        while ((dev = next_k8_northbridge(dev)) != NULL)
                num_k8_northbridges++;
@@ -52,6 +52,11 @@ int cache_k8_northbridges(void)
        if (!k8_northbridges)
                return -ENOMEM;
 
+       if (!num_k8_northbridges) {
+               k8_northbridges[0] = NULL;
+               return 0;
+       }
+
        flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
        if (!flush_words) {
                kfree(k8_northbridges);
index 93a2cf6..863a8c0 100644 (file)
@@ -423,7 +423,10 @@ static ssize_t disk_size_read(struct gendisk * disk, char *page)
 {
        return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
 }
-
+static ssize_t disk_capability_read(struct gendisk *disk, char *page)
+{
+       return sprintf(page, "%x\n", disk->flags);
+}
 static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
        preempt_disable();
@@ -466,6 +469,10 @@ static struct disk_attribute disk_attr_size = {
        .attr = {.name = "size", .mode = S_IRUGO },
        .show   = disk_size_read
 };
+static struct disk_attribute disk_attr_capability = {
+       .attr = {.name = "capability", .mode = S_IRUGO },
+       .show   = disk_capability_read
+};
 static struct disk_attribute disk_attr_stat = {
        .attr = {.name = "stat", .mode = S_IRUGO },
        .show   = disk_stats_read
@@ -506,6 +513,7 @@ static struct attribute * default_attrs[] = {
        &disk_attr_removable.attr,
        &disk_attr_size.attr,
        &disk_attr_stat.attr,
+       &disk_attr_capability.attr,
 #ifdef CONFIG_FAIL_MAKE_REQUEST
        &disk_attr_fail.attr,
 #endif
@@ -688,6 +696,27 @@ struct seq_operations diskstats_op = {
        .show   = diskstats_show
 };
 
+static void media_change_notify_thread(struct work_struct *work)
+{
+       struct gendisk *gd = container_of(work, struct gendisk, async_notify);
+       char event[] = "MEDIA_CHANGE=1";
+       char *envp[] = { event, NULL };
+
+       /*
+        * set enviroment vars to indicate which event this is for
+        * so that user space will know to go check the media status.
+        */
+       kobject_uevent_env(&gd->kobj, KOBJ_CHANGE, envp);
+       put_device(gd->driverfs_dev);
+}
+
+void genhd_media_change_notify(struct gendisk *disk)
+{
+       get_device(disk->driverfs_dev);
+       schedule_work(&disk->async_notify);
+}
+EXPORT_SYMBOL_GPL(genhd_media_change_notify);
+
 struct gendisk *alloc_disk(int minors)
 {
        return alloc_disk_node(minors, -1);
@@ -717,6 +746,8 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
                kobj_set_kset_s(disk,block_subsys);
                kobject_init(&disk->kobj);
                rand_initialize_disk(disk);
+               INIT_WORK(&disk->async_notify,
+                       media_change_notify_thread);
        }
        return disk;
 }
index 3587cb4..fe08804 100644 (file)
@@ -670,7 +670,7 @@ static void __reschedule_timeout(int drive, const char *message, int marg)
        if (drive == current_reqD)
                drive = current_drive;
        del_timer(&fd_timeout);
-       if (drive < 0 || drive > N_DRIVE) {
+       if (drive < 0 || drive >= N_DRIVE) {
                fd_timeout.expires = jiffies + 20UL * HZ;
                drive = 0;
        } else
index c72ee97..ca376b9 100644 (file)
@@ -1061,6 +1061,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
 
                                if (data & info->ignore_status_mask) {
                                        info->icount.rx++;
+                                       spin_unlock(&cinfo->card_lock);
                                        return;
                                }
                                if (tty_buffer_request_room(tty, 1)) {
index 6d3840e..6a86958 100644 (file)
@@ -102,10 +102,15 @@ geode_aes_crypt(struct geode_aes_op *op)
        u32 flags = 0;
        unsigned long iflags;
 
-       if (op->len == 0 || op->src == op->dst)
+       if (op->len == 0)
                return 0;
 
-       if (op->flags & AES_FLAGS_COHERENT)
+       /* If the source and destination is the same, then
+        * we need to turn on the coherent flags, otherwise
+        * we don't need to worry
+        */
+
+       if (op->src == op->dst)
                flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
 
        if (op->dir == AES_DIR_ENCRYPT)
@@ -120,7 +125,7 @@ geode_aes_crypt(struct geode_aes_op *op)
                _writefield(AES_WRITEIV0_REG, op->iv);
        }
 
-       if (op->flags & AES_FLAGS_USRKEY) {
+       if (!(op->flags & AES_FLAGS_HIDDENKEY)) {
                flags |= AES_CTRL_WRKEY;
                _writefield(AES_WRITEKEY0_REG, op->key);
        }
@@ -289,6 +294,7 @@ static struct crypto_alg geode_cbc_alg = {
                        .setkey                 =       geode_setkey,
                        .encrypt                =       geode_cbc_encrypt,
                        .decrypt                =       geode_cbc_decrypt,
+                       .ivsize                 =       AES_IV_LENGTH,
                }
        }
 };
index 8003a36..f479686 100644 (file)
@@ -20,8 +20,7 @@
 #define AES_DIR_DECRYPT 0
 #define AES_DIR_ENCRYPT 1
 
-#define AES_FLAGS_USRKEY   (1 << 0)
-#define AES_FLAGS_COHERENT (1 << 1)
+#define AES_FLAGS_HIDDENKEY (1 << 0)
 
 struct geode_aes_op {
 
index 0c16067..366f4a1 100644 (file)
@@ -491,6 +491,12 @@ out:
 
 /* Sysfs Files */
 
+static ssize_t applesmc_name_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "applesmc\n");
+}
+
 static ssize_t applesmc_position_show(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
@@ -913,6 +919,8 @@ static struct led_classdev applesmc_backlight = {
        .brightness_set         = applesmc_brightness_set,
 };
 
+static DEVICE_ATTR(name, 0444, applesmc_name_show, NULL);
+
 static DEVICE_ATTR(position, 0444, applesmc_position_show, NULL);
 static DEVICE_ATTR(calibrate, 0644,
                        applesmc_calibrate_show, applesmc_calibrate_store);
@@ -1197,6 +1205,8 @@ static int __init applesmc_init(void)
                goto out_driver;
        }
 
+       ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr);
+
        /* Create key enumeration sysfs files */
        ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group);
        if (ret)
index ff284ae..82edc1c 100644 (file)
@@ -189,21 +189,21 @@ void *TransmitBufferSet(APPL * appl, dword ref)
 {
        appl->xbuffer_used[ref] = true;
        DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
-           return (void *) ref;
+           return (void *)(long)ref;
 }
 
 void *TransmitBufferGet(APPL * appl, void *p)
 {
-       if (appl->xbuffer_internal[(dword) p])
-               return appl->xbuffer_internal[(dword) p];
+       if (appl->xbuffer_internal[(dword)(long)p])
+               return appl->xbuffer_internal[(dword)(long)p];
 
-       return appl->xbuffer_ptr[(dword) p];
+       return appl->xbuffer_ptr[(dword)(long)p];
 }
 
 void TransmitBufferFree(APPL * appl, void *p)
 {
-       appl->xbuffer_used[(dword) p] = false;
-       DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword) p) + 1))
+       appl->xbuffer_used[(dword)(long)p] = false;
+       DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword)(long)p) + 1))
 }
 
 void *ReceiveBufferGet(APPL * appl, int Num)
@@ -301,7 +301,7 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...)
        /* if DATA_B3_IND, copy data too */
        if (command == _DATA_B3_I) {
                dword data = GET_DWORD(&msg.info.data_b3_ind.Data);
-               memcpy(write + length, (void *) data, dlength);
+               memcpy(write + length, (void *)(long)data, dlength);
        }
 
 #ifndef DIVA_NO_DEBUGLIB
@@ -318,7 +318,7 @@ void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...)
                        if (myDriverDebugHandle.dbgMask & DL_BLK) {
                                xlog("\x00\x02", &msg, 0x81, length);
                                for (i = 0; i < dlength; i += 256) {
-                                 DBG_BLK((((char *) GET_DWORD(&msg.info.data_b3_ind.Data)) + i,
+                                 DBG_BLK((((char *)(long)GET_DWORD(&msg.info.data_b3_ind.Data)) + i,
                                        ((dlength - i) < 256) ? (dlength - i) : 256))
                                  if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
                                          break; /* not more if not explicitely requested */
index 784232a..ccd35d0 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  *
   Copyright (c) Eicon Networks, 2002.
@@ -533,7 +532,7 @@ word api_put(APPL   * appl, CAPI_MSG   * msg)
         if (m->header.command == _DATA_B3_R)
         {
 
-          m->info.data_b3_req.Data = (dword)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
+          m->info.data_b3_req.Data = (dword)(long)(TransmitBufferSet (appl, m->info.data_b3_req.Data));
 
         }
 
@@ -1032,7 +1031,7 @@ static void plci_free_msg_in_queue (PLCI   *plci)
       {
 
         TransmitBufferFree (plci->appl,
-          (byte   *)(((CAPI_MSG   *)(&((byte   *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
+          (byte *)(long)(((CAPI_MSG *)(&((byte *)(plci->msg_in_queue))[i]))->info.data_b3_req.Data));
 
       }
 
@@ -3118,7 +3117,7 @@ byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci,
        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
       {
 
-        data->P = (byte   *)(*((dword   *)(parms[0].info)));
+        data->P = (byte *)(long)(*((dword *)(parms[0].info)));
 
       }
       else
@@ -3151,7 +3150,7 @@ byte data_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER   * a, PLCI   * plci,
        && (((byte   *)(parms[0].info)) < ((byte   *)(plci->msg_in_queue)) + sizeof(plci->msg_in_queue)))
       {
 
-        TransmitBufferFree (appl, (byte   *)(*((dword   *)(parms[0].info))));
+        TransmitBufferFree (appl, (byte *)(long)(*((dword *)(parms[0].info))));
 
       }
     }
@@ -4057,7 +4056,7 @@ capi_callback_suffix:
     {
       if (m->header.command == _DATA_B3_R)
 
-        TransmitBufferFree (appl, (byte   *)(m->info.data_b3_req.Data));
+        TransmitBufferFree (appl, (byte *)(long)(m->info.data_b3_req.Data));
 
       dbug(1,dprintf("Error 0x%04x from msg(0x%04x)", i, m->header.command));
       break;
@@ -7134,7 +7133,7 @@ void nl_ind(PLCI   * plci)
   case N_UDATA:
     if (!(udata_forwarding_table[plci->NL.RBuffer->P[0] >> 5] & (1L << (plci->NL.RBuffer->P[0] & 0x1f))))
     {
-      plci->RData[0].P = plci->internal_ind_buffer + (-((int)(plci->internal_ind_buffer)) & 3);
+      plci->RData[0].P = plci->internal_ind_buffer + (-((int)(long)(plci->internal_ind_buffer)) & 3);
       plci->RData[0].PLength = INTERNAL_IND_BUFFER_SIZE;
       plci->NL.R = plci->RData;
       plci->NL.RNum = 1;
index da4196f..8d53a7f 100644 (file)
@@ -1551,7 +1551,7 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[],
        if (retval == 0) { // yuck
                cards[i].typ = 0;
                nrcards--;
-               return retval;
+               return -EINVAL;
        }
        cs = cards[i].cs;
        hisax_d_if->cs = cs;
index 1f18f19..b1a26e0 100644 (file)
@@ -485,7 +485,6 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
 {
        int k;
 
-       spin_lock_init(&urb->lock);
        urb->dev = dev;
        urb->pipe = pipe;
        urb->complete = complete;
@@ -578,16 +577,14 @@ stop_isoc_chain(usb_fifo * fifo)
                            "HFC-S USB: Stopping iso chain for fifo %i.%i",
                            fifo->fifonum, i);
 #endif
-                       usb_unlink_urb(fifo->iso[i].purb);
+                       usb_kill_urb(fifo->iso[i].purb);
                        usb_free_urb(fifo->iso[i].purb);
                        fifo->iso[i].purb = NULL;
                }
        }
-       if (fifo->urb) {
-               usb_unlink_urb(fifo->urb);
-               usb_free_urb(fifo->urb);
-               fifo->urb = NULL;
-       }
+       usb_kill_urb(fifo->urb);
+       usb_free_urb(fifo->urb);
+       fifo->urb = NULL;
        fifo->active = 0;
 }
 
@@ -1305,7 +1302,11 @@ usb_init(hfcusb_data * hfc)
        }
        /* default Prot: EURO ISDN, should be a module_param */
        hfc->protocol = 2;
-       hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
+       i = hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
+       if (i) {
+               printk(KERN_INFO "HFC-S USB: hisax_register -> %d\n", i);
+               return i;
+       }
 
 #ifdef CONFIG_HISAX_DEBUG
        hfc_debug = debug;
@@ -1626,11 +1627,9 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 #endif
                        /* init the chip and register the driver */
                        if (usb_init(context)) {
-                               if (context->ctrl_urb) {
-                                       usb_unlink_urb(context->ctrl_urb);
-                                       usb_free_urb(context->ctrl_urb);
-                                       context->ctrl_urb = NULL;
-                               }
+                               usb_kill_urb(context->ctrl_urb);
+                               usb_free_urb(context->ctrl_urb);
+                               context->ctrl_urb = NULL;
                                kfree(context);
                                return (-EIO);
                        }
@@ -1682,21 +1681,15 @@ hfc_usb_disconnect(struct usb_interface
                                    i);
 #endif
                        }
-                       if (context->fifos[i].urb) {
-                               usb_unlink_urb(context->fifos[i].urb);
-                               usb_free_urb(context->fifos[i].urb);
-                               context->fifos[i].urb = NULL;
-                       }
+                       usb_kill_urb(context->fifos[i].urb);
+                       usb_free_urb(context->fifos[i].urb);
+                       context->fifos[i].urb = NULL;
                }
                context->fifos[i].active = 0;
        }
-       /* wait for all URBS to terminate */
-       mdelay(10);
-       if (context->ctrl_urb) {
-               usb_unlink_urb(context->ctrl_urb);
-               usb_free_urb(context->ctrl_urb);
-               context->ctrl_urb = NULL;
-       }
+       usb_kill_urb(context->ctrl_urb);
+       usb_free_urb(context->ctrl_urb);
+       context->ctrl_urb = NULL;
        hisax_unregister(&context->d_if);
        kfree(context);         /* free our structure again */
 }                              /* hfc_usb_disconnect */
index 9e088fc..7993e01 100644 (file)
@@ -859,7 +859,11 @@ new_adapter(void)
        for (i = 0; i < 2; i++)
                b_if[i] = &adapter->bcs[i].b_if;
 
-       hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp", protocol);
+       if (hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp",
+                       protocol) != 0) {
+               kfree(adapter);
+               adapter = NULL;
+       }
 
        return adapter;
 }
index bb3a28a..1375123 100644 (file)
@@ -107,12 +107,17 @@ static int probe_st5481(struct usb_interface *intf,
        for (i = 0; i < 2; i++)
                b_if[i] = &adapter->bcs[i].b_if;
 
-       hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol);
+       if (hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb",
+                       protocol) != 0)
+               goto err_b1;
+
        st5481_start(adapter);
 
        usb_set_intfdata(intf, adapter);
        return 0;
 
+ err_b1:
+       st5481_release_b(&adapter->bcs[1]);
  err_b:
        st5481_release_b(&adapter->bcs[0]);
  err_d:
index ff15951..4ada66b 100644 (file)
@@ -407,7 +407,6 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev,
 {
        int k;
 
-       spin_lock_init(&urb->lock);
        urb->dev=dev;
        urb->pipe=pipe;
        urb->interval = 1;
index 5a4a74c..9620d45 100644 (file)
@@ -255,19 +255,25 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
 
 }
 
-static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
        mdk_rdev_t *rdev;
        struct list_head *tmp;
+       mddev_t *mddev = bitmap->mddev;
 
        ITERATE_RDEV(mddev, rdev, tmp)
                if (test_bit(In_sync, &rdev->flags)
-                   && !test_bit(Faulty, &rdev->flags))
+                   && !test_bit(Faulty, &rdev->flags)) {
+                       int size = PAGE_SIZE;
+                       if (page->index == bitmap->file_pages-1)
+                               size = roundup(bitmap->last_page_size,
+                                              bdev_hardsect_size(rdev->bdev));
                        md_super_write(mddev, rdev,
-                                      (rdev->sb_offset<<1) + offset
+                                      (rdev->sb_offset<<1) + bitmap->offset
                                       + page->index * (PAGE_SIZE/512),
-                                      PAGE_SIZE,
+                                      size,
                                       page);
+               }
 
        if (wait)
                md_super_wait(mddev);
@@ -282,7 +288,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
        struct buffer_head *bh;
 
        if (bitmap->file == NULL)
-               return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+               return write_sb_page(bitmap, page, wait);
 
        bh = page_buffers(page);
 
@@ -923,6 +929,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
                        }
 
                        bitmap->filemap[bitmap->file_pages++] = page;
+                       bitmap->last_page_size = count;
                }
                paddr = kmap_atomic(page, KM_USER0);
                if (bitmap->flags & BITMAP_HOSTENDIAN)
index d5ecd2d..1927410 100644 (file)
@@ -139,8 +139,6 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
        if (!conf)
                return NULL;
 
-       mddev->private = conf;
-
        cnt = 0;
        conf->array_size = 0;
 
@@ -232,7 +230,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
         * First calculate the device offsets.
         */
        conf->disks[0].offset = 0;
-       for (i=1; i<mddev->raid_disks; i++)
+       for (i = 1; i < raid_disks; i++)
                conf->disks[i].offset =
                        conf->disks[i-1].offset +
                        conf->disks[i-1].size;
@@ -244,7 +242,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
             curr_offset < conf->array_size;
             curr_offset += conf->hash_spacing) {
 
-               while (i < mddev->raid_disks-1 &&
+               while (i < raid_disks-1 &&
                       curr_offset >= conf->disks[i+1].offset)
                        i++;
 
@@ -299,9 +297,11 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
         */
        linear_conf_t *newconf;
 
-       if (rdev->raid_disk != mddev->raid_disks)
+       if (rdev->saved_raid_disk != mddev->raid_disks)
                return -EINVAL;
 
+       rdev->raid_disk = rdev->saved_raid_disk;
+
        newconf = linear_conf(mddev,mddev->raid_disks+1);
 
        if (!newconf)
index c10ce91..1c54f3c 100644 (file)
@@ -1298,8 +1298,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
        ITERATE_RDEV(mddev,rdev2,tmp)
                if (rdev2->desc_nr+1 > max_dev)
                        max_dev = rdev2->desc_nr+1;
-       
-       sb->max_dev = cpu_to_le32(max_dev);
+
+       if (max_dev > le32_to_cpu(sb->max_dev))
+               sb->max_dev = cpu_to_le32(max_dev);
        for (i=0; i<max_dev;i++)
                sb->dev_roles[i] = cpu_to_le16(0xfffe);
        
@@ -1365,10 +1366,14 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
        }
        /* make sure rdev->size exceeds mddev->size */
        if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) {
-               if (mddev->pers)
-                       /* Cannot change size, so fail */
-                       return -ENOSPC;
-               else
+               if (mddev->pers) {
+                       /* Cannot change size, so fail
+                        * If mddev->level <= 0, then we don't care
+                        * about aligning sizes (e.g. linear)
+                        */
+                       if (mddev->level > 0)
+                               return -ENOSPC;
+               } else
                        mddev->size = rdev->size;
        }
 
@@ -2142,6 +2147,9 @@ static void analyze_sbs(mddev_t * mddev)
                        rdev->desc_nr = i++;
                        rdev->raid_disk = rdev->desc_nr;
                        set_bit(In_sync, &rdev->flags);
+               } else if (rdev->raid_disk >= mddev->raid_disks) {
+                       rdev->raid_disk = -1;
+                       clear_bit(In_sync, &rdev->flags);
                }
        }
 
index dfe3214..2c404f7 100644 (file)
@@ -415,7 +415,7 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
        raid0_conf_t *conf = mddev_to_conf(mddev);
        struct strip_zone *zone;
        mdk_rdev_t *tmp_dev;
-       unsigned long chunk;
+       sector_t chunk;
        sector_t block, rsect;
        const int rw = bio_data_dir(bio);
 
@@ -470,7 +470,6 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
 
                sector_div(x, zone->nb_dev);
                chunk = x;
-               BUG_ON(x != (sector_t)chunk);
 
                x = block >> chunksize_bits;
                tmp_dev = zone->dev[sector_div(x, zone->nb_dev)];
index d3235f2..e0d474b 100644 (file)
@@ -123,8 +123,12 @@ int i2o_driver_register(struct i2o_driver *drv)
        }
 
        rc = driver_register(&drv->driver);
-       if (rc)
-               destroy_workqueue(drv->event_queue);
+       if (rc) {
+               if (drv->event) {
+                       destroy_workqueue(drv->event_queue);
+                       drv->event_queue = NULL;
+               }
+       }
 
        return rc;
 };
@@ -256,7 +260,7 @@ void i2o_driver_notify_controller_add_all(struct i2o_controller *c)
        int i;
        struct i2o_driver *drv;
 
-       for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+       for (i = 0; i < i2o_max_drivers; i++) {
                drv = i2o_drivers[i];
 
                if (drv)
@@ -276,7 +280,7 @@ void i2o_driver_notify_controller_remove_all(struct i2o_controller *c)
        int i;
        struct i2o_driver *drv;
 
-       for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+       for (i = 0; i < i2o_max_drivers; i++) {
                drv = i2o_drivers[i];
 
                if (drv)
@@ -295,7 +299,7 @@ void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev)
        int i;
        struct i2o_driver *drv;
 
-       for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+       for (i = 0; i < i2o_max_drivers; i++) {
                drv = i2o_drivers[i];
 
                if (drv)
@@ -314,7 +318,7 @@ void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev)
        int i;
        struct i2o_driver *drv;
 
-       for (i = 0; i < I2O_MAX_DRIVERS; i++) {
+       for (i = 0; i < i2o_max_drivers; i++) {
                drv = i2o_drivers[i];
 
                if (drv)
@@ -335,17 +339,15 @@ int __init i2o_driver_init(void)
 
        spin_lock_init(&i2o_drivers_lock);
 
-       if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
-           ((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
-            (2 * i2o_max_drivers - 1))) {
-               osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and "
-                        "a power of 2\n", i2o_max_drivers);
+       if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) {
+               osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n",
+                        i2o_max_drivers);
                i2o_max_drivers = I2O_MAX_DRIVERS;
        }
        osm_info("max drivers = %d\n", i2o_max_drivers);
 
        i2o_drivers =
-           kzalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
+           kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL);
        if (!i2o_drivers)
                return -ENOMEM;
 
index 35b139b..5108b7c 100644 (file)
@@ -47,6 +47,7 @@ struct phantom_device {
        struct cdev cdev;
 
        struct mutex open_lock;
+       spinlock_t ioctl_lock;
 };
 
 static unsigned char phantom_devices[PHANTOM_MAX_MINORS];
@@ -59,8 +60,11 @@ static int phantom_status(struct phantom_device *dev, unsigned long newstat)
                atomic_set(&dev->counter, 0);
                iowrite32(PHN_CTL_IRQ, dev->iaddr + PHN_CONTROL);
                iowrite32(0x43, dev->caddr + PHN_IRQCTL);
-       } else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING))
+               ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
+       } else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING)) {
                iowrite32(0, dev->caddr + PHN_IRQCTL);
+               ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
+       }
 
        dev->status = newstat;
 
@@ -71,8 +75,8 @@ static int phantom_status(struct phantom_device *dev, unsigned long newstat)
  * File ops
  */
 
-static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd,
-       u_long arg)
+static long phantom_ioctl(struct file *file, unsigned int cmd,
+               unsigned long arg)
 {
        struct phantom_device *dev = file->private_data;
        struct phm_regs rs;
@@ -92,24 +96,32 @@ static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd,
                if (r.reg > 7)
                        return -EINVAL;
 
+               spin_lock(&dev->ioctl_lock);
                if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) &&
-                               phantom_status(dev, dev->status | PHB_RUNNING))
+                               phantom_status(dev, dev->status | PHB_RUNNING)){
+                       spin_unlock(&dev->ioctl_lock);
                        return -ENODEV;
+               }
 
                pr_debug("phantom: writing %x to %u\n", r.value, r.reg);
                iowrite32(r.value, dev->iaddr + r.reg);
+               ioread32(dev->iaddr); /* PCI posting */
 
                if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ))
                        phantom_status(dev, dev->status & ~PHB_RUNNING);
+               spin_unlock(&dev->ioctl_lock);
                break;
        case PHN_SET_REGS:
                if (copy_from_user(&rs, argp, sizeof(rs)))
                        return -EFAULT;
 
                pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask);
+               spin_lock(&dev->ioctl_lock);
                for (i = 0; i < min(rs.count, 8U); i++)
                        if ((1 << i) & rs.mask)
                                iowrite32(rs.values[i], dev->oaddr + i);
+               ioread32(dev->iaddr); /* PCI posting */
+               spin_unlock(&dev->ioctl_lock);
                break;
        case PHN_GET_REG:
                if (copy_from_user(&r, argp, sizeof(r)))
@@ -128,9 +140,11 @@ static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd,
                        return -EFAULT;
 
                pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask);
+               spin_lock(&dev->ioctl_lock);
                for (i = 0; i < min(rs.count, 8U); i++)
                        if ((1 << i) & rs.mask)
                                rs.values[i] = ioread32(dev->iaddr + i);
+               spin_unlock(&dev->ioctl_lock);
 
                if (copy_to_user(argp, &rs, sizeof(rs)))
                        return -EFAULT;
@@ -199,7 +213,7 @@ static unsigned int phantom_poll(struct file *file, poll_table *wait)
 static struct file_operations phantom_file_ops = {
        .open = phantom_open,
        .release = phantom_release,
-       .ioctl = phantom_ioctl,
+       .unlocked_ioctl = phantom_ioctl,
        .poll = phantom_poll,
 };
 
@@ -212,6 +226,7 @@ static irqreturn_t phantom_isr(int irq, void *data)
 
        iowrite32(0, dev->iaddr);
        iowrite32(0xc0, dev->iaddr);
+       ioread32(dev->iaddr); /* PCI posting */
 
        atomic_inc(&dev->counter);
        wake_up_interruptible(&dev->wait);
@@ -282,11 +297,13 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
        }
 
        mutex_init(&pht->open_lock);
+       spin_lock_init(&pht->ioctl_lock);
        init_waitqueue_head(&pht->wait);
        cdev_init(&pht->cdev, &phantom_file_ops);
        pht->cdev.owner = THIS_MODULE;
 
        iowrite32(0, pht->caddr + PHN_IRQCTL);
+       ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
        retval = request_irq(pdev->irq, phantom_isr,
                        IRQF_SHARED | IRQF_DISABLED, "phantom", pht);
        if (retval) {
@@ -337,6 +354,7 @@ static void __devexit phantom_remove(struct pci_dev *pdev)
        cdev_del(&pht->cdev);
 
        iowrite32(0, pht->caddr + PHN_IRQCTL);
+       ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
        free_irq(pdev->irq, pht);
 
        pci_iounmap(pdev, pht->oaddr);
@@ -358,6 +376,7 @@ static int phantom_suspend(struct pci_dev *pdev, pm_message_t state)
        struct phantom_device *dev = pci_get_drvdata(pdev);
 
        iowrite32(0, dev->caddr + PHN_IRQCTL);
+       ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
 
        return 0;
 }
index a7562f7..540ff4b 100644 (file)
@@ -135,23 +135,6 @@ struct mmc_blk_request {
        struct mmc_data         data;
 };
 
-static int mmc_blk_prep_rq(struct mmc_queue *mq, struct request *req)
-{
-       struct mmc_blk_data *md = mq->data;
-       int stat = BLKPREP_OK;
-
-       /*
-        * If we have no device, we haven't finished initialising.
-        */
-       if (!md || !mq->card) {
-               printk(KERN_ERR "%s: killing request - no device/host\n",
-                      req->rq_disk->disk_name);
-               stat = BLKPREP_KILL;
-       }
-
-       return stat;
-}
-
 static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
 {
        int err;
@@ -460,7 +443,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
        if (ret)
                goto err_putdisk;
 
-       md->queue.prep_fn = mmc_blk_prep_rq;
        md->queue.issue_fn = mmc_blk_issue_rq;
        md->queue.data = md;
 
index 2e77963..dd97bc7 100644 (file)
 #define MMC_QUEUE_SUSPENDED    (1 << 0)
 
 /*
- * Prepare a MMC request.  Essentially, this means passing the
- * preparation off to the media driver.  The media driver will
- * create a mmc_io_request in req->special.
+ * Prepare a MMC request. This just filters out odd stuff.
  */
 static int mmc_prep_request(struct request_queue *q, struct request *req)
 {
-       struct mmc_queue *mq = q->queuedata;
-       int ret = BLKPREP_KILL;
-
-       if (blk_special_request(req)) {
-               /*
-                * Special commands already have the command
-                * blocks already setup in req->special.
-                */
-               BUG_ON(!req->special);
-
-               ret = BLKPREP_OK;
-       } else if (blk_fs_request(req) || blk_pc_request(req)) {
-               /*
-                * Block I/O requests need translating according
-                * to the protocol.
-                */
-               ret = mq->prep_fn(mq, req);
-       } else {
-               /*
-                * Everything else is invalid.
-                */
+       /*
+        * We only like normal block requests.
+        */
+       if (!blk_fs_request(req) && !blk_pc_request(req)) {
                blk_dump_rq_flags(req, "MMC bad request");
+               return BLKPREP_KILL;
        }
 
-       if (ret == BLKPREP_OK)
-               req->cmd_flags |= REQ_DONTPREP;
+       req->cmd_flags |= REQ_DONTPREP;
 
-       return ret;
+       return BLKPREP_OK;
 }
 
 static int mmc_queue_thread(void *d)
index c9f139e..1590b3f 100644 (file)
@@ -10,20 +10,12 @@ struct mmc_queue {
        struct semaphore        thread_sem;
        unsigned int            flags;
        struct request          *req;
-       int                     (*prep_fn)(struct mmc_queue *, struct request *);
        int                     (*issue_fn)(struct mmc_queue *, struct request *);
        void                    *data;
        struct request_queue    *queue;
        struct scatterlist      *sg;
 };
 
-struct mmc_io_request {
-       struct request          *rq;
-       int                     num;
-       struct mmc_command      selcmd;         /* mmc_queue private */
-       struct mmc_command      cmd[4];         /* max 4 commands */
-};
-
 extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
 extern void mmc_cleanup_queue(struct mmc_queue *);
 extern void mmc_queue_suspend(struct mmc_queue *);
index 052359f..11f36be 100644 (file)
@@ -329,8 +329,8 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
        int ret = 0;
 
 #if defined(CONFIG_PPC_MERGE)
-       cdm = mpc52xx_find_and_map("mpc52xx-cdm");
-       gpio = mpc52xx_find_and_map("mpc52xx-gpio");
+       cdm = mpc52xx_find_and_map("mpc5200-cdm");
+       gpio = mpc52xx_find_and_map("mpc5200-gpio");
 #else
        cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
        gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
@@ -445,9 +445,6 @@ static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
        struct spi_master *master;
        int ret;
 
-       if (pdata == NULL)
-               return -ENODEV;
-
        master = spi_alloc_master(dev, sizeof *mps);
        if (master == NULL)
                return -ENOMEM;
@@ -594,17 +591,17 @@ static int __init mpc52xx_psc_spi_of_probe(struct of_device *op,
        }
        regaddr64 = of_translate_address(op->node, regaddr_p);
 
+       /* get PSC id (1..6, used by port_config) */
        if (op->dev.platform_data == NULL) {
-               struct device_node *np;
-               int i = 0;
+               const u32 *psc_nump;
 
-               for_each_node_by_type(np, "spi") {
-                       if (of_find_device_by_node(np) == op) {
-                               id = i;
-                               break;
-                       }
-                       i++;
+               psc_nump = of_get_property(op->node, "cell-index", NULL);
+               if (!psc_nump || *psc_nump > 5) {
+                       printk(KERN_ERR "mpc52xx_psc_spi: Device node %s has invalid "
+                                       "cell-index property\n", op->node->full_name);
+                       return -EINVAL;
                }
+               id = *psc_nump + 1;
        }
 
        return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
@@ -617,7 +614,7 @@ static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op)
 }
 
 static struct of_device_id mpc52xx_psc_spi_of_match[] = {
-       { .type = "spi", .compatible = "mpc52xx-psc-spi", },
+       { .type = "spi", .compatible = "mpc5200-psc-spi", },
        {},
 };
 
index 96f62b2..95183e1 100644 (file)
@@ -358,11 +358,11 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
        switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
        case SPI_MODE_0:
        case SPI_MODE_3:
-               flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
+               flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
                break;
        case SPI_MODE_1:
        case SPI_MODE_2:
-               flags |= UWIRE_WRITE_FALLING_EDGE | UWIRE_READ_RISING_EDGE;
+               flags |= UWIRE_WRITE_RISING_EDGE | UWIRE_READ_FALLING_EDGE;
                break;
        }
 
index 225d6b2..d04242a 100644 (file)
@@ -168,6 +168,12 @@ static int spidev_message(struct spidev_data *spidev,
                        n--, k_tmp++, u_tmp++) {
                k_tmp->len = u_tmp->len;
 
+               total += k_tmp->len;
+               if (total > bufsiz) {
+                       status = -EMSGSIZE;
+                       goto done;
+               }
+
                if (u_tmp->rx_buf) {
                        k_tmp->rx_buf = buf;
                        if (!access_ok(VERIFY_WRITE, u_tmp->rx_buf, u_tmp->len))
@@ -179,12 +185,6 @@ static int spidev_message(struct spidev_data *spidev,
                                        u_tmp->len))
                                goto done;
                }
-
-               total += k_tmp->len;
-               if (total > bufsiz) {
-                       status = -EMSGSIZE;
-                       goto done;
-               }
                buf += k_tmp->len;
 
                k_tmp->cs_change = !!u_tmp->cs_change;
@@ -364,6 +364,7 @@ spidev_ioctl(struct inode *inode, struct file *filp,
                        break;
                }
                if (__copy_from_user(ioc, (void __user *)arg, tmp)) {
+                       kfree(ioc);
                        retval = -EFAULT;
                        break;
                }
index a524805..c7a7c59 100644 (file)
@@ -193,6 +193,19 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
        out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004);
        out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
 
+#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+       /*
+        * Turn on cache snooping hardware, since some PowerPC platforms
+        * wholly rely on hardware to deal with cache coherent
+        */
+
+       /* Setup Snooping for all the 4GB space */
+       /* SNOOP1 starts from 0x0, size 2G */
+       out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB);
+       /* SNOOP2 starts from 0x80000000, size 2G */
+       out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
+#endif
+
        if (pdata->operating_mode == FSL_USB2_DR_HOST)
                mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
 
index f28736a..b5e59db 100644 (file)
@@ -34,4 +34,5 @@
 #define FSL_SOC_USB_PRICTRL    0x40c   /* NOTE: big-endian */
 #define FSL_SOC_USB_SICTRL     0x410   /* NOTE: big-endian */
 #define FSL_SOC_USB_CTRL       0x500   /* NOTE: big-endian */
+#define SNOOP_SIZE_2GB         0x1e
 #endif                         /* _EHCI_FSL_H */
index 4d7485f..6e1f1ea 100644 (file)
@@ -704,6 +704,91 @@ config FB_CG6
          This is the frame buffer device driver for the CGsix (GX, TurboGX)
          frame buffer.
 
+config FB_FFB
+       bool "Creator/Creator3D/Elite3D support"
+       depends on FB_SBUS && SPARC64
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the frame buffer device driver for the Creator, Creator3D,
+         and Elite3D graphics boards.
+
+config FB_TCX
+       bool "TCX (SS4/SS5 only) support"
+       depends on FB_SBUS
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the frame buffer device driver for the TCX 24/8bit frame
+         buffer.
+
+config FB_CG14
+       bool "CGfourteen (SX) support"
+       depends on FB_SBUS
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the frame buffer device driver for the CGfourteen frame
+         buffer on Desktop SPARCsystems with the SX graphics option.
+
+config FB_P9100
+       bool "P9100 (Sparcbook 3 only) support"
+       depends on FB_SBUS
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the frame buffer device driver for the P9100 card
+         supported on Sparcbook 3 machines.
+
+config FB_LEO
+       bool "Leo (ZX) support"
+       depends on FB_SBUS
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the frame buffer device driver for the SBUS-based Sun ZX
+         (leo) frame buffer cards.
+
+config FB_IGA
+       bool "IGA 168x display support"
+       depends on FB && SPARC32
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the framebuffer device for the INTERGRAPHICS 1680 and
+         successor frame buffer cards.
+
+config FB_XVR500
+       bool "Sun XVR-500 3DLABS Wildcat support"
+       depends on FB && PCI && SPARC64
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the framebuffer device for the Sun XVR-500 and similar
+         graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+         only works on sparc64 systems where the system firwmare has
+         mostly initialized the card already.  It is treated as a
+         completely dumb framebuffer device.
+
+config FB_XVR2500
+       bool "Sun XVR-2500 3DLABS Wildcat support"
+       depends on FB && PCI && SPARC64
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       help
+         This is the framebuffer device for the Sun XVR-2500 and similar
+         graphics cards based upon the 3DLABS Wildcat chipset.  The driver
+         only works on sparc64 systems where the system firwmare has
+         mostly initialized the card already.  It is treated as a
+         completely dumb framebuffer device.
+
 config FB_PVR2
        tristate "NEC PowerVR 2 display support"
        depends on FB && SH_DREAMCAST
@@ -1195,7 +1280,7 @@ config FB_ATY
 config FB_ATY_CT
        bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support"
        depends on PCI && FB_ATY
-       default y if SPARC64 && FB_PCI
+       default y if SPARC64 && PCI
        help
          Say Y here to support use of ATI's 64-bit Rage boards (or other
          boards based on the Mach64 CT, VT, GT, and LT chipsets) as a
@@ -1484,95 +1569,6 @@ config FB_AU1200
 
 source "drivers/video/geode/Kconfig"
 
-config FB_FFB
-       bool "Creator/Creator3D/Elite3D support"
-       depends on FB_SBUS && SPARC64
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the frame buffer device driver for the Creator, Creator3D,
-         and Elite3D graphics boards.
-
-config FB_TCX
-       bool "TCX (SS4/SS5 only) support"
-       depends on FB_SBUS
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the frame buffer device driver for the TCX 24/8bit frame
-         buffer.
-
-config FB_CG14
-       bool "CGfourteen (SX) support"
-       depends on FB_SBUS
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the frame buffer device driver for the CGfourteen frame
-         buffer on Desktop SPARCsystems with the SX graphics option.
-
-config FB_P9100
-       bool "P9100 (Sparcbook 3 only) support"
-       depends on FB_SBUS
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the frame buffer device driver for the P9100 card
-         supported on Sparcbook 3 machines.
-
-config FB_LEO
-       bool "Leo (ZX) support"
-       depends on FB_SBUS
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the frame buffer device driver for the SBUS-based Sun ZX
-         (leo) frame buffer cards.
-
-config FB_XVR500
-       bool "Sun XVR-500 3DLABS Wildcat support"
-       depends on (FB = y) && PCI && SPARC64
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the framebuffer device for the Sun XVR-500 and similar
-         graphics cards based upon the 3DLABS Wildcat chipset.  The driver
-         only works on sparc64 systems where the system firwmare has
-         mostly initialized the card already.  It is treated as a
-         completely dumb framebuffer device.
-
-config FB_XVR2500
-       bool "Sun XVR-2500 3DLABS Wildcat support"
-       depends on (FB = y) && PCI && SPARC64
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the framebuffer device for the Sun XVR-2500 and similar
-         graphics cards based upon the 3DLABS Wildcat chipset.  The driver
-         only works on sparc64 systems where the system firwmare has
-         mostly initialized the card already.  It is treated as a
-         completely dumb framebuffer device.
-
-config FB_PCI
-       bool "PCI framebuffers"
-       depends on (FB = y) && PCI && SPARC
-
-config FB_IGA
-       bool "IGA 168x display support"
-       depends on SPARC32 && FB_PCI
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       help
-         This is the framebuffer device for the INTERGRAPHICS 1680 and
-         successor frame buffer cards.
-
 config FB_HIT
        tristate "HD64461 Frame Buffer support"
        depends on FB && HD64461
@@ -1796,9 +1792,10 @@ config FB_IBM_GXT4500
 config FB_PS3
        bool "PS3 GPU framebuffer driver"
        depends on (FB = y) && PS3_PS3AV
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
+       select FB_SYS_FILLRECT
+       select FB_SYS_COPYAREA
+       select FB_SYS_IMAGEBLIT
+       select FB_SYS_FOPS
        ---help---
          Include support for the virtual frame buffer in the PS3 platform.
 
index 267c1ff..a125898 100644 (file)
@@ -394,26 +394,18 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi)
 
        /* initialize GPIOs */
        imx_gpio_mode(PD6_PF_LSCLK);
-       imx_gpio_mode(PD10_PF_SPL_SPR);
        imx_gpio_mode(PD11_PF_CONTRAST);
        imx_gpio_mode(PD14_PF_FLM_VSYNC);
        imx_gpio_mode(PD13_PF_LP_HSYNC);
-       imx_gpio_mode(PD7_PF_REV);
-       imx_gpio_mode(PD8_PF_CLS);
-
-#ifndef CONFIG_MACH_PIMX1
-       /* on PiMX1 used as buffers enable signal
-        */
-       imx_gpio_mode(PD9_PF_PS);
-#endif
-
-#ifndef CONFIG_MACH_MX1FS2
-       /* on mx1fs2 this pin is used to (de)activate the display, so we need
-        * it as a normal gpio
-        */
        imx_gpio_mode(PD12_PF_ACD_OE);
-#endif
 
+       /* These are only needed for Sharp HR TFT displays */
+       if (fbi->pcr & PCR_SHARP) {
+               imx_gpio_mode(PD7_PF_REV);
+               imx_gpio_mode(PD8_PF_CLS);
+               imx_gpio_mode(PD9_PF_PS);
+               imx_gpio_mode(PD10_PF_SPL_SPR);
+       }
 }
 
 #ifdef CONFIG_PM
@@ -476,7 +468,6 @@ static int __init imxfb_init_fbinfo(struct device *dev)
 
        info->fbops                     = &imxfb_ops;
        info->flags                     = FBINFO_FLAG_DEFAULT;
-       info->pseudo_palette            = (fbi + 1);
 
        fbi->rgb[RGB_16]                = &def_rgb_16;
        fbi->rgb[RGB_8]                 = &def_rgb_8;
@@ -499,6 +490,7 @@ static int __init imxfb_init_fbinfo(struct device *dev)
        info->var.sync                  = inf->sync;
        info->var.grayscale             = inf->cmap_greyscale;
        fbi->cmap_inverse               = inf->cmap_inverse;
+       fbi->cmap_static                = inf->cmap_static;
        fbi->pcr                        = inf->pcr;
        fbi->lscr1                      = inf->lscr1;
        fbi->dmacr                      = inf->dmacr;
index ab5e668..0a04483 100644 (file)
@@ -183,15 +183,17 @@ static inline void pm2_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
                index = PM2VR_RD_INDEXED_DATA;
                break;
        }       
-       mb();
+       wmb();
        pm2_WR(p, index, v);
+       wmb();
 }
 
 static inline void pm2v_RDAC_WR(struct pm2fb_par* p, s32 idx, u32 v)
 {
        pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
-       mb();
+       wmb();
        pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
+       wmb();
 }
 
 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
@@ -466,11 +468,9 @@ static void set_memclock(struct pm2fb_par* par, u32 clk)
                WAIT_FIFO(par, 8);
                pm2_WR(par, PM2VR_RD_INDEX_HIGH, PM2VI_RD_MCLK_CONTROL >> 8);
                pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 0);
-               wmb();
                pm2v_RDAC_WR(par, PM2VI_RD_MCLK_PRESCALE, m);
                pm2v_RDAC_WR(par, PM2VI_RD_MCLK_FEEDBACK, n);
                pm2v_RDAC_WR(par, PM2VI_RD_MCLK_POSTSCALE, p);
-               wmb();
                pm2v_RDAC_WR(par, PM2VI_RD_MCLK_CONTROL, 1);
                rmb();
                for (i = 256;
@@ -483,12 +483,9 @@ static void set_memclock(struct pm2fb_par* par, u32 clk)
                pm2_mnp(clk, &m, &n, &p);
                WAIT_FIFO(par, 10);
                pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 6);
-               wmb();
                pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_1, m);
                pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_2, n);
-               wmb();
                pm2_RDAC_WR(par, PM2I_RD_MEMORY_CLOCK_3, 8|p);
-               wmb();
                pm2_RDAC_RD(par, PM2I_RD_MEMORY_CLOCK_STATUS);
                rmb();
                for (i = 256;
@@ -509,12 +506,9 @@ static void set_pixclock(struct pm2fb_par* par, u32 clk)
                pm2_mnp(clk, &m, &n, &p);
                WAIT_FIFO(par, 8);
                pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 0);
-               wmb();
                pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A1, m);
                pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A2, n);
-               wmb();
                pm2_RDAC_WR(par, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
-               wmb();
                pm2_RDAC_RD(par, PM2I_RD_PIXEL_CLOCK_STATUS);
                rmb();
                for (i = 256;
@@ -1066,10 +1060,9 @@ static void pm2fb_block_op(struct fb_info* info, int copy,
 
        if (!w || !h)
                return;
-       WAIT_FIFO(par, 6);
+       WAIT_FIFO(par, 5);
        pm2_WR(par, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE |
                PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
-       pm2_WR(par, PM2R_FB_PIXEL_OFFSET, 0);
        if (copy)
                pm2_WR(par, PM2R_FB_SOURCE_DELTA,
                        ((ysrc-y) & 0xfff) << 16 | ((xsrc-x) & 0xfff));
index c77a1a1..616a0c0 100644 (file)
 static char *mode_option __devinitdata;
 
 /*
- *  If your driver supports multiple boards, you should make the
- *  below data types arrays, or allocate them dynamically (using kmalloc()).
- */
-
-/*
  * This structure defines the hardware state of the graphics card. Normally
  * you place this in a header file in linux/include/video. This file usually
  * also includes register information. That allows other driver subsystems
@@ -67,7 +62,7 @@ struct pm3_par {
        unsigned char   __iomem *v_regs;/* virtual address of p_regs */
        u32             video;          /* video flags before blanking */
        u32             base;           /* screen base (xoffset+yoffset) in 128 bits unit */
-       u32             palette[16];
+       u32             palette[16];
 };
 
 /*
@@ -104,36 +99,28 @@ static inline void PM3_WAIT(struct pm3_par *par, u32 n)
        while (PM3_READ_REG(par, PM3InFIFOSpace) < n);
 }
 
-static inline void PM3_SLOW_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
-{
-       if (par->v_regs) {
-               mb();
-               PM3_WAIT(par, 1);
-               wmb();
-               PM3_WRITE_REG(par, off, v);
-       }
-}
-
-static inline void PM3_SET_INDEX(struct pm3_par *par, unsigned index)
-{
-       PM3_SLOW_WRITE_REG(par, PM3RD_IndexHigh, (index >> 8) & 0xff);
-       PM3_SLOW_WRITE_REG(par, PM3RD_IndexLow, index & 0xff);
-}
-
 static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
 {
-       PM3_SET_INDEX(par, r);
+       PM3_WAIT(par, 3);
+       PM3_WRITE_REG(par, PM3RD_IndexHigh, (r >> 8) & 0xff);
+       PM3_WRITE_REG(par, PM3RD_IndexLow, r & 0xff);
        wmb();
        PM3_WRITE_REG(par, PM3RD_IndexedData, v);
+       wmb();
 }
 
 static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
                        unsigned char r, unsigned char g, unsigned char b)
 {
-       PM3_SLOW_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
-       PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, r);
-       PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, g);
-       PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, b);
+       PM3_WAIT(par, 4);
+       PM3_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
+       wmb();
+       PM3_WRITE_REG(par, PM3RD_PaletteData, r);
+       wmb();
+       PM3_WRITE_REG(par, PM3RD_PaletteData, g);
+       wmb();
+       PM3_WRITE_REG(par, PM3RD_PaletteData, b);
+       wmb();
 }
 
 static void pm3fb_clear_colormap(struct pm3_par *par,
@@ -141,7 +128,7 @@ static void pm3fb_clear_colormap(struct pm3_par *par,
 {
        int i;
 
-       for (i = 0; i < 256 ; i++) /* fill color map with white */
+       for (i = 0; i < 256 ; i++)
                pm3fb_set_color(par, i, r, g, b);
 
 }
@@ -175,19 +162,26 @@ static void pm3fb_calculate_clock(unsigned long reqclock,
        }
 }
 
-static inline int pm3fb_shift_bpp(unsigned long depth, int v)
+static inline int pm3fb_depth(const struct fb_var_screeninfo *var)
 {
-       switch (depth) {
+       if ( var->bits_per_pixel == 16 )
+               return var->red.length + var->green.length
+                       + var->blue.length;
+
+       return var->bits_per_pixel;
+}
+
+static inline int pm3fb_shift_bpp(unsigned bpp, int v)
+{
+       switch (bpp) {
        case 8:
                return (v >> 4);
-       case 12:
-       case 15:
        case 16:
                return (v >> 3);
        case 32:
                return (v >> 2);
        }
-       DPRINTK("Unsupported depth %ld\n", depth);
+       DPRINTK("Unsupported depth %u\n", bpp);
        return 0;
 }
 
@@ -206,56 +200,50 @@ static void pm3fb_write_mode(struct fb_info *info)
        const u32 vbend = vsend + info->var.upper_margin;
        const u32 vtotal = info->var.yres + vbend;
        const u32 width = (info->var.xres_virtual + 7) & ~7;
-
-       PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
-       PM3_SLOW_WRITE_REG(par, PM3Aperture0, 0x00000000);
-       PM3_SLOW_WRITE_REG(par, PM3Aperture1, 0x00000000);
-       PM3_SLOW_WRITE_REG(par, PM3FIFODis, 0x00000007);
-
-       PM3_SLOW_WRITE_REG(par, PM3HTotal,
-                          pm3fb_shift_bpp(info->var.bits_per_pixel,
-                                         htotal - 1));
-       PM3_SLOW_WRITE_REG(par, PM3HsEnd,
-                          pm3fb_shift_bpp(info->var.bits_per_pixel,
-                                         hsend));
-       PM3_SLOW_WRITE_REG(par, PM3HsStart,
-                          pm3fb_shift_bpp(info->var.bits_per_pixel,
-                                         hsstart));
-       PM3_SLOW_WRITE_REG(par, PM3HbEnd,
-                          pm3fb_shift_bpp(info->var.bits_per_pixel,
-                                         hbend));
-       PM3_SLOW_WRITE_REG(par, PM3HgEnd,
-                          pm3fb_shift_bpp(info->var.bits_per_pixel,
-                                         hbend));
-       PM3_SLOW_WRITE_REG(par, PM3ScreenStride,
-                          pm3fb_shift_bpp(info->var.bits_per_pixel,
-                                         width));
-       PM3_SLOW_WRITE_REG(par, PM3VTotal, vtotal - 1);
-       PM3_SLOW_WRITE_REG(par, PM3VsEnd, vsend - 1);
-       PM3_SLOW_WRITE_REG(par, PM3VsStart, vsstart - 1);
-       PM3_SLOW_WRITE_REG(par, PM3VbEnd, vbend);
-
-       switch (info->var.bits_per_pixel) {
+       const unsigned bpp = info->var.bits_per_pixel;
+
+       PM3_WAIT(par, 20);
+       PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
+       PM3_WRITE_REG(par, PM3Aperture0, 0x00000000);
+       PM3_WRITE_REG(par, PM3Aperture1, 0x00000000);
+       PM3_WRITE_REG(par, PM3FIFODis, 0x00000007);
+
+       PM3_WRITE_REG(par, PM3HTotal,
+                          pm3fb_shift_bpp(bpp, htotal - 1));
+       PM3_WRITE_REG(par, PM3HsEnd,
+                          pm3fb_shift_bpp(bpp, hsend));
+       PM3_WRITE_REG(par, PM3HsStart,
+                          pm3fb_shift_bpp(bpp, hsstart));
+       PM3_WRITE_REG(par, PM3HbEnd,
+                          pm3fb_shift_bpp(bpp, hbend));
+       PM3_WRITE_REG(par, PM3HgEnd,
+                          pm3fb_shift_bpp(bpp, hbend));
+       PM3_WRITE_REG(par, PM3ScreenStride,
+                          pm3fb_shift_bpp(bpp, width));
+       PM3_WRITE_REG(par, PM3VTotal, vtotal - 1);
+       PM3_WRITE_REG(par, PM3VsEnd, vsend - 1);
+       PM3_WRITE_REG(par, PM3VsStart, vsstart - 1);
+       PM3_WRITE_REG(par, PM3VbEnd, vbend);
+
+       switch (bpp) {
        case 8:
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+               PM3_WRITE_REG(par, PM3ByAperture1Mode,
                                   PM3ByApertureMode_PIXELSIZE_8BIT);
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+               PM3_WRITE_REG(par, PM3ByAperture2Mode,
                                   PM3ByApertureMode_PIXELSIZE_8BIT);
                break;
 
-       case 12:
-       case 15:
        case 16:
 #ifndef __BIG_ENDIAN
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+               PM3_WRITE_REG(par, PM3ByAperture1Mode,
                                   PM3ByApertureMode_PIXELSIZE_16BIT);
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+               PM3_WRITE_REG(par, PM3ByAperture2Mode,
                                   PM3ByApertureMode_PIXELSIZE_16BIT);
 #else
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+               PM3_WRITE_REG(par, PM3ByAperture1Mode,
                                   PM3ByApertureMode_PIXELSIZE_16BIT |
                                   PM3ByApertureMode_BYTESWAP_BADC);
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+               PM3_WRITE_REG(par, PM3ByAperture2Mode,
                                   PM3ByApertureMode_PIXELSIZE_16BIT |
                                   PM3ByApertureMode_BYTESWAP_BADC);
 #endif /* ! __BIG_ENDIAN */
@@ -263,23 +251,22 @@ static void pm3fb_write_mode(struct fb_info *info)
 
        case 32:
 #ifndef __BIG_ENDIAN
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+               PM3_WRITE_REG(par, PM3ByAperture1Mode,
                                   PM3ByApertureMode_PIXELSIZE_32BIT);
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+               PM3_WRITE_REG(par, PM3ByAperture2Mode,
                                   PM3ByApertureMode_PIXELSIZE_32BIT);
 #else
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
+               PM3_WRITE_REG(par, PM3ByAperture1Mode,
                                   PM3ByApertureMode_PIXELSIZE_32BIT |
                                   PM3ByApertureMode_BYTESWAP_DCBA);
-               PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
+               PM3_WRITE_REG(par, PM3ByAperture2Mode,
                                   PM3ByApertureMode_PIXELSIZE_32BIT |
                                   PM3ByApertureMode_BYTESWAP_DCBA);
 #endif /* ! __BIG_ENDIAN */
                break;
 
        default:
-               DPRINTK("Unsupported depth %d\n",
-                       info->var.bits_per_pixel);
+               DPRINTK("Unsupported depth %d\n", bpp);
                break;
        }
 
@@ -296,14 +283,15 @@ static void pm3fb_write_mode(struct fb_info *info)
                           PM3VideoControl_VSYNC_MASK);
                video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
                         PM3VideoControl_VSYNC_ACTIVE_HIGH;
-               PM3_SLOW_WRITE_REG(par, PM3VideoControl, video);
+               PM3_WRITE_REG(par, PM3VideoControl, video);
        }
-       PM3_SLOW_WRITE_REG(par, PM3VClkCtl,
+       PM3_WRITE_REG(par, PM3VClkCtl,
                           (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
-       PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
-       PM3_SLOW_WRITE_REG(par, PM3ChipConfig,
+       PM3_WRITE_REG(par, PM3ScreenBase, par->base);
+       PM3_WRITE_REG(par, PM3ChipConfig,
                           (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
 
+       wmb();
        {
                unsigned char uninitialized_var(m);     /* ClkPreScale */
                unsigned char uninitialized_var(n);     /* ClkFeedBackScale */
@@ -337,7 +325,7 @@ static void pm3fb_write_mode(struct fb_info *info)
 
        PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
 
-       switch (info->var.bits_per_pixel) {
+       switch (pm3fb_depth(&info->var)) {
        case 8:
                PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
                                  PM3RD_PixelSize_8_BIT_PIXELS);
@@ -393,57 +381,44 @@ static void pm3fb_write_mode(struct fb_info *info)
  * hardware independent functions
  */
 int pm3fb_init(void);
-int pm3fb_setup(char*);
 
 static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
        u32 lpitch;
+       unsigned bpp = var->red.length + var->green.length
+                       + var->blue.length + var->transp.length;
 
-       var->transp.offset = 0;
-       var->transp.length = 0;
-       switch(var->bits_per_pixel) {
-       case 8:
-               var->red.length = var->green.length = var->blue.length = 8;
-               var->red.offset = var->green.offset = var->blue.offset = 0;
-               break;
-       case 12:
-               var->red.offset   = 8;
-               var->red.length   = 4;
-               var->green.offset = 4;
-               var->green.length = 4;
-               var->blue.offset  = 0;
-               var->blue.length  = 4;
-               var->transp.offset = 12;
-               var->transp.length = 4;
-       case 15:
-               var->red.offset   = 10;
-               var->red.length   = 5;
-               var->green.offset = 5;
-               var->green.length = 5;
-               var->blue.offset  = 0;
-               var->blue.length  = 5;
-               var->transp.offset = 15;
-               var->transp.length = 1;
-               break;
-       case 16:
-               var->red.offset   = 11;
-               var->red.length   = 5;
-               var->green.offset = 5;
-               var->green.length = 6;
-               var->blue.offset  = 0;
-               var->blue.length  = 5;
-               break;
-       case 32:
-               var->transp.offset = 24;
-               var->transp.length = 8;
-               var->red.offset   = 16;
-               var->green.offset = 8;
-               var->blue.offset  = 0;
-               var->red.length = var->green.length = var->blue.length = 8;
-               break;
-       default:
-               DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
-               return -EINVAL;
+       if ( bpp != var->bits_per_pixel ) {
+               /* set predefined mode for bits_per_pixel settings */
+
+               switch(var->bits_per_pixel) {
+               case 8:
+                       var->red.length = var->green.length = var->blue.length = 8;
+                       var->red.offset = var->green.offset = var->blue.offset = 0;
+                       var->transp.offset = 0;
+                       var->transp.length = 0;
+                       break;
+               case 16:
+                       var->red.length = var->blue.length = 5;
+                       var->green.length = 6;
+                       var->transp.length = 0;
+                       break;
+               case 32:
+                       var->red.length = var->green.length = var->blue.length = 8;
+                       var->transp.length = 8;
+                       break;
+               default:
+                       DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+                       return -EINVAL;
+               }
+       }
+       /* it is assumed BGRA order */
+       if (var->bits_per_pixel > 8 )
+       {
+               var->blue.offset = 0;
+               var->green.offset = var->blue.length;
+               var->red.offset = var->green.offset + var->green.length;
+               var->transp.offset = var->red.offset + var->red.length;
        }
        var->height = var->width = -1;
 
@@ -502,10 +477,9 @@ static int pm3fb_set_par(struct fb_info *info)
 {
        struct pm3_par *par = info->par;
        const u32 xres = (info->var.xres + 31) & ~31;
-       const int depth = (info->var.bits_per_pixel + 7) & ~7;
+       const unsigned bpp = info->var.bits_per_pixel;
 
-       par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
-                                       (info->var.yoffset * xres)
+       par->base = pm3fb_shift_bpp(bpp,(info->var.yoffset * xres)
                                        + info->var.xoffset);
        par->video = 0;
 
@@ -530,12 +504,10 @@ static int pm3fb_set_par(struct fb_info *info)
                par->video |= PM3VideoControl_DISABLE;
                DPRINTK("PM3Video disabled\n");
        }
-       switch (depth) {
+       switch (bpp) {
        case 8:
                par->video |= PM3VideoControl_PIXELSIZE_8BIT;
                break;
-       case 12:
-       case 15:
        case 16:
                par->video |= PM3VideoControl_PIXELSIZE_16BIT;
                break;
@@ -548,9 +520,9 @@ static int pm3fb_set_par(struct fb_info *info)
        }
 
        info->fix.visual =
-               (depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+               (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
        info->fix.line_length = ((info->var.xres_virtual + 7)  & ~7)
-                                       * depth / 8;
+                                       * bpp / 8;
 
 /*     pm3fb_clear_memory(info, 0);*/
        pm3fb_clear_colormap(par, 0, 0, 0);
@@ -580,8 +552,8 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
         *   var->{color}.length contains length of bitfield
         *   {hardwarespecific} contains width of DAC
         *   pseudo_palette[X] is programmed to (X << red.offset) |
-        *                                    (X << green.offset) |
-        *                                    (X << blue.offset)
+        *                                      (X << green.offset) |
+        *                                      (X << blue.offset)
         *   RAMDAC[X] is programmed to (red, green, blue)
         *   color depth = SUM(var->{color}.length)
         *
@@ -621,7 +593,6 @@ static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                case 8:
                        break;
                case 16:
-               case 24:
                case 32:
                        ((u32*)(info->pseudo_palette))[regno] = v;
                        break;
@@ -643,7 +614,8 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var,
        par->base = pm3fb_shift_bpp(var->bits_per_pixel,
                                        (var->yoffset * xres)
                                        + var->xoffset);
-       PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
+       PM3_WAIT(par, 1);
+       PM3_WRITE_REG(par, PM3ScreenBase, par->base);
        return 0;
 }
 
@@ -665,31 +637,31 @@ static int pm3fb_blank(int blank_mode, struct fb_info *info)
 
        switch (blank_mode) {
        case FB_BLANK_UNBLANK:
-               video = video | PM3VideoControl_ENABLE;
+               video |= PM3VideoControl_ENABLE;
                break;
-       case FB_BLANK_NORMAL:   /* FIXME */
-               video = video & ~(PM3VideoControl_ENABLE);
+       case FB_BLANK_NORMAL:
+               video &= ~(PM3VideoControl_ENABLE);
                break;
        case FB_BLANK_HSYNC_SUSPEND:
-               video = video & ~(PM3VideoControl_HSYNC_MASK |
-                                 PM3VideoControl_BLANK_ACTIVE_LOW);
+               video &= ~(PM3VideoControl_HSYNC_MASK |
+                         PM3VideoControl_BLANK_ACTIVE_LOW);
                break;
        case FB_BLANK_VSYNC_SUSPEND:
-               video = video & ~(PM3VideoControl_VSYNC_MASK |
-                                 PM3VideoControl_BLANK_ACTIVE_LOW);
+               video &= ~(PM3VideoControl_VSYNC_MASK |
+                         PM3VideoControl_BLANK_ACTIVE_LOW);
                break;
        case FB_BLANK_POWERDOWN:
-               video = video & ~(PM3VideoControl_HSYNC_MASK |
-                                 PM3VideoControl_VSYNC_MASK |
-                                 PM3VideoControl_BLANK_ACTIVE_LOW);
+               video &= ~(PM3VideoControl_HSYNC_MASK |
+                         PM3VideoControl_VSYNC_MASK |
+                         PM3VideoControl_BLANK_ACTIVE_LOW);
                break;
        default:
                DPRINTK("Unsupported blanking %d\n", blank_mode);
                return 1;
        }
 
-       PM3_SLOW_WRITE_REG(par,PM3VideoControl, video);
-
+       PM3_WAIT(par, 1);
+       PM3_WRITE_REG(par,PM3VideoControl, video);
        return 0;
 }
 
@@ -703,9 +675,9 @@ static struct fb_ops pm3fb_ops = {
        .fb_set_par     = pm3fb_set_par,
        .fb_setcolreg   = pm3fb_setcolreg,
        .fb_pan_display = pm3fb_pan_display,
-       .fb_fillrect    = cfb_fillrect,         /* Needed !!! */
-       .fb_copyarea    = cfb_copyarea,         /* Needed !!! */
-       .fb_imageblit   = cfb_imageblit,        /* Needed !!! */
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
        .fb_blank       = pm3fb_blank,
 };
 
@@ -722,7 +694,7 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
        unsigned long   memsize = 0, tempBypass, i, temp1, temp2;
        unsigned char   __iomem *screen_mem;
 
-       pm3fb_fix.smem_len = 64 * 1024 * 1024; /* request full aperture size */
+       pm3fb_fix.smem_len = 64 * 1024l * 1024; /* request full aperture size */
        /* Linear frame buffer - request region and map it. */
        if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
                                 "pm3fb smem")) {
@@ -744,7 +716,8 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
 
        DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
 
-       PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
+       PM3_WAIT(par, 1);
+       PM3_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
 
        /* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
        for (i = 0; i < 32; i++) {
@@ -765,10 +738,9 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
        if (memsize + 1 == i) {
                for (i = 0; i < 32; i++) {
                        /* Clear first 32MB ; 0 is 0, no need to byteswap */
-                       writel(0x0000000,
-                              (screen_mem + (i * 1048576)));
-                       mb();
+                       writel(0x0000000, (screen_mem + (i * 1048576)));
                }
+               wmb();
 
                for (i = 32; i < 64; i++) {
                        fb_writel(i * 0x00345678,
@@ -787,7 +759,8 @@ static unsigned long pm3fb_size_memory(struct pm3_par *par)
        }
        DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
 
-       PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
+       PM3_WAIT(par, 1);
+       PM3_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
 
        iounmap(screen_mem);
        release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
@@ -890,7 +863,6 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
                goto err_exit_both;
        }
 
-       /* This has to been done !!! */
        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
                retval = -ENOMEM;
                goto err_exit_both;
@@ -907,7 +879,7 @@ static int __devinit pm3fb_probe(struct pci_dev *dev,
        }
        printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
           info->fix.id);
-       pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+       pci_set_drvdata(dev, info);
        return 0;
 
  err_exit_all:
@@ -949,8 +921,7 @@ static void __devexit pm3fb_remove(struct pci_dev *dev)
 
 static struct pci_device_id pm3fb_id_table[] = {
        { PCI_VENDOR_ID_3DLABS, 0x0a,
-         PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
-         0xff0000, 0 },
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        { 0, }
 };
 
@@ -964,6 +935,22 @@ static struct pci_driver pm3fb_driver = {
 
 MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
 
+#ifndef MODULE
+       /*
+        *  Setup
+        */
+
+/*
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+static int __init pm3fb_setup(char *options)
+{
+       /* Parse user speficied options (`video=pm3fb:') */
+       return 0;
+}
+#endif /* MODULE */
+
 int __init pm3fb_init(void)
 {
        /*
@@ -985,22 +972,6 @@ static void __exit pm3fb_exit(void)
        pci_unregister_driver(&pm3fb_driver);
 }
 
-#ifndef MODULE
-       /*
-        *  Setup
-        */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-int __init pm3fb_setup(char *options)
-{
-       /* Parse user speficied options (`video=pm3fb:') */
-       return 0;
-}
-#endif /* MODULE */
-
 module_init(pm3fb_init);
 module_exit(pm3fb_exit);
 
index 9756a72..9cf92ba 100644 (file)
@@ -951,12 +951,14 @@ static int ps3fb_xdr_settings(u64 xdr_lpar)
 static struct fb_ops ps3fb_ops = {
        .fb_open        = ps3fb_open,
        .fb_release     = ps3fb_release,
+       .fb_read        = fb_sys_read,
+       .fb_write       = fb_sys_write,
        .fb_check_var   = ps3fb_check_var,
        .fb_set_par     = ps3fb_set_par,
        .fb_setcolreg   = ps3fb_setcolreg,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
+       .fb_fillrect    = sys_fillrect,
+       .fb_copyarea    = sys_copyarea,
+       .fb_imageblit   = sys_imageblit,
        .fb_mmap        = ps3fb_mmap,
        .fb_blank       = ps3fb_blank,
        .fb_ioctl       = ps3fb_ioctl,
index 5fc86ea..003c49a 100644 (file)
@@ -660,7 +660,7 @@ int __init w100fb_probe(struct platform_device *pdev)
                        err = -ENODEV;
                        goto out;
        }
-       printk(" at 0x%08lx.\n", mem->start+W100_CFG_BASE);
+       printk(" at 0x%08lx.\n", (unsigned long) mem->start+W100_CFG_BASE);
 
        /* Remap the framebuffer */
        remapped_fbuf = ioremap_nocache(mem->start+MEM_WINDOW_BASE, MEM_WINDOW_SIZE);
@@ -753,10 +753,14 @@ int __init w100fb_probe(struct platform_device *pdev)
                goto out;
        }
 
-       device_create_file(&pdev->dev, &dev_attr_fastpllclk);
-       device_create_file(&pdev->dev, &dev_attr_reg_read);
-       device_create_file(&pdev->dev, &dev_attr_reg_write);
-       device_create_file(&pdev->dev, &dev_attr_flip);
+       err = device_create_file(&pdev->dev, &dev_attr_fastpllclk);
+       err |= device_create_file(&pdev->dev, &dev_attr_reg_read);
+       err |= device_create_file(&pdev->dev, &dev_attr_reg_write);
+       err |= device_create_file(&pdev->dev, &dev_attr_flip);
+
+       if (err != 0)
+               printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
+                               info->node, err);
 
        printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
        return 0;
index 1de2331..4db6216 100644 (file)
@@ -1544,9 +1544,10 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
 {
        fd_set_bits fds;
-       char *bits;
+       void *bits;
        int size, max_fds, ret = -EINVAL;
        struct fdtable *fdt;
+       long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
 
        if (n < 0)
                goto out_nofds;
@@ -1564,11 +1565,14 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
         * since we used fdset we need to allocate memory in units of
         * long-words.
         */
-       ret = -ENOMEM;
        size = FDS_BYTES(n);
-       bits = kmalloc(6 * size, GFP_KERNEL);
-       if (!bits)
-               goto out_nofds;
+       bits = stack_fds;
+       if (size > sizeof(stack_fds) / 6) {
+               bits = kmalloc(6 * size, GFP_KERNEL);
+               ret = -ENOMEM;
+               if (!bits)
+                       goto out_nofds;
+       }
        fds.in      = (unsigned long *)  bits;
        fds.out     = (unsigned long *) (bits +   size);
        fds.ex      = (unsigned long *) (bits + 2*size);
@@ -1600,7 +1604,8 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
            compat_set_fd_set(n, exp, fds.res_ex))
                ret = -EFAULT;
 out:
-       kfree(bits);
+       if (bits != stack_fds)
+               kfree(bits);
 out_nofds:
        return ret;
 }
index 9881b5c..59288d8 100644 (file)
 #include "ecryptfs_kernel.h"
 
 /**
- * ecryptfs_llseek
- * @file: File we are seeking in
- * @offset: The offset to seek to
- * @origin: 2 - offset from i_size; 1 - offset from f_pos
- *
- * Returns the position we have seeked to, or negative on error
- */
-static loff_t ecryptfs_llseek(struct file *file, loff_t offset, int origin)
-{
-       loff_t rv;
-       loff_t new_end_pos;
-       int rc;
-       int expanding_file = 0;
-       struct inode *inode = file->f_mapping->host;
-
-       /* If our offset is past the end of our file, we're going to
-        * need to grow it so we have a valid length of 0's */
-       new_end_pos = offset;
-       switch (origin) {
-       case 2:
-               new_end_pos += i_size_read(inode);
-               expanding_file = 1;
-               break;
-       case 1:
-               new_end_pos += file->f_pos;
-               if (new_end_pos > i_size_read(inode)) {
-                       ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
-                                       "> i_size_read(inode)(=[0x%.16x])\n",
-                                       new_end_pos, i_size_read(inode));
-                       expanding_file = 1;
-               }
-               break;
-       default:
-               if (new_end_pos > i_size_read(inode)) {
-                       ecryptfs_printk(KERN_DEBUG, "new_end_pos(=[0x%.16x]) "
-                                       "> i_size_read(inode)(=[0x%.16x])\n",
-                                       new_end_pos, i_size_read(inode));
-                       expanding_file = 1;
-               }
-       }
-       ecryptfs_printk(KERN_DEBUG, "new_end_pos = [0x%.16x]\n", new_end_pos);
-       if (expanding_file) {
-               rc = ecryptfs_truncate(file->f_path.dentry, new_end_pos);
-               if (rc) {
-                       rv = rc;
-                       ecryptfs_printk(KERN_ERR, "Error on attempt to "
-                                       "truncate to (higher) offset [0x%.16x];"
-                                       " rc = [%d]\n", new_end_pos, rc);
-                       goto out;
-               }
-       }
-       rv = generic_file_llseek(file, offset, origin);
-out:
-       return rv;
-}
-
-/**
  * ecryptfs_read_update_atime
  *
  * generic_file_read updates the atime of upper layer inode.  But, it
@@ -425,7 +368,7 @@ const struct file_operations ecryptfs_dir_fops = {
 };
 
 const struct file_operations ecryptfs_main_fops = {
-       .llseek = ecryptfs_llseek,
+       .llseek = generic_file_llseek,
        .read = do_sync_read,
        .aio_read = ecryptfs_read_update_atime,
        .write = do_sync_write,
index 88ea669..55cec98 100644 (file)
@@ -376,9 +376,31 @@ out:
        return 0;
 }
 
+/**
+ * eCryptfs does not currently support holes. When writing after a
+ * seek past the end of the file, eCryptfs fills in 0's through to the
+ * current location. The code to fill in the 0's to all the
+ * intermediate pages calls ecryptfs_prepare_write_no_truncate().
+ */
+static int
+ecryptfs_prepare_write_no_truncate(struct file *file, struct page *page,
+                                  unsigned from, unsigned to)
+{
+       int rc = 0;
+
+       if (from == 0 && to == PAGE_CACHE_SIZE)
+               goto out;       /* If we are writing a full page, it will be
+                                  up to date. */
+       if (!PageUptodate(page))
+               rc = ecryptfs_do_readpage(file, page, page->index);
+out:
+       return rc;
+}
+
 static int ecryptfs_prepare_write(struct file *file, struct page *page,
                                  unsigned from, unsigned to)
 {
+       loff_t pos;
        int rc = 0;
 
        if (from == 0 && to == PAGE_CACHE_SIZE)
@@ -386,6 +408,16 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
                                   up to date. */
        if (!PageUptodate(page))
                rc = ecryptfs_do_readpage(file, page, page->index);
+       pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+       if (pos > i_size_read(page->mapping->host)) {
+               rc = ecryptfs_truncate(file->f_path.dentry, pos);
+               if (rc) {
+                       printk(KERN_ERR "Error on attempt to "
+                              "truncate to (higher) offset [%lld];"
+                              " rc = [%d]\n", pos, rc);
+                       goto out;
+               }
+       }
 out:
        return rc;
 }
@@ -744,10 +776,10 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
                rc = PTR_ERR(tmp_page);
                goto out;
        }
-       rc = ecryptfs_prepare_write(file, tmp_page, start, start + num_zeros);
-       if (rc) {
+       if ((rc = ecryptfs_prepare_write_no_truncate(file, tmp_page, start,
+                                                    (start + num_zeros)))) {
                ecryptfs_printk(KERN_ERR, "Error preparing to write zero's "
-                               "to remainder of page at index [0x%.16x]\n",
+                               "to page at index [0x%.16x]\n",
                                index);
                page_cache_release(tmp_page);
                goto out;
index 0b68588..f20561f 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -134,6 +134,9 @@ asmlinkage long sys_uselib(const char __user * library)
        if (error)
                goto out;
 
+       error = -EACCES;
+       if (nd.mnt->mnt_flags & MNT_NOEXEC)
+               goto exit;
        error = -EINVAL;
        if (!S_ISREG(nd.dentry->d_inode->i_mode))
                goto exit;
index 8890eba..bd5a772 100644 (file)
@@ -485,7 +485,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
 static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
                       struct nameidata *nd)
 {
-       if (nd && (nd->flags & LOOKUP_CREATE)) {
+       if (nd && (nd->flags & LOOKUP_OPEN)) {
                int err = fuse_create_open(dir, entry, mode, nd);
                if (err != -ENOSYS)
                        return err;
index d0ed60b..adf7995 100644 (file)
@@ -610,7 +610,9 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
        ssize_t res;
        /* Don't allow parallel writes to the same file */
        mutex_lock(&inode->i_mutex);
-       res = fuse_direct_io(file, buf, count, ppos, 1);
+       res = generic_write_checks(file, ppos, &count, 0);
+       if (!res)
+               res = fuse_direct_io(file, buf, count, ppos, 1);
        mutex_unlock(&inode->i_mutex);
        return res;
 }
index 78f7a1d..9804c0c 100644 (file)
@@ -454,6 +454,7 @@ static const struct super_operations fuse_super_operations = {
        .destroy_inode  = fuse_destroy_inode,
        .read_inode     = fuse_read_inode,
        .clear_inode    = fuse_clear_inode,
+       .drop_inode     = generic_delete_inode,
        .remount_fs     = fuse_remount_fs,
        .put_super      = fuse_put_super,
        .umount_begin   = fuse_umount_begin,
index 9c23fee..ffbfc2c 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/buffer_head.h>
 #include <asm/uaccess.h>
 
-extern struct reiserfs_key MIN_KEY;
+extern const struct reiserfs_key MIN_KEY;
 
 static int reiserfs_readdir(struct file *, void *, filldir_t);
 static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry,
index 7cfeab4..f1da892 100644 (file)
@@ -11,6 +11,8 @@
  *      Now using anonymous inode source.
  *      Thanks to Oleg Nesterov for useful code review and suggestions.
  *      More comments and suggestions from Arnd Bergmann.
+ * Sat May 19, 2007: Davi E. M. Arnaut <davi@haxent.com.br>
+ *      Retrieve multiple signals with one read() call
  */
 
 #include <linux/file.h>
@@ -206,6 +208,59 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
        return err ? -EFAULT: sizeof(*uinfo);
 }
 
+static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
+                               int nonblock)
+{
+       ssize_t ret;
+       struct signalfd_lockctx lk;
+       DECLARE_WAITQUEUE(wait, current);
+
+       if (!signalfd_lock(ctx, &lk))
+               return 0;
+
+       ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
+       switch (ret) {
+       case 0:
+               if (!nonblock)
+                       break;
+               ret = -EAGAIN;
+       default:
+               signalfd_unlock(&lk);
+               return ret;
+       }
+
+       add_wait_queue(&ctx->wqh, &wait);
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               ret = dequeue_signal(lk.tsk, &ctx->sigmask, info);
+               signalfd_unlock(&lk);
+               if (ret != 0)
+                       break;
+               if (signal_pending(current)) {
+                       ret = -ERESTARTSYS;
+                       break;
+               }
+               schedule();
+               ret = signalfd_lock(ctx, &lk);
+               if (unlikely(!ret)) {
+                       /*
+                        * Let the caller read zero byte, ala socket
+                        * recv() when the peer disconnect. This test
+                        * must be done before doing a dequeue_signal(),
+                        * because if the sighand has been orphaned,
+                        * the dequeue_signal() call is going to crash
+                        * because ->sighand will be long gone.
+                        */
+                        break;
+               }
+       }
+
+       remove_wait_queue(&ctx->wqh, &wait);
+       __set_current_state(TASK_RUNNING);
+
+       return ret;
+}
+
 /*
  * Returns either the size of a "struct signalfd_siginfo", or zero if the
  * sighand we are attached to, has been orphaned. The "count" parameter
@@ -215,55 +270,30 @@ static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
                             loff_t *ppos)
 {
        struct signalfd_ctx *ctx = file->private_data;
-       ssize_t res = 0;
-       int locked, signo;
+       struct signalfd_siginfo __user *siginfo;
+       int nonblock = file->f_flags & O_NONBLOCK;
+       ssize_t ret, total = 0;
        siginfo_t info;
-       struct signalfd_lockctx lk;
-       DECLARE_WAITQUEUE(wait, current);
 
-       if (count < sizeof(struct signalfd_siginfo))
+       count /= sizeof(struct signalfd_siginfo);
+       if (!count)
                return -EINVAL;
-       locked = signalfd_lock(ctx, &lk);
-       if (!locked)
-               return 0;
-       res = -EAGAIN;
-       signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
-       if (signo == 0 && !(file->f_flags & O_NONBLOCK)) {
-               add_wait_queue(&ctx->wqh, &wait);
-               for (;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
-                       if (signo != 0)
-                               break;
-                       if (signal_pending(current)) {
-                               res = -ERESTARTSYS;
-                               break;
-                       }
-                       signalfd_unlock(&lk);
-                       schedule();
-                       locked = signalfd_lock(ctx, &lk);
-                       if (unlikely(!locked)) {
-                               /*
-                                * Let the caller read zero byte, ala socket
-                                * recv() when the peer disconnect. This test
-                                * must be done before doing a dequeue_signal(),
-                                * because if the sighand has been orphaned,
-                                * the dequeue_signal() call is going to crash.
-                                */
-                               res = 0;
-                               break;
-                       }
-               }
-               remove_wait_queue(&ctx->wqh, &wait);
-               __set_current_state(TASK_RUNNING);
-       }
-       if (likely(locked))
-               signalfd_unlock(&lk);
-       if (likely(signo))
-               res = signalfd_copyinfo((struct signalfd_siginfo __user *) buf,
-                                       &info);
 
-       return res;
+       siginfo = (struct signalfd_siginfo __user *) buf;
+
+       do {
+               ret = signalfd_dequeue(ctx, &info, nonblock);
+               if (unlikely(ret <= 0))
+                       break;
+               ret = signalfd_copyinfo(siginfo, &info);
+               if (ret < 0)
+                       break;
+               siginfo++;
+               total += ret;
+               nonblock = 1;
+       } while (--count);
+
+       return total ? total : ret;
 }
 
 static const struct file_operations signalfd_fops = {
index 0baa2f8..437aac8 100644 (file)
@@ -182,7 +182,7 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
        int __i;
 #ifdef CONFIG_M386
        unsigned long flags;
-       if(unlikely(boot_cpu_data.x86==3))
+       if(unlikely(boot_cpu_data.x86 <= 3))
                goto no_xadd;
 #endif
        /* Modern 486+ processor */
index e13d3e9..6e85975 100644 (file)
@@ -135,7 +135,7 @@ static __inline__ long local_add_return(long i, local_t *l)
        long __i;
 #ifdef CONFIG_M386
        unsigned long flags;
-       if(unlikely(boot_cpu_data.x86==3))
+       if(unlikely(boot_cpu_data.x86 <= 3))
                goto no_xadd;
 #endif
        /* Modern 486+ processor */
index 6548b35..bbf8df7 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/types.h>
 #include <linux/compiler.h>
 
+struct task_struct;
+
 /* User-level do most of the mapping between kernel and user
    capabilities based on the version tag given by the kernel. The
    kernel might be somewhat backwards compatible, but don't bet on
index 5e75e26..4631086 100644 (file)
@@ -37,25 +37,25 @@ static inline void do_not_freeze(struct task_struct *p)
 
 /*
  * Wake up a frozen process
+ *
+ * task_lock() is taken to prevent the race with refrigerator() which may
+ * occur if the freezing of tasks fails.  Namely, without the lock, if the
+ * freezing of tasks failed, thaw_tasks() might have run before a task in
+ * refrigerator() could call frozen_process(), in which case the task would be
+ * frozen and no one would thaw it.
  */
 static inline int thaw_process(struct task_struct *p)
 {
+       task_lock(p);
        if (frozen(p)) {
                p->flags &= ~PF_FROZEN;
+               task_unlock(p);
                wake_up_process(p);
                return 1;
        }
-       return 0;
-}
-
-/*
- * freezing is complete, mark process as frozen
- */
-static inline void frozen_process(struct task_struct *p)
-{
-       p->flags |= PF_FROZEN;
-       wmb();
        clear_tsk_thread_flag(p, TIF_FREEZE);
+       task_unlock(p);
+       return 0;
 }
 
 extern void refrigerator(void);
@@ -71,14 +71,55 @@ static inline int try_to_freeze(void)
                return 0;
 }
 
-extern void thaw_some_processes(int all);
+/*
+ * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
+ * calls wait_for_completion(&vfork) and reset right after it returns from this
+ * function.  Next, the parent should call try_to_freeze() to freeze itself
+ * appropriately in case the child has exited before the freezing of tasks is
+ * complete.  However, we don't want kernel threads to be frozen in unexpected
+ * places, so we allow them to block freeze_processes() instead or to set
+ * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
+ * parents.  Fortunately, in the ____call_usermodehelper() case the parent won't
+ * really block freeze_processes(), since ____call_usermodehelper() (the child)
+ * does a little before exec/exit and it can't be frozen before waking up the
+ * parent.
+ */
+
+/*
+ * If the current task is a user space one, tell the freezer not to count it as
+ * freezable.
+ */
+static inline void freezer_do_not_count(void)
+{
+       if (current->mm)
+               current->flags |= PF_FREEZER_SKIP;
+}
+
+/*
+ * If the current task is a user space one, tell the freezer to count it as
+ * freezable again and try to freeze it.
+ */
+static inline void freezer_count(void)
+{
+       if (current->mm) {
+               current->flags &= ~PF_FREEZER_SKIP;
+               try_to_freeze();
+       }
+}
+
+/*
+ * Check if the task should be counted as freezeable by the freezer
+ */
+static inline int freezer_should_skip(struct task_struct *p)
+{
+       return !!(p->flags & PF_FREEZER_SKIP);
+}
 
 #else
 static inline int frozen(struct task_struct *p) { return 0; }
 static inline int freezing(struct task_struct *p) { return 0; }
 static inline void freeze(struct task_struct *p) { BUG(); }
 static inline int thaw_process(struct task_struct *p) { return 1; }
-static inline void frozen_process(struct task_struct *p) { BUG(); }
 
 static inline void refrigerator(void) {}
 static inline int freeze_processes(void) { BUG(); return 0; }
@@ -86,5 +127,7 @@ static inline void thaw_processes(void) {}
 
 static inline int try_to_freeze(void) { return 0; }
 
-
+static inline void freezer_do_not_count(void) {}
+static inline void freezer_count(void) {}
+static inline int freezer_should_skip(struct task_struct *p) { return 0; }
 #endif
index 4c03ee3..9756fc1 100644 (file)
@@ -66,6 +66,7 @@ struct partition {
 #include <linux/smp.h>
 #include <linux/string.h>
 #include <linux/fs.h>
+#include <linux/workqueue.h>
 
 struct partition {
        unsigned char boot_ind;         /* 0x80 - active */
@@ -94,6 +95,7 @@ struct hd_struct {
 
 #define GENHD_FL_REMOVABLE                     1
 #define GENHD_FL_DRIVERFS                      2
+#define GENHD_FL_MEDIA_CHANGE_NOTIFY           4
 #define GENHD_FL_CD                            8
 #define GENHD_FL_UP                            16
 #define GENHD_FL_SUPPRESS_PARTITION_INFO       32
@@ -138,6 +140,7 @@ struct gendisk {
 #else
        struct disk_stats dkstats;
 #endif
+       struct work_struct async_notify;
 };
 
 /* Structure for sysfs attributes on block devices */
@@ -419,7 +422,7 @@ extern struct gendisk *alloc_disk_node(int minors, int node_id);
 extern struct gendisk *alloc_disk(int minors);
 extern struct kobject *get_disk(struct gendisk *disk);
 extern void put_disk(struct gendisk *disk);
-
+extern void genhd_media_change_notify(struct gendisk *disk);
 extern void blk_register_region(dev_t dev, unsigned long range,
                        struct module *module,
                        struct kobject *(*probe)(dev_t, int *, void *),
index 6db9a4c..dd5a05d 100644 (file)
@@ -232,6 +232,7 @@ struct bitmap {
        struct page **filemap; /* list of cache pages for the file */
        unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
        unsigned long file_pages; /* number of pages in the file */
+       int last_page_size; /* bytes in the last page */
 
        unsigned long flags;
 
index a81897e..d58e74b 100644 (file)
@@ -1182,6 +1182,7 @@ static inline void put_task_struct(struct task_struct *t)
 #define PF_SPREAD_SLAB 0x02000000      /* Spread some slab caches over cpuset */
 #define PF_MEMPOLICY   0x10000000      /* Non-default NUMA mempolicy */
 #define PF_MUTEX_TESTER        0x20000000      /* Thread belongs to the rt mutex tester */
+#define PF_FREEZER_SKIP        0x40000000      /* Freezer should not count it as freezeable */
 
 /*
  * Only the _current_ task can read/write to tsk->flags, but other
@@ -1615,11 +1616,13 @@ static inline int lock_need_resched(spinlock_t *lock)
        return 0;
 }
 
-/* Reevaluate whether the task has signals pending delivery.
-   This is required every time the blocked sigset_t changes.
-   callers must hold sighand->siglock.  */
-
-extern FASTCALL(void recalc_sigpending_tsk(struct task_struct *t));
+/*
+ * Reevaluate whether the task has signals pending delivery.
+ * Wake the task if so.
+ * This is required every time the blocked sigset_t changes.
+ * callers must hold sighand->siglock.
+ */
+extern void recalc_sigpending_and_wake(struct task_struct *t);
 extern void recalc_sigpending(void);
 
 extern void signal_wake_up(struct task_struct *t, int resume_stopped);
index c6d14b8..5b888c2 100644 (file)
@@ -762,11 +762,8 @@ static void exit_notify(struct task_struct *tsk)
                read_lock(&tasklist_lock);
                spin_lock_irq(&tsk->sighand->siglock);
                for (t = next_thread(tsk); t != tsk; t = next_thread(t))
-                       if (!signal_pending(t) && !(t->flags & PF_EXITING)) {
-                               recalc_sigpending_tsk(t);
-                               if (signal_pending(t))
-                                       signal_wake_up(t, 0);
-                       }
+                       if (!signal_pending(t) && !(t->flags & PF_EXITING))
+                               recalc_sigpending_and_wake(t);
                spin_unlock_irq(&tsk->sighand->siglock);
                read_unlock(&tasklist_lock);
        }
index 87069cf..73ad5cd 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/acct.h>
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
+#include <linux/freezer.h>
 #include <linux/delayacct.h>
 #include <linux/taskstats_kern.h>
 #include <linux/random.h>
@@ -1405,7 +1406,9 @@ long do_fork(unsigned long clone_flags,
                }
 
                if (clone_flags & CLONE_VFORK) {
+                       freezer_do_not_count();
                        wait_for_completion(&vfork);
+                       freezer_count();
                        if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
                                current->ptrace_message = nr;
                                ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
index b0d81aa..bd9e272 100644 (file)
@@ -135,6 +135,39 @@ report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
        }
 }
 
+static inline int try_misrouted_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
+{
+       struct irqaction *action;
+
+       if (!irqfixup)
+               return 0;
+
+       /* We didn't actually handle the IRQ - see if it was misrouted? */
+       if (action_ret == IRQ_NONE)
+               return 1;
+
+       /*
+        * But for 'irqfixup == 2' we also do it for handled interrupts if
+        * they are marked as IRQF_IRQPOLL (or for irq zero, which is the
+        * traditional PC timer interrupt.. Legacy)
+        */
+       if (irqfixup < 2)
+               return 0;
+
+       if (!irq)
+               return 1;
+
+       /*
+        * Since we don't get the descriptor lock, "action" can
+        * change under us.  We don't really care, but we don't
+        * want to follow a NULL pointer. So tell the compiler to
+        * just load it once by using a barrier.
+        */
+       action = desc->action;
+       barrier();
+       return action && (action->flags & IRQF_IRQPOLL);
+}
+
 void note_interrupt(unsigned int irq, struct irq_desc *desc,
                    irqreturn_t action_ret)
 {
@@ -144,15 +177,10 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
                        report_bad_irq(irq, desc, action_ret);
        }
 
-       if (unlikely(irqfixup)) {
-               /* Don't punish working computers */
-               if ((irqfixup == 2 && ((irq == 0) ||
-                               (desc->action->flags & IRQF_IRQPOLL))) ||
-                               action_ret == IRQ_NONE) {
-                       int ok = misrouted_irq(irq);
-                       if (action_ret == IRQ_NONE)
-                               desc->irqs_unhandled -= ok;
-               }
+       if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
+               int ok = misrouted_irq(irq);
+               if (action_ret == IRQ_NONE)
+                       desc->irqs_unhandled -= ok;
        }
 
        desc->irq_count++;
index df8a8e8..bbd51b8 100644 (file)
@@ -70,7 +70,7 @@ static int kthread(void *_create)
        data = create->data;
 
        /* OK, tell user we're spawned, wait for stop or wakeup */
-       __set_current_state(TASK_INTERRUPTIBLE);
+       __set_current_state(TASK_UNINTERRUPTIBLE);
        complete(&create->started);
        schedule();
 
@@ -162,7 +162,10 @@ EXPORT_SYMBOL(kthread_create);
  */
 void kthread_bind(struct task_struct *k, unsigned int cpu)
 {
-       BUG_ON(k->state != TASK_INTERRUPTIBLE);
+       if (k->state != TASK_UNINTERRUPTIBLE) {
+               WARN_ON(1);
+               return;
+       }
        /* Must have done schedule() in kthread() before we set_task_cpu */
        wait_task_inactive(k);
        set_task_cpu(k, cpu);
index 0884193..e0233d8 100644 (file)
@@ -31,16 +31,36 @@ static inline int freezeable(struct task_struct * p)
        return 1;
 }
 
+/*
+ * freezing is complete, mark current process as frozen
+ */
+static inline void frozen_process(void)
+{
+       if (!unlikely(current->flags & PF_NOFREEZE)) {
+               current->flags |= PF_FROZEN;
+               wmb();
+       }
+       clear_tsk_thread_flag(current, TIF_FREEZE);
+}
+
 /* Refrigerator is place where frozen processes are stored :-). */
 void refrigerator(void)
 {
        /* Hmm, should we be allowed to suspend when there are realtime
           processes around? */
        long save;
+
+       task_lock(current);
+       if (freezing(current)) {
+               frozen_process();
+               task_unlock(current);
+       } else {
+               task_unlock(current);
+               return;
+       }
        save = current->state;
        pr_debug("%s entered refrigerator\n", current->comm);
 
-       frozen_process(current);
        spin_lock_irq(&current->sighand->siglock);
        recalc_sigpending(); /* We sent fake signal, clean it up */
        spin_unlock_irq(&current->sighand->siglock);
@@ -81,7 +101,7 @@ static void cancel_freezing(struct task_struct *p)
                pr_debug("  clean up: %s\n", p->comm);
                do_not_freeze(p);
                spin_lock_irqsave(&p->sighand->siglock, flags);
-               recalc_sigpending_tsk(p);
+               recalc_sigpending_and_wake(p);
                spin_unlock_irqrestore(&p->sighand->siglock, flags);
        }
 }
@@ -112,22 +132,12 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space)
                                cancel_freezing(p);
                                continue;
                        }
-                       if (is_user_space(p)) {
-                               if (!freeze_user_space)
-                                       continue;
-
-                               /* Freeze the task unless there is a vfork
-                                * completion pending
-                                */
-                               if (!p->vfork_done)
-                                       freeze_process(p);
-                       } else {
-                               if (freeze_user_space)
-                                       continue;
-
-                               freeze_process(p);
-                       }
-                       todo++;
+                       if (freeze_user_space && !is_user_space(p))
+                               continue;
+
+                       freeze_process(p);
+                       if (!freezer_should_skip(p))
+                               todo++;
                } while_each_thread(g, p);
                read_unlock(&tasklist_lock);
                yield();                        /* Yield is okay here */
@@ -149,13 +159,16 @@ static unsigned int try_to_freeze_tasks(int freeze_user_space)
                                TIMEOUT / HZ, todo);
                read_lock(&tasklist_lock);
                do_each_thread(g, p) {
-                       if (is_user_space(p) == !freeze_user_space)
+                       if (freeze_user_space && !is_user_space(p))
                                continue;
 
-                       if (freezeable(p) && !frozen(p))
+                       task_lock(p);
+                       if (freezeable(p) && !frozen(p) &&
+                           !freezer_should_skip(p))
                                printk(KERN_ERR " %s\n", p->comm);
 
                        cancel_freezing(p);
+                       task_unlock(p);
                } while_each_thread(g, p);
                read_unlock(&tasklist_lock);
        }
@@ -200,9 +213,7 @@ static void thaw_tasks(int thaw_user_space)
                if (is_user_space(p) == !thaw_user_space)
                        continue;
 
-               if (!thaw_process(p))
-                       printk(KERN_WARNING " Strange, %s not stopped\n",
-                               p->comm );
+               thaw_process(p);
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
 }
index b8b235c..8b1a1b8 100644 (file)
@@ -584,7 +584,7 @@ int swsusp_check(void)
        resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
        if (!IS_ERR(resume_bdev)) {
                set_blocksize(resume_bdev, PAGE_SIZE);
-               memset(swsusp_header, 0, sizeof(PAGE_SIZE));
+               memset(swsusp_header, 0, PAGE_SIZE);
                error = bio_read_page(swsusp_resume_block,
                                        swsusp_header, NULL);
                if (error)
index 799d23b..13cdab3 100644 (file)
@@ -4775,9 +4775,7 @@ int __sched cond_resched_softirq(void)
        BUG_ON(!in_softirq());
 
        if (need_resched() && system_state == SYSTEM_RUNNING) {
-               raw_local_irq_disable();
-               _local_bh_enable();
-               raw_local_irq_enable();
+               local_bh_enable();
                __cond_resched();
                local_bh_disable();
                return 1;
index 364fc95..acdfc05 100644 (file)
@@ -96,15 +96,27 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
 
 #define PENDING(p,b) has_pending_signals(&(p)->signal, (b))
 
-fastcall void recalc_sigpending_tsk(struct task_struct *t)
+static int recalc_sigpending_tsk(struct task_struct *t)
 {
        if (t->signal->group_stop_count > 0 ||
            (freezing(t)) ||
            PENDING(&t->pending, &t->blocked) ||
-           PENDING(&t->signal->shared_pending, &t->blocked))
+           PENDING(&t->signal->shared_pending, &t->blocked)) {
                set_tsk_thread_flag(t, TIF_SIGPENDING);
-       else
-               clear_tsk_thread_flag(t, TIF_SIGPENDING);
+               return 1;
+       }
+       clear_tsk_thread_flag(t, TIF_SIGPENDING);
+       return 0;
+}
+
+/*
+ * After recalculating TIF_SIGPENDING, we need to make sure the task wakes up.
+ * This is superfluous when called on current, the wakeup is a harmless no-op.
+ */
+void recalc_sigpending_and_wake(struct task_struct *t)
+{
+       if (recalc_sigpending_tsk(t))
+               signal_wake_up(t, 0);
 }
 
 void recalc_sigpending(void)
@@ -744,7 +756,7 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
                action->sa.sa_handler = SIG_DFL;
                if (blocked) {
                        sigdelset(&t->blocked, sig);
-                       recalc_sigpending_tsk(t);
+                       recalc_sigpending_and_wake(t);
                }
        }
        ret = specific_send_sig_info(sig, info, t);
@@ -2273,7 +2285,7 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
                        rm_from_queue_full(&mask, &t->signal->shared_pending);
                        do {
                                rm_from_queue_full(&mask, &t->pending);
-                               recalc_sigpending_tsk(t);
+                               recalc_sigpending_and_wake(t);
                                t = next_thread(t);
                        } while (t != current);
                }
index eadfce2..8001d37 100644 (file)
@@ -243,11 +243,18 @@ void tick_broadcast_on_off(unsigned long reason, int *oncpu)
 {
        int cpu = get_cpu();
 
-       if (cpu == *oncpu)
-               tick_do_broadcast_on_off(&reason);
-       else
-               smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
-                                        &reason, 1, 1);
+       if (!cpu_isset(*oncpu, cpu_online_map)) {
+               printk(KERN_ERR "tick-braodcast: ignoring broadcast for "
+                      "offline CPU #%d\n", *oncpu);
+       } else {
+
+               if (cpu == *oncpu)
+                       tick_do_broadcast_on_off(&reason);
+               else
+                       smp_call_function_single(*oncpu,
+                                                tick_do_broadcast_on_off,
+                                                &reason, 1, 1);
+       }
        put_cpu();
 }
 
index 3483e6c..3e7ebc4 100644 (file)
@@ -167,9 +167,15 @@ void tick_nohz_stop_sched_tick(void)
                goto end;
 
        cpu = smp_processor_id();
-       if (unlikely(local_softirq_pending()))
-               printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
-                      local_softirq_pending());
+       if (unlikely(local_softirq_pending())) {
+               static int ratelimit;
+
+               if (ratelimit < 10) {
+                       printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+                              local_softirq_pending());
+                       ratelimit++;
+               }
+       }
 
        now = ktime_get();
        /*
index fb56fed..3bebf73 100644 (file)
@@ -47,7 +47,6 @@ struct cpu_workqueue_struct {
 
        struct workqueue_struct *wq;
        struct task_struct *thread;
-       int should_stop;
 
        int run_depth;          /* Detect run_workqueue() recursion depth */
 } ____cacheline_aligned;
@@ -71,7 +70,13 @@ static LIST_HEAD(workqueues);
 
 static int singlethread_cpu __read_mostly;
 static cpumask_t cpu_singlethread_map __read_mostly;
-/* optimization, we could use cpu_possible_map */
+/*
+ * _cpu_down() first removes CPU from cpu_online_map, then CPU_DEAD
+ * flushes cwq->worklist. This means that flush_workqueue/wait_on_work
+ * which comes in between can't use for_each_online_cpu(). We could
+ * use cpu_possible_map, the cpumask below is more a documentation
+ * than optimization.
+ */
 static cpumask_t cpu_populated_map __read_mostly;
 
 /* If it's single threaded, it isn't in the list of workqueues. */
@@ -272,24 +277,6 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
        spin_unlock_irq(&cwq->lock);
 }
 
-/*
- * NOTE: the caller must not touch *cwq if this func returns true
- */
-static int cwq_should_stop(struct cpu_workqueue_struct *cwq)
-{
-       int should_stop = cwq->should_stop;
-
-       if (unlikely(should_stop)) {
-               spin_lock_irq(&cwq->lock);
-               should_stop = cwq->should_stop && list_empty(&cwq->worklist);
-               if (should_stop)
-                       cwq->thread = NULL;
-               spin_unlock_irq(&cwq->lock);
-       }
-
-       return should_stop;
-}
-
 static int worker_thread(void *__cwq)
 {
        struct cpu_workqueue_struct *cwq = __cwq;
@@ -302,14 +289,15 @@ static int worker_thread(void *__cwq)
 
        for (;;) {
                prepare_to_wait(&cwq->more_work, &wait, TASK_INTERRUPTIBLE);
-               if (!freezing(current) && !cwq->should_stop
-                   && list_empty(&cwq->worklist))
+               if (!freezing(current) &&
+                   !kthread_should_stop() &&
+                   list_empty(&cwq->worklist))
                        schedule();
                finish_wait(&cwq->more_work, &wait);
 
                try_to_freeze();
 
-               if (cwq_should_stop(cwq))
+               if (kthread_should_stop())
                        break;
 
                run_workqueue(cwq);
@@ -340,18 +328,21 @@ static void insert_wq_barrier(struct cpu_workqueue_struct *cwq,
        insert_work(cwq, &barr->work, tail);
 }
 
-static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
+static int flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
 {
+       int active;
+
        if (cwq->thread == current) {
                /*
                 * Probably keventd trying to flush its own queue. So simply run
                 * it by hand rather than deadlocking.
                 */
                run_workqueue(cwq);
+               active = 1;
        } else {
                struct wq_barrier barr;
-               int active = 0;
 
+               active = 0;
                spin_lock_irq(&cwq->lock);
                if (!list_empty(&cwq->worklist) || cwq->current_work != NULL) {
                        insert_wq_barrier(cwq, &barr, 1);
@@ -362,6 +353,8 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
                if (active)
                        wait_for_completion(&barr.done);
        }
+
+       return active;
 }
 
 /**
@@ -674,7 +667,6 @@ static int create_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
                return PTR_ERR(p);
 
        cwq->thread = p;
-       cwq->should_stop = 0;
 
        return 0;
 }
@@ -740,29 +732,27 @@ EXPORT_SYMBOL_GPL(__create_workqueue);
 
 static void cleanup_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu)
 {
-       struct wq_barrier barr;
-       int alive = 0;
-
-       spin_lock_irq(&cwq->lock);
-       if (cwq->thread != NULL) {
-               insert_wq_barrier(cwq, &barr, 1);
-               cwq->should_stop = 1;
-               alive = 1;
-       }
-       spin_unlock_irq(&cwq->lock);
+       /*
+        * Our caller is either destroy_workqueue() or CPU_DEAD,
+        * workqueue_mutex protects cwq->thread
+        */
+       if (cwq->thread == NULL)
+               return;
 
-       if (alive) {
-               wait_for_completion(&barr.done);
+       /*
+        * If the caller is CPU_DEAD the single flush_cpu_workqueue()
+        * is not enough, a concurrent flush_workqueue() can insert a
+        * barrier after us.
+        * When ->worklist becomes empty it is safe to exit because no
+        * more work_structs can be queued on this cwq: flush_workqueue
+        * checks list_empty(), and a "normal" queue_work() can't use
+        * a dead CPU.
+        */
+       while (flush_cpu_workqueue(cwq))
+               ;
 
-               while (unlikely(cwq->thread != NULL))
-                       cpu_relax();
-               /*
-                * Wait until cwq->thread unlocks cwq->lock,
-                * it won't touch *cwq after that.
-                */
-               smp_rmb();
-               spin_unlock_wait(&cwq->lock);
-       }
+       kthread_stop(cwq->thread);
+       cwq->thread = NULL;
 }
 
 /**
index fbc5c62..1ba77ca 100644 (file)
@@ -378,14 +378,13 @@ config FORCED_INLINING
 config RCU_TORTURE_TEST
        tristate "torture tests for RCU"
        depends on DEBUG_KERNEL
+       depends on m
        default n
        help
          This option provides a kernel module that runs torture tests
          on the RCU infrastructure.  The kernel module may be built
          after the fact on the running kernel to be tested, if desired.
 
-         Say Y here if you want RCU torture tests to start automatically
-         at boot time (you probably don't).
          Say M if you want the RCU torture tests to build as a module.
          Say N if you are unsure.
 
index 8b000d6..d897062 100644 (file)
@@ -136,6 +136,11 @@ static unsigned long __meminitdata dma_reserve;
 #endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
 #endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
+#if MAX_NUMNODES > 1
+int nr_node_ids __read_mostly = MAX_NUMNODES;
+EXPORT_SYMBOL(nr_node_ids);
+#endif
+
 #ifdef CONFIG_DEBUG_VM
 static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
 {
@@ -669,26 +674,6 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
        return i;
 }
 
-#if MAX_NUMNODES > 1
-int nr_node_ids __read_mostly = MAX_NUMNODES;
-EXPORT_SYMBOL(nr_node_ids);
-
-/*
- * Figure out the number of possible node ids.
- */
-static void __init setup_nr_node_ids(void)
-{
-       unsigned int node;
-       unsigned int highest = 0;
-
-       for_each_node_mask(node, node_possible_map)
-               highest = node;
-       nr_node_ids = highest + 1;
-}
-#else
-static void __init setup_nr_node_ids(void) {}
-#endif
-
 #ifdef CONFIG_NUMA
 /*
  * Called from the vmstat counter updater to drain pagesets of this
@@ -2733,6 +2718,26 @@ void __meminit free_area_init_node(int nid, struct pglist_data *pgdat,
 }
 
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+
+#if MAX_NUMNODES > 1
+/*
+ * Figure out the number of possible node ids.
+ */
+static void __init setup_nr_node_ids(void)
+{
+       unsigned int node;
+       unsigned int highest = 0;
+
+       for_each_node_mask(node, node_possible_map)
+               highest = node;
+       nr_node_ids = highest + 1;
+}
+#else
+static inline void setup_nr_node_ids(void)
+{
+}
+#endif
+
 /**
  * add_active_range - Register a range of PFNs backed by physical memory
  * @nid: The node ID the range resides on
index 98801d4..3e5aefc 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -939,7 +939,7 @@ static void kmem_cache_open_debug_check(struct kmem_cache *s)
         * Debugging or ctor may create a need to move the free
         * pointer. Fail if this happens.
         */
-       if (s->size >= 65535 * sizeof(void *)) {
+       if (s->objsize >= 65535 * sizeof(void *)) {
                BUG_ON(s->flags & (SLAB_RED_ZONE | SLAB_POISON |
                                SLAB_STORE_USER | SLAB_DESTROY_BY_RCU));
                BUG_ON(s->ctor);
@@ -1917,7 +1917,6 @@ static int calculate_sizes(struct kmem_cache *s)
         */
        s->inuse = size;
 
-#ifdef CONFIG_SLUB_DEBUG
        if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) ||
                s->ctor)) {
                /*
@@ -1932,6 +1931,7 @@ static int calculate_sizes(struct kmem_cache *s)
                size += sizeof(void *);
        }
 
+#ifdef CONFIG_SLUB_DEBUG
        if (flags & SLAB_STORE_USER)
                /*
                 * Need to store information about allocs and frees after