]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Nov 2008 17:17:59 +0000 (09:17 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Nov 2008 17:17:59 +0000 (09:17 -0800)
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  x86, xen: fix use of pgd_page now that it really does return a page

195 files changed:
Documentation/cciss.txt
Documentation/email-clients.txt
Documentation/filesystems/vfat.txt
Documentation/io-mapping.txt [new file with mode: 0644]
Documentation/kernel-parameters.txt
MAINTAINERS
arch/arm/include/asm/memory.h
arch/arm/include/asm/system.h
arch/arm/kernel/elf.c
arch/arm/kernel/module.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mm/cache-xsc3l2.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-v7.S
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/include/mach/entry-macro.S
arch/arm/plat-omap/include/mach/irqs.h
arch/powerpc/platforms/cell/ras.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/x86/Kconfig
arch/x86/include/asm/fixmap.h
arch/x86/include/asm/fixmap_32.h
arch/x86/include/asm/highmem.h
arch/x86/include/asm/topology.h
arch/x86/mm/Makefile
arch/x86/mm/init_32.c
arch/x86/mm/iomap_32.c [new file with mode: 0644]
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
block/blk-core.c
block/blk-merge.c
block/blk-timeout.c
block/elevator.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/sata_nv.c
drivers/ata/sata_promise.c
drivers/ata/sata_via.c
drivers/block/cciss.c
drivers/block/cpqarray.c
drivers/char/vt.c
drivers/firewire/fw-device.c
drivers/firewire/fw-ohci.c
drivers/firewire/fw-sbp2.c
drivers/firmware/dmi_scan.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/hwmon/applesmc.c
drivers/ieee1394/dv1394.c
drivers/ieee1394/hosts.c
drivers/ieee1394/nodemgr.c
drivers/ieee1394/raw1394.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/raid10.c
drivers/message/fusion/mptlan.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/jedec_probe.c
drivers/mtd/onenand/omap2.c
drivers/net/Kconfig
drivers/net/atl1e/atl1e.h
drivers/net/bnx2x_init.h
drivers/net/bnx2x_main.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/mv643xx_eth.c
drivers/net/niu.c
drivers/net/smc911x.c
drivers/net/smc91x.c
drivers/net/ucc_geth_ethtool.c
drivers/net/wireless/ath5k/base.c
drivers/net/wireless/ath5k/desc.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/pnp/interface.c
drivers/ps3/ps3-lpm.c
drivers/rtc/interface.c
drivers/rtc/rtc-cmos.c
drivers/sbus/char/jsflash.c
drivers/serial/atmel_serial.c
drivers/staging/echo/echo.c
drivers/staging/me4000/me4000.c
drivers/video/Kconfig
drivers/video/Makefile
drivers/video/fbmem.c
drivers/video/mb862xx/Makefile [new file with mode: 0644]
drivers/video/mb862xx/mb862xx_reg.h [new file with mode: 0644]
drivers/video/mb862xx/mb862xxfb.c [new file with mode: 0644]
drivers/video/mb862xx/mb862xxfb.h [new file with mode: 0644]
drivers/watchdog/Kconfig
drivers/watchdog/at91sam9_wdt.c
drivers/xen/balloon.c
fs/Makefile
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/block_dev.c
fs/cifs/CHANGES
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/transport.c
fs/ext3/super.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/fat/Makefile
fs/fat/cache.c
fs/fat/dir.c
fs/fat/fat.h [new file with mode: 0644]
fs/fat/fatent.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
fs/fat/namei_msdos.c [moved from fs/msdos/namei.c with 97% similarity]
fs/fat/namei_vfat.c [moved from fs/vfat/namei.c with 89% similarity]
fs/jbd/checkpoint.c
fs/jbd2/checkpoint.c
fs/jbd2/journal.c
fs/jffs2/background.c
fs/jffs2/compr_lzo.c
fs/jffs2/nodemgmt.c
fs/msdos/Makefile [deleted file]
fs/proc/uptime.c
fs/vfat/Makefile [deleted file]
include/asm-x86/iomap.h [new file with mode: 0644]
include/drm/i915_drm.h
include/linux/bio.h
include/linux/hrtimer.h
include/linux/if_vlan.h
include/linux/io-mapping.h [new file with mode: 0644]
include/linux/libata.h
include/linux/msdos_fs.h
include/linux/mtd/cfi.h
include/linux/sched.h
include/linux/timer.h
include/linux/topology.h
include/net/scm.h
kernel/cgroup.c
kernel/sched.c
kernel/sched_fair.c
kernel/sched_features.h
kernel/smp.c
kernel/timer.c
kernel/trace/Kconfig
kernel/trace/ring_buffer.c
kernel/trace/trace.c
mm/hugetlb.c
mm/internal.h
mm/mempolicy.c
mm/migrate.c
mm/oom_kill.c
mm/page_alloc.c
mm/page_isolation.c
mm/sparse-vmemmap.c
mm/vmalloc.c
net/8021q/vlan_core.c
net/9p/client.c
net/9p/trans_rdma.c
net/core/dev.c
net/core/scm.c
net/ipv4/tcp.c
net/ipv4/xfrm4_state.c
net/ipv6/addrconf.c
net/ipv6/udp.c
net/ipv6/xfrm6_state.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_proto.c
net/rfkill/rfkill.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c
sound/aoa/soundbus/core.c
sound/core/rawmidi.c
sound/drivers/ml403-ac97cr.c
sound/drivers/pcsp/pcsp_input.c
sound/isa/ad1848/ad1848.c
sound/isa/adlib.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/sb/sb8.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/soc-core.c

index 8244c6442faa4d24ce9980c586be316629d54633..89698e8df7d46deb7e2b5332dd8199606073b15c 100644 (file)
@@ -21,11 +21,14 @@ This driver is known to work with the following cards:
        * SA E200
        * SA E200i
        * SA E500
+       * SA P700m
        * SA P212
        * SA P410
        * SA P410i
        * SA P411
        * SA P812
+       * SA P712m
+       * SA P711m
 
 Detecting drive failures:
 -------------------------
index 2ebb94d6ed8e547d5cb84cdc6feeba126388baf3..a618efab7b156658be70b29c1a6a9b9c4093e0f5 100644 (file)
@@ -213,4 +213,29 @@ TkRat (GUI)
 
 Works.  Use "Insert file..." or external editor.
 
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Gmail (Web GUI)
+
+If you just have to use Gmail to send patches, it CAN be made to work.  It
+requires a bit of external help, though.
+
+The first problem is that Gmail converts tabs to spaces.  This will
+totally break your patches.  To prevent this, you have to use a different
+editor.  There is a firefox extension called "ViewSourceWith"
+(https://addons.mozilla.org/en-US/firefox/addon/394) which allows you to
+edit any text box in the editor of your choice.  Configure it to launch
+your favorite editor.  When you want to send a patch, use this technique.
+Once you have crafted your messsage + patch, save and exit the editor,
+which should reload the Gmail edit box.  GMAIL WILL PRESERVE THE TABS.
+Hoorah.  Apparently you can cut-n-paste literal tabs, but Gmail will
+convert those to spaces upon sending!
+
+The second problem is that Gmail converts tabs to spaces on replies.  If
+you reply to a patch, don't expect to be able to apply it as a patch.
+
+The last problem is that Gmail will base64-encode any message that has a
+non-ASCII character.  That includes things like European names.  Be aware.
+
+Gmail is not convenient for lkml patches, but CAN be made to work.
+
                                 ###
index bbac4f1d90567c3f7ea0f46a869c091160390076..3a5ddc96901a665e3801d8ebf80c817e2efb5fc2 100644 (file)
@@ -8,6 +8,12 @@ if you want to format from within Linux.
 
 VFAT MOUNT OPTIONS
 ----------------------------------------------------------------------
+uid=###       -- Set the owner of all files on this filesystem.
+                The default is the uid of current process.
+
+gid=###       -- Set the group of all files on this filesystem.
+                The default is the gid of current process.
+
 umask=###     -- The permission mask (for files and directories, see umask(1)).
                  The default is the umask of current process.
 
@@ -36,7 +42,7 @@ codepage=###  -- Sets the codepage number for converting to shortname
                 characters on FAT filesystem.
                 By default, FAT_DEFAULT_CODEPAGE setting is used.
 
-iocharset=name -- Character set to use for converting between the
+iocharset=<name> -- Character set to use for converting between the
                 encoding is used for user visible filename and 16 bit
                 Unicode characters. Long filenames are stored on disk
                 in Unicode format, but Unix for the most part doesn't
@@ -86,6 +92,8 @@ check=s|r|n   -- Case sensitivity checking setting.
                  r: relaxed, case insensitive
                  n: normal, default setting, currently case insensitive
 
+nocase        -- This was deprecated for vfat. Use shortname=win95 instead.
+
 shortname=lower|win95|winnt|mixed
              -- Shortname display/create setting.
                 lower: convert to lowercase for display,
@@ -99,11 +107,31 @@ shortname=lower|win95|winnt|mixed
 tz=UTC        -- Interpret timestamps as UTC rather than local time.
                  This option disables the conversion of timestamps
                  between local time (as used by Windows on FAT) and UTC
-                 (which Linux uses internally).  This is particuluarly
+                 (which Linux uses internally).  This is particularly
                  useful when mounting devices (like digital cameras)
                  that are set to UTC in order to avoid the pitfalls of
                  local time.
 
+showexec      -- If set, the execute permission bits of the file will be
+                allowed only if the extension part of the name is .EXE,
+                .COM, or .BAT. Not set by default.
+
+debug         -- Can be set, but unused by the current implementation.
+
+sys_immutable -- If set, ATTR_SYS attribute on FAT is handled as
+                IMMUTABLE flag on Linux. Not set by default.
+
+flush         -- If set, the filesystem will try to flush to disk more
+                early than normal. Not set by default.
+
+rodir        -- FAT has the ATTR_RO (read-only) attribute. But on Windows,
+                the ATTR_RO of the directory will be just ignored actually,
+                and is used by only applications as flag. E.g. it's setted
+                for the customized folder.
+
+                If you want to use ATTR_RO as read-only flag even for
+                the directory, set this option.
+
 <bool>: 0,1,yes,no,true,false
 
 TODO
diff --git a/Documentation/io-mapping.txt b/Documentation/io-mapping.txt
new file mode 100644 (file)
index 0000000..473e43b
--- /dev/null
@@ -0,0 +1,82 @@
+The io_mapping functions in linux/io-mapping.h provide an abstraction for
+efficiently mapping small regions of an I/O device to the CPU. The initial
+usage is to support the large graphics aperture on 32-bit processors where
+ioremap_wc cannot be used to statically map the entire aperture to the CPU
+as it would consume too much of the kernel address space.
+
+A mapping object is created during driver initialization using
+
+       struct io_mapping *io_mapping_create_wc(unsigned long base,
+                                               unsigned long size)
+
+               'base' is the bus address of the region to be made
+               mappable, while 'size' indicates how large a mapping region to
+               enable. Both are in bytes.
+
+               This _wc variant provides a mapping which may only be used
+               with the io_mapping_map_atomic_wc or io_mapping_map_wc.
+
+With this mapping object, individual pages can be mapped either atomically
+or not, depending on the necessary scheduling environment. Of course, atomic
+maps are more efficient:
+
+       void *io_mapping_map_atomic_wc(struct io_mapping *mapping,
+                                      unsigned long offset)
+
+               'offset' is the offset within the defined mapping region.
+               Accessing addresses beyond the region specified in the
+               creation function yields undefined results. Using an offset
+               which is not page aligned yields an undefined result. The
+               return value points to a single page in CPU address space.
+
+               This _wc variant returns a write-combining map to the
+               page and may only be used with mappings created by
+               io_mapping_create_wc
+
+               Note that the task may not sleep while holding this page
+               mapped.
+
+       void io_mapping_unmap_atomic(void *vaddr)
+
+               'vaddr' must be the the value returned by the last
+               io_mapping_map_atomic_wc call. This unmaps the specified
+               page and allows the task to sleep once again.
+
+If you need to sleep while holding the lock, you can use the non-atomic
+variant, although they may be significantly slower.
+
+       void *io_mapping_map_wc(struct io_mapping *mapping,
+                               unsigned long offset)
+
+               This works like io_mapping_map_atomic_wc except it allows
+               the task to sleep while holding the page mapped.
+
+       void io_mapping_unmap(void *vaddr)
+
+               This works like io_mapping_unmap_atomic, except it is used
+               for pages mapped with io_mapping_map_wc.
+
+At driver close time, the io_mapping object must be freed:
+
+       void io_mapping_free(struct io_mapping *mapping)
+
+Current Implementation:
+
+The initial implementation of these functions uses existing mapping
+mechanisms and so provides only an abstraction layer and no new
+functionality.
+
+On 64-bit processors, io_mapping_create_wc calls ioremap_wc for the whole
+range, creating a permanent kernel-visible mapping to the resource. The
+map_atomic and map functions add the requested offset to the base of the
+virtual address returned by ioremap_wc.
+
+On 32-bit processors with HIGHMEM defined, io_mapping_map_atomic_wc uses
+kmap_atomic_pfn to map the specified page in an atomic fashion;
+kmap_atomic_pfn isn't really supposed to be used with device pages, but it
+provides an efficient mapping for this usage.
+
+On 32-bit processors without HIGHMEM defined, io_mapping_map_atomic_wc and
+io_mapping_map_wc both use ioremap_wc, a terribly inefficient function which
+performs an IPI to inform all processors about the new mapping. This results
+in a significant performance penalty.
index de4de3e7bc1bdfed1ad514b742d3ffa30cfabaaf..c86c074597129a5b4434b0e35c432a0a28636b11 100644 (file)
@@ -995,13 +995,15 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format:
                        <cpu number>,...,<cpu number>
                        or
-                       <cpu number>-<cpu number>  (must be a positive range in ascending order)
+                       <cpu number>-<cpu number>
+                       (must be a positive range in ascending order)
                        or a mixture
                        <cpu number>,...,<cpu number>-<cpu number>
+
                        This option can be used to specify one or more CPUs
                        to isolate from the general SMP balancing and scheduling
-                       algorithms. The only way to move a process onto or off
-                       an "isolated" CPU is via the CPU affinity syscalls.
+                       algorithms. You can move a process onto or off an
+                       "isolated" CPU via the CPU affinity syscalls or cpuset.
                        <cpu number> begins at 0 and the maximum value is
                        "number of CPUs in system - 1".
 
index d643e862b8e49af7ddc15243f310703278f199e3..7e6a17e1de097d74c57766192e71ed35e2fe9f1b 100644 (file)
@@ -721,7 +721,7 @@ W:  http://sourceforge.net/projects/acpi4asus
 W:     http://xf.iksaif.net/acpi4asus
 S:     Maintained
 
-ASYNCHRONOUS TRANSFERS/TRANSFORMS API
+ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
 P:     Dan Williams
 M:     dan.j.williams@intel.com
 P:     Maciej Sosnowski
index 809ff9ab853a5979c0da8fc35a30c6208533d07b..77764301844b52946996f4a3287185c0fc349e05 100644 (file)
  * The module space lives between the addresses given by TASK_SIZE
  * and PAGE_OFFSET - it must be within 32MB of the kernel text.
  */
-#define MODULE_END             (PAGE_OFFSET)
-#define MODULE_START           (MODULE_END - 16*1048576)
+#define MODULES_END            (PAGE_OFFSET)
+#define MODULES_VADDR          (MODULES_END - 16*1048576)
 
-#if TASK_SIZE > MODULE_START
+#if TASK_SIZE > MODULES_VADDR
 #error Top of user space clashes with start of module space
 #endif
 
@@ -56,7 +56,7 @@
  * Since we use sections to map it, this macro replaces the physical address
  * with its virtual address while keeping offset from the base section.
  */
-#define XIP_VIRT_ADDR(physaddr)  (MODULE_START + ((physaddr) & 0x000fffff))
+#define XIP_VIRT_ADDR(physaddr)  (MODULES_VADDR + ((physaddr) & 0x000fffff))
 
 /*
  * Allow 16MB-aligned ioremap pages
@@ -94,8 +94,8 @@
 /*
  * The module can be at any place in ram in nommu mode.
  */
-#define MODULE_END             (END_MEM)
-#define MODULE_START           (PHYS_OFFSET)
+#define MODULES_END            (END_MEM)
+#define MODULES_VADDR          (PHYS_OFFSET)
 
 #endif /* !CONFIG_MMU */
 
index 7aad78420f18df6b9e375d2023a8ccb998d528e0..568020b34e3e9b1c5883afb935228d2d53d58a40 100644 (file)
 #define CR_U   (1 << 22)       /* Unaligned access operation           */
 #define CR_XP  (1 << 23)       /* Extended page tables                 */
 #define CR_VE  (1 << 24)       /* Vectored interrupts                  */
+#define CR_EE  (1 << 25)       /* Exception (Big) Endian               */
+#define CR_TRE (1 << 28)       /* TEX remap enable                     */
+#define CR_AFE (1 << 29)       /* Access flag enable                   */
+#define CR_TE  (1 << 30)       /* Thumb exception enable               */
 
 /*
  * This is used to ensure the compiler did actually allocate the register we
index 513f332f040d6f6227e1f4d7a551c4729e843a4c..84849098c8e8139da19ae6b8d8fecd089539ee30 100644 (file)
@@ -21,12 +21,16 @@ int elf_check_arch(const struct elf32_hdr *x)
 
        eflags = x->e_flags;
        if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
+               unsigned int flt_fmt;
+
                /* APCS26 is only allowed if the CPU supports it */
                if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT))
                        return 0;
 
+               flt_fmt = eflags & (EF_ARM_VFP_FLOAT | EF_ARM_SOFT_FLOAT);
+
                /* VFP requires the supporting code */
-               if ((eflags & EF_ARM_VFP_FLOAT) && !(elf_hwcap & HWCAP_VFP))
+               if (flt_fmt == EF_ARM_VFP_FLOAT && !(elf_hwcap & HWCAP_VFP))
                        return 0;
        }
        return 1;
index 9203ba7d58eeaf7ce2ce05d8975c5bc9d3bd0793..b8d965dcd6fdbfaec4172dc541030e15b5b653c9 100644 (file)
 /*
  * The XIP kernel text is mapped in the module area for modules and
  * some other stuff to work without any indirect relocations.
- * MODULE_START is redefined here and not in asm/memory.h to avoid
+ * MODULES_VADDR is redefined here and not in asm/memory.h to avoid
  * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off.
  */
 extern void _etext;
-#undef MODULE_START
-#define MODULE_START   (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK)
+#undef MODULES_VADDR
+#define MODULES_VADDR  (((unsigned long)&_etext + ~PGDIR_MASK) & PGDIR_MASK)
 #endif
 
 #ifdef CONFIG_MMU
@@ -43,7 +43,7 @@ void *module_alloc(unsigned long size)
        if (!size)
                return NULL;
 
-       area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
+       area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
        if (!area)
                return NULL;
 
index 763bdbeaf68182c87389d36a3ed4a53db09e59ed..2249049c1d5a3f4020528fa7a4350532fac34c13 100644 (file)
@@ -429,18 +429,16 @@ void __init gpmc_init(void)
        gpmc_l3_clk = clk_get(NULL, ck);
        if (IS_ERR(gpmc_l3_clk)) {
                printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
-               return -ENODEV;
+               BUG();
        }
 
        gpmc_base = ioremap(l, SZ_4K);
        if (!gpmc_base) {
                clk_put(gpmc_l3_clk);
                printk(KERN_ERR "Could not get GPMC register memory\n");
-               return -ENOMEM;
+               BUG();
        }
 
-       BUG_ON(IS_ERR(gpmc_l3_clk));
-
        l = gpmc_read_reg(GPMC_REVISION);
        printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
        /* Set smart idle mode and automatic L3 clock gating */
index 10b1bae1a258f782f0aaf67e128f8a8aef514672..464de893a988033180ac9bb7e25c1a53daa6f149 100644 (file)
@@ -98,7 +98,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
        /*
         * Clean and invalidate partial last cache line.
         */
-       if (end & (CACHE_LINE_SIZE - 1)) {
+       if (start < end && (end & (CACHE_LINE_SIZE - 1))) {
                xsc3_l2_clean_pa(end & ~(CACHE_LINE_SIZE - 1));
                xsc3_l2_inv_pa(end & ~(CACHE_LINE_SIZE - 1));
                end &= ~(CACHE_LINE_SIZE - 1);
@@ -107,7 +107,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
        /*
         * Invalidate all full cache lines between 'start' and 'end'.
         */
-       while (start != end) {
+       while (start < end) {
                xsc3_l2_inv_pa(start);
                start += CACHE_LINE_SIZE;
        }
index 8ba754064559305668dcf96aa9ca974db32ac7db..e63db11f16a808fc0de3b73ea841ad2797ca597b 100644 (file)
@@ -180,20 +180,20 @@ void adjust_cr(unsigned long mask, unsigned long set)
 #endif
 
 #define PROT_PTE_DEVICE                L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE
-#define PROT_SECT_DEVICE       PMD_TYPE_SECT|PMD_SECT_XN|PMD_SECT_AP_WRITE
+#define PROT_SECT_DEVICE       PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
 static struct mem_type mem_types[] = {
        [MT_DEVICE] = {           /* Strongly ordered / ARMv6 shared device */
                .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
                                  L_PTE_SHARED,
                .prot_l1        = PMD_TYPE_TABLE,
-               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_UNCACHED,
+               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_S,
                .domain         = DOMAIN_IO,
        },
        [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */
                .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED,
                .prot_l1        = PMD_TYPE_TABLE,
-               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_TEX(2),
+               .prot_sect      = PROT_SECT_DEVICE,
                .domain         = DOMAIN_IO,
        },
        [MT_DEVICE_CACHED] = {    /* ioremap_cached */
@@ -205,7 +205,7 @@ static struct mem_type mem_types[] = {
        [MT_DEVICE_WC] = {      /* ioremap_wc */
                .prot_pte       = PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,
                .prot_l1        = PMD_TYPE_TABLE,
-               .prot_sect      = PROT_SECT_DEVICE | PMD_SECT_BUFFERABLE,
+               .prot_sect      = PROT_SECT_DEVICE,
                .domain         = DOMAIN_IO,
        },
        [MT_CACHECLEAN] = {
@@ -273,22 +273,23 @@ static void __init build_mem_type_table(void)
 #endif
 
        /*
-        * On non-Xscale3 ARMv5-and-older systems, use CB=01
-        * (Uncached/Buffered) for ioremap_wc() mappings.  On XScale3
-        * and ARMv6+, use TEXCB=00100 mappings (Inner/Outer Uncacheable
-        * in xsc3 parlance, Uncached Normal in ARMv6 parlance).
+        * Strip out features not present on earlier architectures.
+        * Pre-ARMv5 CPUs don't have TEX bits.  Pre-ARMv6 CPUs or those
+        * without extended page tables don't have the 'Shared' bit.
         */
-       if (cpu_is_xsc3() || cpu_arch >= CPU_ARCH_ARMv6) {
-               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
-               mem_types[MT_DEVICE_WC].prot_sect &= ~PMD_SECT_BUFFERABLE;
-       }
+       if (cpu_arch < CPU_ARCH_ARMv5)
+               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+                       mem_types[i].prot_sect &= ~PMD_SECT_TEX(7);
+       if ((cpu_arch < CPU_ARCH_ARMv6 || !(cr & CR_XP)) && !cpu_is_xsc3())
+               for (i = 0; i < ARRAY_SIZE(mem_types); i++)
+                       mem_types[i].prot_sect &= ~PMD_SECT_S;
 
        /*
-        * ARMv5 and lower, bit 4 must be set for page tables.
-        * (was: cache "update-able on write" bit on ARM610)
-        * However, Xscale cores require this bit to be cleared.
+        * ARMv5 and lower, bit 4 must be set for page tables (was: cache
+        * "update-able on write" bit on ARM610).  However, Xscale and
+        * Xscale3 require this bit to be cleared.
         */
-       if (cpu_is_xscale()) {
+       if (cpu_is_xscale() || cpu_is_xsc3()) {
                for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
                        mem_types[i].prot_sect &= ~PMD_BIT4;
                        mem_types[i].prot_l1 &= ~PMD_BIT4;
@@ -302,6 +303,64 @@ static void __init build_mem_type_table(void)
                }
        }
 
+       /*
+        * Mark the device areas according to the CPU/architecture.
+        */
+       if (cpu_is_xsc3() || (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP))) {
+               if (!cpu_is_xsc3()) {
+                       /*
+                        * Mark device regions on ARMv6+ as execute-never
+                        * to prevent speculative instruction fetches.
+                        */
+                       mem_types[MT_DEVICE].prot_sect |= PMD_SECT_XN;
+                       mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN;
+                       mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN;
+                       mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN;
+               }
+               if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
+                       /*
+                        * For ARMv7 with TEX remapping,
+                        * - shared device is SXCB=1100
+                        * - nonshared device is SXCB=0100
+                        * - write combine device mem is SXCB=0001
+                        * (Uncached Normal memory)
+                        */
+                       mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1);
+                       mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(1);
+                       mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
+               } else if (cpu_is_xsc3()) {
+                       /*
+                        * For Xscale3,
+                        * - shared device is TEXCB=00101
+                        * - nonshared device is TEXCB=01000
+                        * - write combine device mem is TEXCB=00100
+                        * (Inner/Outer Uncacheable in xsc3 parlance)
+                        */
+                       mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1) | PMD_SECT_BUFFERED;
+                       mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2);
+                       mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
+               } else {
+                       /*
+                        * For ARMv6 and ARMv7 without TEX remapping,
+                        * - shared device is TEXCB=00001
+                        * - nonshared device is TEXCB=01000
+                        * - write combine device mem is TEXCB=00100
+                        * (Uncached Normal in ARMv6 parlance).
+                        */
+                       mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
+                       mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2);
+                       mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
+               }
+       } else {
+               /*
+                * On others, write combining is "Uncached/Buffered"
+                */
+               mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
+       }
+
+       /*
+        * Now deal with the memory-type mappings
+        */
        cp = &cache_policies[cachepolicy];
        vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
 
@@ -317,12 +376,8 @@ static void __init build_mem_type_table(void)
         * Enable CPU-specific coherency if supported.
         * (Only available on XSC3 at the moment.)
         */
-       if (arch_is_coherent()) {
-               if (cpu_is_xsc3()) {
-                       mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-                       mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
-               }
-       }
+       if (arch_is_coherent() && cpu_is_xsc3())
+               mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
 
        /*
         * ARMv6 and above have extended page tables.
@@ -336,11 +391,6 @@ static void __init build_mem_type_table(void)
                mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
                mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 
-               /*
-                * Mark the device area as "shared device"
-                */
-               mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
-
 #ifdef CONFIG_SMP
                /*
                 * Mark memory with the "shared" attribute for SMP systems
@@ -360,9 +410,6 @@ static void __init build_mem_type_table(void)
        mem_types[MT_LOW_VECTORS].prot_pte |= vecs_pgprot;
        mem_types[MT_HIGH_VECTORS].prot_pte |= vecs_pgprot;
 
-       if (cpu_arch < CPU_ARCH_ARMv5)
-               mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
-
        pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
        pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
                                 L_PTE_DIRTY | L_PTE_WRITE |
@@ -654,7 +701,7 @@ static inline void prepare_page_table(struct meminfo *mi)
        /*
         * Clear out all the mappings below the kernel image.
         */
-       for (addr = 0; addr < MODULE_START; addr += PGDIR_SIZE)
+       for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
                pmd_clear(pmd_off_k(addr));
 
 #ifdef CONFIG_XIP_KERNEL
@@ -766,7 +813,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
         */
 #ifdef CONFIG_XIP_KERNEL
        map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
-       map.virtual = MODULE_START;
+       map.virtual = MODULES_VADDR;
        map.length = ((unsigned long)&_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK;
        map.type = MT_ROM;
        create_mapping(&map);
index 07f82db70945f7d3582dcd6c9f589ebcce648af9..4d3c0a73e7fb6aea1590f6f9c574521c847e91fe 100644 (file)
@@ -115,7 +115,7 @@ ENTRY(cpu_v7_set_pte_ext)
        orr     r3, r3, r2
        orr     r3, r3, #PTE_EXT_AP0 | 2
 
-       tst     r2, #1 << 4
+       tst     r1, #1 << 4
        orrne   r3, r3, #PTE_EXT_TEX(1)
 
        tst     r1, #L_PTE_WRITE
@@ -192,11 +192,11 @@ __v7_setup:
        mov     pc, lr                          @ return to head.S:__ret
 ENDPROC(__v7_setup)
 
-       /*
-        *         V X F   I D LR
-        * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM
-        * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced
-        *         0 110       0011 1.00 .111 1101 < we want
+       /*   AT
+        *  TFR   EV X F   I D LR
+        * .EEE ..EE PUI. .T.T 4RVI ZFRS BLDP WCAM
+        * rxxx rrxx xxx0 0101 xxxx xxxx x111 xxxx < forced
+        *    1    0 110       0011 1.00 .111 1101 < we want
         */
        .type   v7_crval, #object
 v7_crval:
index bf6a10c5fc4ffdfd5f9abb74bec8da1c1140e57e..be6aab9c68344ef8ac10424d23a7319aee0ab6fa 100644 (file)
@@ -428,23 +428,23 @@ static int clk_debugfs_register_one(struct clk *c)
        if (c->id != 0)
                sprintf(p, ":%d", c->id);
        d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
-       if (IS_ERR(d))
-               return PTR_ERR(d);
+       if (!d)
+               return -ENOMEM;
        c->dent = d;
 
        d = debugfs_create_u8("usecount", S_IRUGO, c->dent, (u8 *)&c->usecount);
-       if (IS_ERR(d)) {
-               err = PTR_ERR(d);
+       if (!d) {
+               err = -ENOMEM;
                goto err_out;
        }
        d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
-       if (IS_ERR(d)) {
-               err = PTR_ERR(d);
+       if (!d) {
+               err = -ENOMEM;
                goto err_out;
        }
        d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
-       if (IS_ERR(d)) {
-               err = PTR_ERR(d);
+       if (!d) {
+               err = -ENOMEM;
                goto err_out;
        }
        return 0;
@@ -483,8 +483,8 @@ static int __init clk_debugfs_init(void)
        int err;
 
        d = debugfs_create_dir("clock", NULL);
-       if (IS_ERR(d))
-               return PTR_ERR(d);
+       if (!d)
+               return -ENOMEM;
        clk_debugfs_root = d;
 
        list_for_each_entry(c, &clocks, node) {
index 030118ee204a655065e733508f1feee26c7aa3f2..2276f89671d83dafbce62954f58e41e8b3721fe4 100644 (file)
@@ -65,7 +65,8 @@
 #include <mach/omap34xx.h>
 #endif
 
-#define INTCPS_SIR_IRQ_OFFSET  0x0040          /* Active interrupt number */
+#define INTCPS_SIR_IRQ_OFFSET  0x0040          /* Active interrupt offset */
+#define        ACTIVEIRQ_MASK          0x7f            /* Active interrupt bits */
 
                .macro  disable_fiq
                .endm
@@ -88,6 +89,7 @@
                cmp     \irqnr, #0x0
 2222:
                ldrne   \irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
+               and     \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
 
                .endm
 
index a2929ac8c68733a6e4b606d5737a01a9fafb3fb8..bed5274c910a9e0713ae640c2b8e7fde29134148 100644 (file)
 
 /* External TWL4030 gpio interrupts are optional */
 #define TWL4030_GPIO_IRQ_BASE  TWL4030_PWR_IRQ_END
-#ifdef CONFIG_TWL4030_GPIO
+#ifdef CONFIG_GPIO_TWL4030
 #define TWL4030_GPIO_NR_IRQS   18
 #else
 #define        TWL4030_GPIO_NR_IRQS    0
index fdf088f2430e8ad4feb9d03dee0e16366e7d8fbc..7b4cefa2199b773b74fc274db1c3483145d2bbab 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kexec.h>
 #include <linux/crash_dump.h>
 
+#include <asm/kexec.h>
 #include <asm/reg.h>
 #include <asm/io.h>
 #include <asm/prom.h>
index 31481dc485de85f404f5adf07d558bc644f32742..7190493e9bdc5813f4a8c4321f25a0e66d129a89 100644 (file)
@@ -189,7 +189,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
 {
        struct pci_controller *phb;
        int primary;
-       struct pci_bus *b;
 
        primary = list_empty(&hose_list);
        phb = pcibios_alloc_controller(dn);
index 5d6aa4013dc7346c36fee96482fd3bb42b523456..4cf0ab13d187a943f88afc1d9761c739fee41008 100644 (file)
@@ -1894,6 +1894,10 @@ config SYSVIPC_COMPAT
 endmenu
 
 
+config HAVE_ATOMIC_IOMAP
+       def_bool y
+       depends on X86_32
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
index 8668a94f850e51e16f209e89f17f5e4b0d2afcf5..23696d44a0af85fb2d3bf407d8b44def4874bf81 100644 (file)
@@ -9,6 +9,10 @@
 
 extern int fixmaps_set;
 
+extern pte_t *kmap_pte;
+extern pgprot_t kmap_prot;
+extern pte_t *pkmap_page_table;
+
 void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
 void native_set_fixmap(enum fixed_addresses idx,
                       unsigned long phys, pgprot_t flags);
index 09f29ab5c139345f99596e294443c70e6b6086a6..c7115c1d721721d8929e998c9c4032e27ca399d2 100644 (file)
@@ -28,10 +28,8 @@ extern unsigned long __FIXADDR_TOP;
 #include <asm/acpi.h>
 #include <asm/apicdef.h>
 #include <asm/page.h>
-#ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
-#endif
 
 /*
  * Here we define all the compile-time 'special' virtual
@@ -75,10 +73,8 @@ enum fixed_addresses {
 #ifdef CONFIG_X86_CYCLONE_TIMER
        FIX_CYCLONE_TIMER, /*cyclone timer register*/
 #endif
-#ifdef CONFIG_HIGHMEM
        FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
        FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
-#endif
 #ifdef CONFIG_PCI_MMCONFIG
        FIX_PCIE_MCFG,
 #endif
index a3b3b7c3027ba43bf6c366a8442064afddeaf7f3..bf9276bea6602fca7bf2b93e6aa640a083e57f99 100644 (file)
 #include <asm/kmap_types.h>
 #include <asm/tlbflush.h>
 #include <asm/paravirt.h>
+#include <asm/fixmap.h>
 
 /* declarations for highmem.c */
 extern unsigned long highstart_pfn, highend_pfn;
 
-extern pte_t *kmap_pte;
-extern pgprot_t kmap_prot;
-extern pte_t *pkmap_page_table;
-
 /*
  * Right now we initialize only a single pte table. It can be extended
  * easily, subsequent pte tables have to be allocated in one physical
index 90ac7718469a5b416bfd90350b24ade716698925..4850e4b02b61b255c14db559feb136e80a2f32c9 100644 (file)
@@ -154,7 +154,7 @@ extern unsigned long node_remap_size[];
 
 #endif
 
-/* sched_domains SD_NODE_INIT for NUMAQ machines */
+/* sched_domains SD_NODE_INIT for NUMA machines */
 #define SD_NODE_INIT (struct sched_domain) {           \
        .min_interval           = 8,                    \
        .max_interval           = 32,                   \
@@ -169,8 +169,9 @@ extern unsigned long node_remap_size[];
        .flags                  = SD_LOAD_BALANCE       \
                                | SD_BALANCE_EXEC       \
                                | SD_BALANCE_FORK       \
-                               | SD_SERIALIZE          \
-                               | SD_WAKE_BALANCE,      \
+                               | SD_WAKE_AFFINE        \
+                               | SD_WAKE_BALANCE       \
+                               | SD_SERIALIZE,         \
        .last_balance           = jiffies,              \
        .balance_interval       = 1,                    \
 }
index 59f89b434b45fbb80df02bafe3f54122a8738b50..fea4565ff576b9f52f76d9286ece00ed52a4f141 100644 (file)
@@ -1,7 +1,7 @@
 obj-y  :=  init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
            pat.o pgtable.o gup.o
 
-obj-$(CONFIG_X86_32)           += pgtable_32.o
+obj-$(CONFIG_X86_32)           += pgtable_32.o iomap_32.o
 
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
 obj-$(CONFIG_X86_PTDUMP)       += dump_pagetables.o
index 8396868e82c5637772f8d9fe81129731f87d2e24..c483f424207938cc16ff3a2eb6b92eee5175e6b5 100644 (file)
@@ -334,7 +334,6 @@ int devmem_is_allowed(unsigned long pagenr)
        return 0;
 }
 
-#ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;
 pgprot_t kmap_prot;
 
@@ -357,6 +356,7 @@ static void __init kmap_init(void)
        kmap_prot = PAGE_KERNEL;
 }
 
+#ifdef CONFIG_HIGHMEM
 static void __init permanent_kmaps_init(pgd_t *pgd_base)
 {
        unsigned long vaddr;
@@ -436,7 +436,6 @@ static void __init set_highmem_pages_init(void)
 #endif /* !CONFIG_NUMA */
 
 #else
-# define kmap_init()                           do { } while (0)
 # define permanent_kmaps_init(pgd_base)                do { } while (0)
 # define set_highmem_pages_init()      do { } while (0)
 #endif /* CONFIG_HIGHMEM */
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c
new file mode 100644 (file)
index 0000000..d0151d8
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright Â© 2008 Ingo Molnar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <asm/iomap.h>
+#include <linux/module.h>
+
+/* Map 'pfn' using fixed map 'type' and protections 'prot'
+ */
+void *
+iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+{
+       enum fixed_addresses idx;
+       unsigned long vaddr;
+
+       pagefault_disable();
+
+       idx = type + KM_TYPE_NR*smp_processor_id();
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+       set_pte(kmap_pte-idx, pfn_pte(pfn, prot));
+       arch_flush_lazy_mmu_mode();
+
+       return (void*) vaddr;
+}
+EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
+
+void
+iounmap_atomic(void *kvaddr, enum km_type type)
+{
+       unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+       /*
+        * Force other mappings to Oops if they'll try to access this pte
+        * without first remap it.  Keeping stale mappings around is a bad idea
+        * also, in case the page changes cacheability attributes or becomes
+        * a protected page in a hypervisor.
+        */
+       if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+               kpte_clear_flush(kmap_pte-idx, vaddr);
+
+       arch_flush_lazy_mmu_mode();
+       pagefault_enable();
+}
+EXPORT_SYMBOL_GPL(iounmap_atomic);
index b61534c7a4c4d5894812c5bb97a89f29a0f72338..5e4686d70f629de22f81adc96b658ab06216be24 100644 (file)
@@ -863,15 +863,16 @@ static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned l
        if (PagePinned(virt_to_page(mm->pgd))) {
                SetPagePinned(page);
 
+               vm_unmap_aliases();
                if (!PageHighMem(page)) {
                        make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn)));
                        if (level == PT_PTE && USE_SPLIT_PTLOCKS)
                                pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn);
-               } else
+               } else {
                        /* make sure there are no stray mappings of
                           this page */
                        kmap_flush_unused();
-                       vm_unmap_aliases();
+               }
        }
 }
 
index 49697d86c6a5e1efc4b6cfe6f928d54663129286..688936044dc95cdac8d6ce79e3ee10f39e898178 100644 (file)
@@ -850,13 +850,16 @@ static int xen_pin_page(struct mm_struct *mm, struct page *page,
    read-only, and can be pinned. */
 static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd)
 {
+       vm_unmap_aliases();
+
        xen_mc_batch();
 
-       if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) {
-               /* re-enable interrupts for kmap_flush_unused */
+        if (xen_pgd_walk(mm, xen_pin_page, USER_LIMIT)) {
+               /* re-enable interrupts for flushing */
                xen_mc_issue(0);
+
                kmap_flush_unused();
-               vm_unmap_aliases();
+
                xen_mc_batch();
        }
 
index c3df30cfb3fc332d5a503677b5b383dcf2660ec2..10e8a64a5a5b1b213cbc2886755b22dedce76313 100644 (file)
@@ -1770,8 +1770,6 @@ static void end_that_request_last(struct request *req, int error)
 {
        struct gendisk *disk = req->rq_disk;
 
-       blk_delete_timer(req);
-
        if (blk_rq_tagged(req))
                blk_queue_end_tag(req->q, req);
 
@@ -1781,6 +1779,8 @@ static void end_that_request_last(struct request *req, int error)
        if (unlikely(laptop_mode) && blk_fs_request(req))
                laptop_io_completion();
 
+       blk_delete_timer(req);
+
        /*
         * Account IO completion.  bar_rq isn't accounted as a normal
         * IO on queueing nor completion.  Accounting the containing
index 8681cd6f9911427419b41b99f678e9eb623bbf5e..b92f5b0866b0972b80e5b7f69e1fae046608a90b 100644 (file)
@@ -222,27 +222,6 @@ new_segment:
 }
 EXPORT_SYMBOL(blk_rq_map_sg);
 
-static inline int ll_new_mergeable(struct request_queue *q,
-                                  struct request *req,
-                                  struct bio *bio)
-{
-       int nr_phys_segs = bio_phys_segments(q, bio);
-
-       if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
-               req->cmd_flags |= REQ_NOMERGE;
-               if (req == q->last_merge)
-                       q->last_merge = NULL;
-               return 0;
-       }
-
-       /*
-        * A hw segment is just getting larger, bump just the phys
-        * counter.
-        */
-       req->nr_phys_segments += nr_phys_segs;
-       return 1;
-}
-
 static inline int ll_new_hw_segment(struct request_queue *q,
                                    struct request *req,
                                    struct bio *bio)
index 972a63f848fbb8541a099ae80ecce660cbe826cf..69185ea9fae26d4f643b6e70e07a3cd2e2265100 100644 (file)
@@ -75,14 +75,7 @@ void blk_delete_timer(struct request *req)
 {
        struct request_queue *q = req->q;
 
-       /*
-        * Nothing to detach
-        */
-       if (!q->rq_timed_out_fn || !req->deadline)
-               return;
-
        list_del_init(&req->timeout_list);
-
        if (list_empty(&q->timeout_list))
                del_timer(&q->timeout);
 }
@@ -142,7 +135,7 @@ void blk_rq_timed_out_timer(unsigned long data)
        }
 
        if (next_set && !list_empty(&q->timeout_list))
-               mod_timer(&q->timeout, round_jiffies(next));
+               mod_timer(&q->timeout, round_jiffies_up(next));
 
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
@@ -198,17 +191,10 @@ void blk_add_timer(struct request *req)
 
        /*
         * If the timer isn't already pending or this timeout is earlier
-        * than an existing one, modify the timer. Round to next nearest
+        * than an existing one, modify the timer. Round up to next nearest
         * second.
         */
-       expiry = round_jiffies(req->deadline);
-
-       /*
-        * We use ->deadline == 0 to detect whether a timer was added or
-        * not, so just increase to next jiffy for that specific case
-        */
-       if (unlikely(!req->deadline))
-               req->deadline = 1;
+       expiry = round_jiffies_up(req->deadline);
 
        if (!timer_pending(&q->timeout) ||
            time_before(expiry, q->timeout.expires))
index 59173a69ebdf2d89a406216e6a1b63e910c0f7b6..9ac82dde99dddcd5434659f65a1e81c2a166b639 100644 (file)
@@ -773,12 +773,6 @@ struct request *elv_next_request(struct request_queue *q)
                         */
                        rq->cmd_flags |= REQ_STARTED;
                        blk_add_trace_rq(q, rq, BLK_TA_ISSUE);
-
-                       /*
-                        * We are now handing the request to the hardware,
-                        * add the timeout handler
-                        */
-                       blk_add_timer(rq);
                }
 
                if (!q->boundary_rq || q->boundary_rq == rq) {
@@ -850,6 +844,12 @@ void elv_dequeue_request(struct request_queue *q, struct request *rq)
         */
        if (blk_account_rq(rq))
                q->in_flight++;
+
+       /*
+        * We are now handing the request to the hardware, add the
+        * timeout handler.
+        */
+       blk_add_timer(rq);
 }
 EXPORT_SYMBOL(elv_dequeue_request);
 
index 82af7011f2ddd137e2a601ae95c704a4219ada9e..622350d9b2e3af3915b07ca03ccdd2de4bf00d47 100644 (file)
@@ -4024,6 +4024,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* Weird ATAPI devices */
        { "TORiSAN DVD-ROM DRD-N216", NULL,     ATA_HORKAGE_MAX_SEC_128 },
+       { "QUANTUM DAT    DAT72-000", NULL,     ATA_HORKAGE_ATAPI_MOD16_DMA },
 
        /* Devices we expect to fail diagnostics */
 
@@ -4444,7 +4445,8 @@ int atapi_check_dma(struct ata_queued_cmd *qc)
        /* Don't allow DMA if it isn't multiple of 16 bytes.  Quite a
         * few ATAPI devices choke on such DMA requests.
         */
-       if (unlikely(qc->nbytes & 15))
+       if (!(qc->dev->horkage & ATA_HORKAGE_ATAPI_MOD16_DMA) &&
+           unlikely(qc->nbytes & 15))
                return 1;
 
        if (ap->ops->check_atapi_dma)
@@ -5934,7 +5936,7 @@ static void ata_port_detach(struct ata_port *ap)
         * to us.  Restore SControl and disable all existing devices.
         */
        __ata_port_for_each_link(link, ap) {
-               sata_scr_write(link, SCR_CONTROL, link->saved_scontrol);
+               sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0);
                ata_link_for_each_dev(dev, link)
                        ata_dev_disable(dev);
        }
index bbb30d882f05afc510d972a2583250f5c169dc29..3fa75eac135de3627f3f5765c868ab2b7a6b907c 100644 (file)
@@ -190,7 +190,7 @@ static ssize_t ata_scsi_park_show(struct device *device,
        struct ata_port *ap;
        struct ata_link *link;
        struct ata_device *dev;
-       unsigned long flags;
+       unsigned long flags, now;
        unsigned int uninitialized_var(msecs);
        int rc = 0;
 
@@ -208,10 +208,11 @@ static ssize_t ata_scsi_park_show(struct device *device,
        }
 
        link = dev->link;
+       now = jiffies;
        if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS &&
            link->eh_context.unloaded_mask & (1 << dev->devno) &&
-           time_after(dev->unpark_deadline, jiffies))
-               msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies);
+           time_after(dev->unpark_deadline, now))
+               msecs = jiffies_to_msecs(dev->unpark_deadline - now);
        else
                msecs = 0;
 
index fae3841de0d8726468adc4b6a93202f0d4177ed7..6f1460614325fb61553ca457d6201eb1faacd493 100644 (file)
@@ -307,10 +307,10 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
 
 static void nv_nf2_freeze(struct ata_port *ap);
 static void nv_nf2_thaw(struct ata_port *ap);
+static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
+                           unsigned long deadline);
 static void nv_ck804_freeze(struct ata_port *ap);
 static void nv_ck804_thaw(struct ata_port *ap);
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
-                       unsigned long deadline);
 static int nv_adma_slave_config(struct scsi_device *sdev);
 static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
@@ -405,17 +405,8 @@ static struct scsi_host_template nv_swncq_sht = {
        .slave_configure        = nv_swncq_slave_config,
 };
 
-/* OSDL bz3352 reports that some nv controllers can't determine device
- * signature reliably and nv_hardreset is implemented to work around
- * the problem.  This was reported on nf3 and it's unclear whether any
- * other controllers are affected.  However, the workaround has been
- * applied to all variants and there isn't much to gain by trying to
- * find out exactly which ones are affected at this point especially
- * because NV has moved over to ahci for newer controllers.
- */
 static struct ata_port_operations nv_common_ops = {
        .inherits               = &ata_bmdma_port_ops,
-       .hardreset              = nv_hardreset,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
 };
@@ -429,12 +420,22 @@ static struct ata_port_operations nv_generic_ops = {
        .hardreset              = ATA_OP_NULL,
 };
 
+/* OSDL bz3352 reports that nf2/3 controllers can't determine device
+ * signature reliably.  Also, the following thread reports detection
+ * failure on cold boot with the standard debouncing timing.
+ *
+ * http://thread.gmane.org/gmane.linux.ide/34098
+ *
+ * Debounce with hotplug timing and request follow-up SRST.
+ */
 static struct ata_port_operations nv_nf2_ops = {
        .inherits               = &nv_common_ops,
        .freeze                 = nv_nf2_freeze,
        .thaw                   = nv_nf2_thaw,
+       .hardreset              = nv_nf2_hardreset,
 };
 
+/* CK804 finally gets hardreset right */
 static struct ata_port_operations nv_ck804_ops = {
        .inherits               = &nv_common_ops,
        .freeze                 = nv_ck804_freeze,
@@ -443,7 +444,7 @@ static struct ata_port_operations nv_ck804_ops = {
 };
 
 static struct ata_port_operations nv_adma_ops = {
-       .inherits               = &nv_common_ops,
+       .inherits               = &nv_ck804_ops,
 
        .check_atapi_dma        = nv_adma_check_atapi_dma,
        .sff_tf_read            = nv_adma_tf_read,
@@ -467,7 +468,7 @@ static struct ata_port_operations nv_adma_ops = {
 };
 
 static struct ata_port_operations nv_swncq_ops = {
-       .inherits               = &nv_common_ops,
+       .inherits               = &nv_generic_ops,
 
        .qc_defer               = ata_std_qc_defer,
        .qc_prep                = nv_swncq_qc_prep,
@@ -1553,6 +1554,17 @@ static void nv_nf2_thaw(struct ata_port *ap)
        iowrite8(mask, scr_addr + NV_INT_ENABLE);
 }
 
+static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class,
+                           unsigned long deadline)
+{
+       bool online;
+       int rc;
+
+       rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
+                                &online, NULL);
+       return online ? -EAGAIN : rc;
+}
+
 static void nv_ck804_freeze(struct ata_port *ap)
 {
        void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
@@ -1605,21 +1617,6 @@ static void nv_mcp55_thaw(struct ata_port *ap)
        ata_sff_thaw(ap);
 }
 
-static int nv_hardreset(struct ata_link *link, unsigned int *class,
-                       unsigned long deadline)
-{
-       int rc;
-
-       /* SATA hardreset fails to retrieve proper device signature on
-        * some controllers.  Request follow up SRST.  For more info,
-        * see http://bugzilla.kernel.org/show_bug.cgi?id=3352
-        */
-       rc = sata_sff_hardreset(link, class, deadline);
-       if (rc)
-               return rc;
-       return -EAGAIN;
-}
-
 static void nv_adma_error_handler(struct ata_port *ap)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
index 750d8cdc00cd1b495eb8c40b7af5e288f18163fe..ba9a2570a742c6fccfc5325cd116f9dcb055238a 100644 (file)
@@ -153,6 +153,10 @@ static void pdc_freeze(struct ata_port *ap);
 static void pdc_sata_freeze(struct ata_port *ap);
 static void pdc_thaw(struct ata_port *ap);
 static void pdc_sata_thaw(struct ata_port *ap);
+static int pdc_pata_softreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline);
+static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline);
 static void pdc_error_handler(struct ata_port *ap);
 static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
 static int pdc_pata_cable_detect(struct ata_port *ap);
@@ -186,6 +190,7 @@ static struct ata_port_operations pdc_sata_ops = {
        .scr_read               = pdc_sata_scr_read,
        .scr_write              = pdc_sata_scr_write,
        .port_start             = pdc_sata_port_start,
+       .hardreset              = pdc_sata_hardreset,
 };
 
 /* First-generation chips need a more restrictive ->check_atapi_dma op */
@@ -200,6 +205,7 @@ static struct ata_port_operations pdc_pata_ops = {
        .freeze                 = pdc_freeze,
        .thaw                   = pdc_thaw,
        .port_start             = pdc_common_port_start,
+       .softreset              = pdc_pata_softreset,
 };
 
 static const struct ata_port_info pdc_port_info[] = {
@@ -693,6 +699,20 @@ static void pdc_sata_thaw(struct ata_port *ap)
        readl(host_mmio + hotplug_offset); /* flush */
 }
 
+static int pdc_pata_softreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline)
+{
+       pdc_reset_port(link->ap);
+       return ata_sff_softreset(link, class, deadline);
+}
+
+static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline)
+{
+       pdc_reset_port(link->ap);
+       return sata_sff_hardreset(link, class, deadline);
+}
+
 static void pdc_error_handler(struct ata_port *ap)
 {
        if (!(ap->pflags & ATA_PFLAG_FROZEN))
index 62367fe4d5dc2f6e9cf6d77c327f64eb8407ce12..c18935f0bda215d5987c4324fa8374a4f3efa1e1 100644 (file)
@@ -602,8 +602,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                rc = vt8251_prepare_host(pdev, &host);
                break;
        default:
-               return -EINVAL;
+               rc = -EINVAL;
        }
+       if (rc)
+               return rc;
 
        svia_configure(pdev);
 
index 4023885353e095e75d179f7ed8f649cd1abbb5a2..12de1fdaa6c68b76479cdfed53140e7188207449 100644 (file)
@@ -96,6 +96,8 @@ static const struct pci_device_id cciss_pci_device_id[] = {
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3245},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3247},
        {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3249},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324A},
+       {PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324B},
        {PCI_VENDOR_ID_HP,     PCI_ANY_ID,      PCI_ANY_ID, PCI_ANY_ID,
                PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
        {0,}
@@ -133,6 +135,8 @@ static struct board_type products[] = {
        {0x3245103C, "Smart Array P410i", &SA5_access},
        {0x3247103C, "Smart Array P411", &SA5_access},
        {0x3249103C, "Smart Array P812", &SA5_access},
+       {0x324A103C, "Smart Array P712m", &SA5_access},
+       {0x324B103C, "Smart Array P711m", &SA5_access},
        {0xFFFF103C, "Unknown Smart Array", &SA5_access},
 };
 
@@ -1366,6 +1370,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
        disk->first_minor = drv_index << NWD_SHIFT;
        disk->fops = &cciss_fops;
        disk->private_data = &h->drv[drv_index];
+       disk->driverfs_dev = &h->pdev->dev;
 
        /* Set up queue information */
        blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
@@ -3404,7 +3409,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        int i;
        int j = 0;
        int rc;
-       int dac;
+       int dac, return_code;
+       InquiryData_struct *inq_buff = NULL;
 
        i = alloc_cciss_hba();
        if (i < 0)
@@ -3510,6 +3516,25 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        /* Turn the interrupts on so we can service requests */
        hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
+       /* Get the firmware version */
+       inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+       if (inq_buff == NULL) {
+               printk(KERN_ERR "cciss: out of memory\n");
+               goto clean4;
+       }
+
+       return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff,
+               sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD);
+       if (return_code == IO_OK) {
+               hba[i]->firm_ver[0] = inq_buff->data_byte[32];
+               hba[i]->firm_ver[1] = inq_buff->data_byte[33];
+               hba[i]->firm_ver[2] = inq_buff->data_byte[34];
+               hba[i]->firm_ver[3] = inq_buff->data_byte[35];
+       } else {         /* send command failed */
+               printk(KERN_WARNING "cciss: unable to determine firmware"
+                       " version of controller\n");
+       }
+
        cciss_procinit(i);
 
        hba[i]->cciss_max_sectors = 2048;
@@ -3520,6 +3545,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
        return 1;
 
 clean4:
+       kfree(inq_buff);
 #ifdef CONFIG_CISS_SCSI_TAPE
        kfree(hba[i]->scsi_rejects.complete);
 #endif
index 47d233c6d0b33879b83994c8d39757de940e82cd..5d39df14ed9032eef70f62f87ec21427f14ad6a1 100644 (file)
@@ -567,7 +567,12 @@ static int __init cpqarray_init(void)
                        num_cntlrs_reg++;
        }
 
-       return(num_cntlrs_reg);
+       if (num_cntlrs_reg)
+               return 0;
+       else {
+               pci_unregister_driver(&cpqarray_pci_driver);
+               return -ENODEV;
+       }
 }
 
 /* Function to find the first free pointer into our hba[] array */
index d8f83e26e4a4de09210646ea5733d719c42649b4..a5af6072e2b34760ade3cf63b879dd16f4015957 100644 (file)
@@ -1644,7 +1644,10 @@ static void reset_terminal(struct vc_data *vc, int do_clear)
        vc->vc_tab_stop[1]      =
        vc->vc_tab_stop[2]      =
        vc->vc_tab_stop[3]      =
-       vc->vc_tab_stop[4]      = 0x01010101;
+       vc->vc_tab_stop[4]      =
+       vc->vc_tab_stop[5]      =
+       vc->vc_tab_stop[6]      =
+       vc->vc_tab_stop[7]      = 0x01010101;
 
        vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
        vc->vc_bell_duration = DEFAULT_BELL_DURATION;
@@ -1935,7 +1938,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                                        vc->vc_tab_stop[1] =
                                        vc->vc_tab_stop[2] =
                                        vc->vc_tab_stop[3] =
-                                       vc->vc_tab_stop[4] = 0;
+                                       vc->vc_tab_stop[4] =
+                                       vc->vc_tab_stop[5] =
+                                       vc->vc_tab_stop[6] =
+                                       vc->vc_tab_stop[7] = 0;
                        }
                        return;
                case 'm':
index 3fccdd48410094a1bc99fe22e916d465d3ab191b..6b9be42c7b98f4ef8c99a1806f2b81ed8021885a 100644 (file)
@@ -587,8 +587,7 @@ static void create_units(struct fw_device *device)
                unit->device.bus = &fw_bus_type;
                unit->device.type = &fw_unit_type;
                unit->device.parent = &device->device;
-               snprintf(unit->device.bus_id, sizeof(unit->device.bus_id),
-                        "%s.%d", device->device.bus_id, i++);
+               dev_set_name(&unit->device, "%s.%d", dev_name(&device->device), i++);
 
                init_fw_attribute_group(&unit->device,
                                        fw_unit_attributes,
@@ -711,8 +710,7 @@ static void fw_device_init(struct work_struct *work)
        device->device.type = &fw_device_type;
        device->device.parent = device->card->device;
        device->device.devt = MKDEV(fw_cdev_major, minor);
-       snprintf(device->device.bus_id, sizeof(device->device.bus_id),
-                "fw%d", minor);
+       dev_set_name(&device->device, "fw%d", minor);
 
        init_fw_attribute_group(&device->device,
                                fw_device_attributes,
@@ -741,13 +739,13 @@ static void fw_device_init(struct work_struct *work)
                if (device->config_rom_retries)
                        fw_notify("created device %s: GUID %08x%08x, S%d00, "
                                  "%d config ROM retries\n",
-                                 device->device.bus_id,
+                                 dev_name(&device->device),
                                  device->config_rom[3], device->config_rom[4],
                                  1 << device->max_speed,
                                  device->config_rom_retries);
                else
                        fw_notify("created device %s: GUID %08x%08x, S%d00\n",
-                                 device->device.bus_id,
+                                 dev_name(&device->device),
                                  device->config_rom[3], device->config_rom[4],
                                  1 << device->max_speed);
                device->config_rom_retries = 0;
@@ -883,12 +881,12 @@ static void fw_device_refresh(struct work_struct *work)
                    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
                goto gone;
 
-       fw_notify("refreshed device %s\n", device->device.bus_id);
+       fw_notify("refreshed device %s\n", dev_name(&device->device));
        device->config_rom_retries = 0;
        goto out;
 
  give_up:
-       fw_notify("giving up on refresh of device %s\n", device->device.bus_id);
+       fw_notify("giving up on refresh of device %s\n", dev_name(&device->device));
  gone:
        atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
        fw_device_shutdown(work);
index 8e16bfbdcb3db8c92553a9535c4f0adfa28dada8..46610b090415544306a292a02a4d62f63033d901 100644 (file)
@@ -2468,7 +2468,7 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
                goto fail_self_id;
 
        fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
-                 dev->dev.bus_id, version >> 16, version & 0xff);
+                 dev_name(&dev->dev), version >> 16, version & 0xff);
        return 0;
 
  fail_self_id:
index d334cac5e1fc64f4847ea4a72ad2620afd3167ee..97df6dac3a821c250dbf068e0e11b33d13affb6f 100644 (file)
@@ -1135,7 +1135,7 @@ static int sbp2_probe(struct device *dev)
        tgt->unit = unit;
        kref_init(&tgt->kref);
        INIT_LIST_HEAD(&tgt->lu_list);
-       tgt->bus_id = unit->device.bus_id;
+       tgt->bus_id = dev_name(&unit->device);
        tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
 
        if (fw_device_enable_phys_dma(device) < 0)
index 3e526b6d00cbff758be01772aa8663c002e4f5a4..8daf4793ac32485824194af5e14f332c50fc6f26 100644 (file)
@@ -81,9 +81,9 @@ static void dmi_table(u8 *buf, int len, int num,
                const struct dmi_header *dm = (const struct dmi_header *)data;
 
                /*
-                *  We want to know the total length (formated area and strings)
-                *  before decoding to make sure we won't run off the table in
-                *  dmi_decode or dmi_string
+                *  We want to know the total length (formatted area and
+                *  strings) before decoding to make sure we won't run off the
+                *  table in dmi_decode or dmi_string
                 */
                data += dm->length;
                while ((data - buf < len - 1) && (data[0] || data[1]))
index 5ba78e4fd2b517c9e6bab2af49c7f6c93fb38b21..d8fb5d8ee7ea38aa55308bda89ebee06978f1366 100644 (file)
@@ -3,13 +3,14 @@
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
 ccflags-y := -Iinclude/drm
-i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o \
+i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
           i915_suspend.o \
          i915_gem.o \
          i915_gem_debug.o \
          i915_gem_proc.o \
          i915_gem_tiling.o
 
+i915-$(CONFIG_ACPI)    += i915_opregion.o
 i915-$(CONFIG_COMPAT)   += i915_ioc32.o
 
 obj-$(CONFIG_DRM_I915)  += i915.o
index 01de536e0211772ba3df3154af63e5cab652a1f4..256e22963ae4d3949c9384aaec1921195d878ee6 100644 (file)
@@ -960,6 +960,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0),
        DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0),
        DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
+       DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
index f20ffe17df71d36cae69df56536d329be4c7ea27..572dcd0e3e0ddf860b77fc754f9ce2c3f35d1205 100644 (file)
@@ -31,6 +31,7 @@
 #define _I915_DRV_H_
 
 #include "i915_reg.h"
+#include <linux/io-mapping.h>
 
 /* General customization:
  */
@@ -246,6 +247,8 @@ typedef struct drm_i915_private {
        struct {
                struct drm_mm gtt_space;
 
+               struct io_mapping *gtt_mapping;
+
                /**
                 * List of objects currently involved in rendering from the
                 * ringbuffer.
@@ -502,6 +505,8 @@ int i915_gem_set_tiling(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
 int i915_gem_get_tiling(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
+int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_proc_init(struct drm_minor *minor);
 void i915_gem_proc_cleanup(struct drm_minor *minor);
@@ -539,11 +544,18 @@ extern int i915_restore_state(struct drm_device *dev);
 extern int i915_save_state(struct drm_device *dev);
 extern int i915_restore_state(struct drm_device *dev);
 
+#ifdef CONFIG_ACPI
 /* i915_opregion.c */
 extern int intel_opregion_init(struct drm_device *dev);
 extern void intel_opregion_free(struct drm_device *dev);
 extern void opregion_asle_intr(struct drm_device *dev);
 extern void opregion_enable_asle(struct drm_device *dev);
+#else
+static inline int intel_opregion_init(struct drm_device *dev) { return 0; }
+static inline void intel_opregion_free(struct drm_device *dev) { return; }
+static inline void opregion_asle_intr(struct drm_device *dev) { return; }
+static inline void opregion_enable_asle(struct drm_device *dev) { return; }
+#endif
 
 /**
  * Lock test for when it's just for synchronization of ring access.
index 17ae330ff269b10610d12a237ed9412f8e5e5856..b0ec73fa6a9348c329b0fd8715e86848db4b4b84 100644 (file)
@@ -79,6 +79,28 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+int
+i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_gem_get_aperture *args = data;
+       struct drm_i915_gem_object *obj_priv;
+
+       if (!(dev->driver->driver_features & DRIVER_GEM))
+               return -ENODEV;
+
+       args->aper_size = dev->gtt_total;
+       args->aper_available_size = args->aper_size;
+
+       list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
+               if (obj_priv->pin_count > 0)
+                       args->aper_available_size -= obj_priv->obj->size;
+       }
+
+       return 0;
+}
+
 
 /**
  * Creates a new mm object and returns a handle to it.
@@ -171,35 +193,50 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
-/*
- * Try to write quickly with an atomic kmap. Return true on success.
- *
- * If this fails (which includes a partial write), we'll redo the whole
- * thing with the slow version.
- *
- * This is a workaround for the low performance of iounmap (approximate
- * 10% cpu cost on normal 3D workloads).  kmap_atomic on HIGHMEM kernels
- * happens to let us map card memory without taking IPIs.  When the vmap
- * rework lands we should be able to dump this hack.
+/* This is the fast write path which cannot handle
+ * page faults in the source data
  */
-static inline int fast_user_write(unsigned long pfn, char __user *user_data,
-                                 int l, int o)
+
+static inline int
+fast_user_write(struct io_mapping *mapping,
+               loff_t page_base, int page_offset,
+               char __user *user_data,
+               int length)
 {
-#ifdef CONFIG_HIGHMEM
-       unsigned long unwritten;
        char *vaddr_atomic;
+       unsigned long unwritten;
 
-       vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0);
-#if WATCH_PWRITE
-       DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n",
-                i, o, l, pfn, vaddr_atomic);
-#endif
-       unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o, user_data, l);
-       kunmap_atomic(vaddr_atomic, KM_USER0);
-       return !unwritten;
-#else
+       vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
+       unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
+                                                     user_data, length);
+       io_mapping_unmap_atomic(vaddr_atomic);
+       if (unwritten)
+               return -EFAULT;
+       return 0;
+}
+
+/* Here's the write path which can sleep for
+ * page faults
+ */
+
+static inline int
+slow_user_write(struct io_mapping *mapping,
+               loff_t page_base, int page_offset,
+               char __user *user_data,
+               int length)
+{
+       char __iomem *vaddr;
+       unsigned long unwritten;
+
+       vaddr = io_mapping_map_wc(mapping, page_base);
+       if (vaddr == NULL)
+               return -EFAULT;
+       unwritten = __copy_from_user(vaddr + page_offset,
+                                    user_data, length);
+       io_mapping_unmap(vaddr);
+       if (unwritten)
+               return -EFAULT;
        return 0;
-#endif
 }
 
 static int
@@ -208,10 +245,12 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
                    struct drm_file *file_priv)
 {
        struct drm_i915_gem_object *obj_priv = obj->driver_private;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        ssize_t remain;
-       loff_t offset;
+       loff_t offset, page_base;
        char __user *user_data;
-       int ret = 0;
+       int page_offset, page_length;
+       int ret;
 
        user_data = (char __user *) (uintptr_t) args->data_ptr;
        remain = args->size;
@@ -235,57 +274,37 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
        obj_priv->dirty = 1;
 
        while (remain > 0) {
-               unsigned long pfn;
-               int i, o, l;
-
                /* Operation in this page
                 *
-                * i = page number
-                * o = offset within page
-                * l = bytes to copy
+                * page_base = page offset within aperture
+                * page_offset = offset within page
+                * page_length = bytes to copy for this page
                 */
-               i = offset >> PAGE_SHIFT;
-               o = offset & (PAGE_SIZE-1);
-               l = remain;
-               if ((o + l) > PAGE_SIZE)
-                       l = PAGE_SIZE - o;
-
-               pfn = (dev->agp->base >> PAGE_SHIFT) + i;
-
-               if (!fast_user_write(pfn, user_data, l, o)) {
-                       unsigned long unwritten;
-                       char __iomem *vaddr;
-
-                       vaddr = ioremap_wc(pfn << PAGE_SHIFT, PAGE_SIZE);
-#if WATCH_PWRITE
-                       DRM_INFO("pwrite slow i %d o %d l %d "
-                                "pfn %ld vaddr %p\n",
-                                i, o, l, pfn, vaddr);
-#endif
-                       if (vaddr == NULL) {
-                               ret = -EFAULT;
-                               goto fail;
-                       }
-                       unwritten = __copy_from_user(vaddr + o, user_data, l);
-#if WATCH_PWRITE
-                       DRM_INFO("unwritten %ld\n", unwritten);
-#endif
-                       iounmap(vaddr);
-                       if (unwritten) {
-                               ret = -EFAULT;
+               page_base = (offset & ~(PAGE_SIZE-1));
+               page_offset = offset & (PAGE_SIZE-1);
+               page_length = remain;
+               if ((page_offset + remain) > PAGE_SIZE)
+                       page_length = PAGE_SIZE - page_offset;
+
+               ret = fast_user_write (dev_priv->mm.gtt_mapping, page_base,
+                                      page_offset, user_data, page_length);
+
+               /* If we get a fault while copying data, then (presumably) our
+                * source page isn't available. In this case, use the
+                * non-atomic function
+                */
+               if (ret) {
+                       ret = slow_user_write (dev_priv->mm.gtt_mapping,
+                                              page_base, page_offset,
+                                              user_data, page_length);
+                       if (ret)
                                goto fail;
-                       }
                }
 
-               remain -= l;
-               user_data += l;
-               offset += l;
+               remain -= page_length;
+               user_data += page_length;
+               offset += page_length;
        }
-#if WATCH_PWRITE && 1
-       i915_gem_clflush_object(obj);
-       i915_gem_dump_object(obj, args->offset + args->size, __func__, ~0);
-       i915_gem_clflush_object(obj);
-#endif
 
 fail:
        i915_gem_object_unpin(obj);
@@ -1503,12 +1522,12 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                                 struct drm_i915_gem_exec_object *entry)
 {
        struct drm_device *dev = obj->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
        struct drm_i915_gem_relocation_entry reloc;
        struct drm_i915_gem_relocation_entry __user *relocs;
        struct drm_i915_gem_object *obj_priv = obj->driver_private;
        int i, ret;
-       uint32_t last_reloc_offset = -1;
-       void __iomem *reloc_page = NULL;
+       void __iomem *reloc_page;
 
        /* Choose the GTT offset for our buffer and put it there. */
        ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment);
@@ -1631,26 +1650,11 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                 * perform.
                 */
                reloc_offset = obj_priv->gtt_offset + reloc.offset;
-               if (reloc_page == NULL ||
-                   (last_reloc_offset & ~(PAGE_SIZE - 1)) !=
-                   (reloc_offset & ~(PAGE_SIZE - 1))) {
-                       if (reloc_page != NULL)
-                               iounmap(reloc_page);
-
-                       reloc_page = ioremap_wc(dev->agp->base +
-                                               (reloc_offset &
-                                                ~(PAGE_SIZE - 1)),
-                                               PAGE_SIZE);
-                       last_reloc_offset = reloc_offset;
-                       if (reloc_page == NULL) {
-                               drm_gem_object_unreference(target_obj);
-                               i915_gem_object_unpin(obj);
-                               return -ENOMEM;
-                       }
-               }
-
+               reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
+                                                     (reloc_offset &
+                                                      ~(PAGE_SIZE - 1)));
                reloc_entry = (uint32_t __iomem *)(reloc_page +
-                                          (reloc_offset & (PAGE_SIZE - 1)));
+                                                  (reloc_offset & (PAGE_SIZE - 1)));
                reloc_val = target_obj_priv->gtt_offset + reloc.delta;
 
 #if WATCH_BUF
@@ -1659,6 +1663,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                          readl(reloc_entry), reloc_val);
 #endif
                writel(reloc_val, reloc_entry);
+               io_mapping_unmap_atomic(reloc_page);
 
                /* Write the updated presumed offset for this entry back out
                 * to the user.
@@ -1674,9 +1679,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                drm_gem_object_unreference(target_obj);
        }
 
-       if (reloc_page != NULL)
-               iounmap(reloc_page);
-
 #if WATCH_BUF
        if (0)
                i915_gem_dump_object(obj, 128, __func__, ~0);
@@ -2518,6 +2520,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
        if (ret != 0)
                return ret;
 
+       dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base,
+                                                       dev->agp->agp_info.aper_size
+                                                       * 1024 * 1024);
+
        mutex_lock(&dev->struct_mutex);
        BUG_ON(!list_empty(&dev_priv->mm.active_list));
        BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
@@ -2535,11 +2541,13 @@ int
 i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv)
 {
+       drm_i915_private_t *dev_priv = dev->dev_private;
        int ret;
 
        ret = i915_gem_idle(dev);
        drm_irq_uninstall(dev);
 
+       io_mapping_free(dev_priv->mm.gtt_mapping);
        return ret;
 }
 
index 59a2132a8f57a5e833b83011191de047dc9ec43e..073894824e6b0f530a18fe4a37b233faba16d400 100644 (file)
@@ -653,15 +653,16 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
        RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);
 
        /* Turn on bus mastering */
-       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
+       if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
-               /* rs400, rs690/rs740 */
-               tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS400_BUS_MASTER_DIS;
+               /* rs600/rs690/rs740 */
+               tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS;
                RADEON_WRITE(RADEON_BUS_CNTL, tmp);
-       } else if (!(((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
-                   ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R423))) {
-               /* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+               /* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
                tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
                RADEON_WRITE(RADEON_BUS_CNTL, tmp);
        } /* PCIE cards appears to not need this */
index 4dbb813910c3f85060bd956998d7a3a85a63a0b6..02f5575ba395786d3f15a078fcd4e2e06ee70d37 100644 (file)
@@ -447,12 +447,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
  * handling, not bus mastering itself.
  */
 #define RADEON_BUS_CNTL                        0x0030
-/* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */
+/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */
 #      define RADEON_BUS_MASTER_DIS            (1 << 6)
-/* rs400, rs690/rs740 */
-#      define RS400_BUS_MASTER_DIS             (1 << 14)
-#      define RS400_MSI_REARM                  (1 << 20)
-/* see RS480_MSI_REARM in AIC_CNTL for rs480 */
+/* rs600/rs690/rs740 */
+#      define RS600_BUS_MASTER_DIS             (1 << 14)
+#      define RS600_MSI_REARM                  (1 << 20)
+/* see RS400_MSI_REARM in AIC_CNTL for rs480 */
 
 #define RADEON_BUS_CNTL1               0x0034
 #      define RADEON_PMI_BM_DIS                (1 << 2)
@@ -937,7 +937,7 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
 
 #define RADEON_AIC_CNTL                        0x01d0
 #      define RADEON_PCIGART_TRANSLATE_EN      (1 << 0)
-#      define RS480_MSI_REARM                  (1 << 3)
+#      define RS400_MSI_REARM                  (1 << 3)
 #define RADEON_AIC_STAT                        0x01d4
 #define RADEON_AIC_PT_BASE             0x01d8
 #define RADEON_AIC_LO_ADDR             0x01dc
index bc011da79e148249e24a1439e3c4cb55fcd1c7b0..be3285912cb76b65a7d69375215614f4fc898ee2 100644 (file)
@@ -116,6 +116,18 @@ static const char* temperature_sensors_sets[][36] = {
 /* Set 9: Macbook Pro 3,1 (Santa Rosa) */
        { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P",
          "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
+/* Set 10: iMac 5,1 */
+       { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL },
+/* Set 11: Macbook 5,1 */
+       { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P",
+         "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL },
+/* Set 12: Macbook Pro 5,1 */
+       { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D",
+         "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0",
+         "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL },
+/* Set 13: iMac 8,1 */
+       { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P",
+         "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL },
 };
 
 /* List of keys used to read/write fan speeds */
@@ -1276,6 +1288,14 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
        { .accelerometer = 1, .light = 1, .temperature_set = 8 },
 /* MacBook Pro 3: accelerometer, backlight and temperature set 9 */
        { .accelerometer = 1, .light = 1, .temperature_set = 9 },
+/* iMac 5: light sensor only, temperature set 10 */
+       { .accelerometer = 0, .light = 0, .temperature_set = 10 },
+/* MacBook 5: accelerometer, backlight and temperature set 11 */
+       { .accelerometer = 1, .light = 1, .temperature_set = 11 },
+/* MacBook Pro 5: accelerometer, backlight and temperature set 12 */
+       { .accelerometer = 1, .light = 1, .temperature_set = 12 },
+/* iMac 8: light sensor only, temperature set 13 */
+       { .accelerometer = 0, .light = 0, .temperature_set = 13 },
 };
 
 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
@@ -1285,6 +1305,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
                &applesmc_dmi_data[7]},
+       { applesmc_dmi_match, "Apple MacBook Pro 5", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") },
+               &applesmc_dmi_data[12]},
        { applesmc_dmi_match, "Apple MacBook Pro 4", {
          DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") },
@@ -1305,6 +1329,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
                &applesmc_dmi_data[6]},
+       { applesmc_dmi_match, "Apple MacBook 5", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") },
+               &applesmc_dmi_data[11]},
        { applesmc_dmi_match, "Apple MacBook", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
@@ -1317,6 +1345,14 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
                &applesmc_dmi_data[4]},
+       { applesmc_dmi_match, "Apple iMac 8", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") },
+               &applesmc_dmi_data[13]},
+       { applesmc_dmi_match, "Apple iMac 5", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") },
+               &applesmc_dmi_data[10]},
        { applesmc_dmi_match, "Apple iMac", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
index 965cfdb84ebc757c0c170e437be99bf637b88dbd..c19f23267157621b2fa613c9ea23a3bf82af5393 100644 (file)
@@ -1270,8 +1270,14 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
        struct video_card *video = file_to_video_card(file);
        int retval = -EINVAL;
 
-       /* serialize mmap */
-       mutex_lock(&video->mtx);
+       /*
+        * We cannot use the blocking variant mutex_lock here because .mmap
+        * is called with mmap_sem held, while .ioctl, .read, .write acquire
+        * video->mtx and subsequently call copy_to/from_user which will
+        * grab mmap_sem in case of a page fault.
+        */
+       if (!mutex_trylock(&video->mtx))
+               return -EAGAIN;
 
        if ( ! video_card_initialized(video) ) {
                retval = do_dv1394_init_default(video);
index 8dd09d8504196eecbe750887ec23f702667b105d..237d0c9d69c6cdd945a8de007e2a29485ec0f1ac 100644 (file)
@@ -155,11 +155,11 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
        memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
        h->device.parent = dev;
        set_dev_node(&h->device, dev_to_node(dev));
-       snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
+       dev_set_name(&h->device, "fw-host%d", h->id);
 
        h->host_dev.parent = &h->device;
        h->host_dev.class = &hpsb_host_class;
-       snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
+       dev_set_name(&h->host_dev, "fw-host%d", h->id);
 
        if (device_register(&h->device))
                goto fail;
index 2376b729e8765c5ca85bb7f1e0acf7201fe3b227..9e39f73282ee6dd439e76647af5ab5c4755e711a 100644 (file)
@@ -826,13 +826,11 @@ static struct node_entry *nodemgr_create_node(octlet_t guid,
        memcpy(&ne->device, &nodemgr_dev_template_ne,
               sizeof(ne->device));
        ne->device.parent = &host->device;
-       snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
-                (unsigned long long)(ne->guid));
+       dev_set_name(&ne->device, "%016Lx", (unsigned long long)(ne->guid));
 
        ne->node_dev.parent = &ne->device;
        ne->node_dev.class = &nodemgr_ne_class;
-       snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
-               (unsigned long long)(ne->guid));
+       dev_set_name(&ne->node_dev, "%016Lx", (unsigned long long)(ne->guid));
 
        if (device_register(&ne->device))
                goto fail_devreg;
@@ -932,13 +930,11 @@ static void nodemgr_register_device(struct node_entry *ne,
 
        ud->device.parent = parent;
 
-       snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
-                ne->device.bus_id, ud->id);
+       dev_set_name(&ud->device, "%s-%u", dev_name(&ne->device), ud->id);
 
        ud->unit_dev.parent = &ud->device;
        ud->unit_dev.class = &nodemgr_ud_class;
-       snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
-                ne->device.bus_id, ud->id);
+       dev_set_name(&ud->unit_dev, "%s-%u", dev_name(&ne->device), ud->id);
 
        if (device_register(&ud->device))
                goto fail_devreg;
@@ -953,7 +949,7 @@ static void nodemgr_register_device(struct node_entry *ne,
 fail_classdevreg:
        device_unregister(&ud->device);
 fail_devreg:
-       HPSB_ERR("Failed to create unit %s", ud->device.bus_id);
+       HPSB_ERR("Failed to create unit %s", dev_name(&ud->device));
 }      
 
 
index 9f19ac492106a8107a0d9fc2f2af66d92908dfe0..bf7e761c12b1c50ba711ade60eef3e003b767a8e 100644 (file)
@@ -2268,7 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
                return -EFAULT;
        }
 
-       mutex_lock(&fi->state_mutex);
+       if (!mutex_trylock(&fi->state_mutex))
+               return -EAGAIN;
 
        switch (fi->state) {
        case opened:
@@ -2548,7 +2549,8 @@ static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
        struct file_info *fi = file->private_data;
        int ret;
 
-       mutex_lock(&fi->state_mutex);
+       if (!mutex_trylock(&fi->state_mutex))
+               return -EAGAIN;
 
        if (fi->iso_state == RAW1394_ISO_INACTIVE)
                ret = -EINVAL;
@@ -2669,7 +2671,8 @@ static long raw1394_ioctl(struct file *file, unsigned int cmd,
                break;
        }
 
-       mutex_lock(&fi->state_mutex);
+       if (!mutex_trylock(&fi->state_mutex))
+               return -EAGAIN;
 
        switch (fi->iso_state) {
        case RAW1394_ISO_INACTIVE:
index 190147c79e79fbbe9b0e2c0935aa7ac697464a1b..3b90c5c924ecc25a33ba4268d22d65b74142fece 100644 (file)
@@ -148,6 +148,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
 
        min_sectors = conf->array_sectors;
        sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *));
+       if (min_sectors == 0)
+               min_sectors = 1;
 
        /* min_sectors is the minimum spacing that will fit the hash
         * table in one PAGE.  This may be much smaller than needed.
index 9abf6ed16535c925366eb936887f21425be7edc8..1b1d32694f6fc8eddf7a8c4cccc6d836b5e88054 100644 (file)
@@ -3884,7 +3884,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
        if (mode == 0) {
                mdk_rdev_t *rdev;
                struct list_head *tmp;
-               struct block_device *bdev;
 
                printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
 
@@ -3941,11 +3940,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                mddev->degraded = 0;
                mddev->barriers_work = 0;
                mddev->safemode = 0;
-               bdev = bdget_disk(mddev->gendisk, 0);
-               if (bdev) {
-                       blkdev_ioctl(bdev, 0, BLKRRPART, 0);
-                       bdput(bdev);
-               }
                kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE);
 
        } else if (mddev->pers)
index da5129a24b18142d39595c86415bdef40612e353..970a96ef9b1841badb7b43657d46263e67a9e722 100644 (file)
@@ -1137,7 +1137,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        if (!enough(conf))
                return -EINVAL;
 
-       if (rdev->raid_disk)
+       if (rdev->raid_disk >= 0)
                first = last = rdev->raid_disk;
 
        if (rdev->saved_raid_disk >= 0 &&
index a1abf95cf75153d2f2f1abd74549d5ba446ae473..603ffd008c73fb65275e1001af623f02332163d8 100644 (file)
@@ -77,12 +77,6 @@ MODULE_VERSION(my_VERSION);
  *  Fusion MPT LAN private structures
  */
 
-struct NAA_Hosed {
-       u16 NAA;
-       u8 ieee[FC_ALEN];
-       struct NAA_Hosed *next;
-};
-
 struct BufferControl {
        struct sk_buff  *skb;
        dma_addr_t      dma;
@@ -159,11 +153,6 @@ static u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS;
 static u32 max_buckets_out = 127;
 static u32 tx_max_out_p = 127 - 16;
 
-#ifdef QLOGIC_NAA_WORKAROUND
-static struct NAA_Hosed *mpt_bad_naa = NULL;
-DEFINE_RWLOCK(bad_naa_lock);
-#endif
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *     lan_reply - Handle all data sent from the hardware.
@@ -780,30 +769,6 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
 //                     ctx, skb, skb->data));
 
        mac = skb_mac_header(skb);
-#ifdef QLOGIC_NAA_WORKAROUND
-{
-       struct NAA_Hosed *nh;
-
-       /* Munge the NAA for Tx packets to QLogic boards, which don't follow
-          RFC 2625. The longer I look at this, the more my opinion of Qlogic
-          drops. */
-       read_lock_irq(&bad_naa_lock);
-       for (nh = mpt_bad_naa; nh != NULL; nh=nh->next) {
-               if ((nh->ieee[0] == mac[0]) &&
-                   (nh->ieee[1] == mac[1]) &&
-                   (nh->ieee[2] == mac[2]) &&
-                   (nh->ieee[3] == mac[3]) &&
-                   (nh->ieee[4] == mac[4]) &&
-                   (nh->ieee[5] == mac[5])) {
-                       cur_naa = nh->NAA;
-                       dlprintk ((KERN_INFO "mptlan/sdu_send: using NAA value "
-                                 "= %04x.\n", cur_naa));
-                       break;
-               }
-       }
-       read_unlock_irq(&bad_naa_lock);
-}
-#endif
 
        pTrans->TransactionDetails[0] = cpu_to_le32((cur_naa         << 16) |
                                                    (mac[0] <<  8) |
@@ -1572,79 +1537,6 @@ mpt_lan_type_trans(struct sk_buff *skb, struct net_device *dev)
 
        fcllc = (struct fcllc *)skb->data;
 
-#ifdef QLOGIC_NAA_WORKAROUND
-{
-       u16 source_naa = fch->stype, found = 0;
-
-       /* Workaround for QLogic not following RFC 2625 in regards to the NAA
-          value. */
-
-       if ((source_naa & 0xF000) == 0)
-               source_naa = swab16(source_naa);
-
-       if (fcllc->ethertype == htons(ETH_P_ARP))
-           dlprintk ((KERN_INFO "mptlan/type_trans: got arp req/rep w/ naa of "
-                     "%04x.\n", source_naa));
-
-       if ((fcllc->ethertype == htons(ETH_P_ARP)) &&
-          ((source_naa >> 12) !=  MPT_LAN_NAA_RFC2625)){
-               struct NAA_Hosed *nh, *prevnh;
-               int i;
-
-               dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep from "
-                         "system with non-RFC 2625 NAA value (%04x).\n",
-                         source_naa));
-
-               write_lock_irq(&bad_naa_lock);
-               for (prevnh = nh = mpt_bad_naa; nh != NULL;
-                    prevnh=nh, nh=nh->next) {
-                       if ((nh->ieee[0] == fch->saddr[0]) &&
-                           (nh->ieee[1] == fch->saddr[1]) &&
-                           (nh->ieee[2] == fch->saddr[2]) &&
-                           (nh->ieee[3] == fch->saddr[3]) &&
-                           (nh->ieee[4] == fch->saddr[4]) &&
-                           (nh->ieee[5] == fch->saddr[5])) {
-                               found = 1;
-                               dlprintk ((KERN_INFO "mptlan/type_trans: ARP Re"
-                                        "q/Rep w/ bad NAA from system already"
-                                        " in DB.\n"));
-                               break;
-                       }
-               }
-
-               if ((!found) && (nh == NULL)) {
-
-                       nh = kmalloc(sizeof(struct NAA_Hosed), GFP_KERNEL);
-                       dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep w/"
-                                " bad NAA from system not yet in DB.\n"));
-
-                       if (nh != NULL) {
-                               nh->next = NULL;
-                               if (!mpt_bad_naa)
-                                       mpt_bad_naa = nh;
-                               if (prevnh)
-                                       prevnh->next = nh;
-
-                               nh->NAA = source_naa; /* Set the S_NAA value. */
-                               for (i = 0; i < FC_ALEN; i++)
-                                       nh->ieee[i] = fch->saddr[i];
-                               dlprintk ((KERN_INFO "Got ARP from %02x:%02x:%02x:%02x:"
-                                         "%02x:%02x with non-compliant S_NAA value.\n",
-                                         fch->saddr[0], fch->saddr[1], fch->saddr[2],
-                                         fch->saddr[3], fch->saddr[4],fch->saddr[5]));
-                       } else {
-                               printk (KERN_ERR "mptlan/type_trans: Unable to"
-                                       " kmalloc a NAA_Hosed struct.\n");
-                       }
-               } else if (!found) {
-                       printk (KERN_ERR "mptlan/type_trans: found not"
-                               " set, but nh isn't null. Evil "
-                               "funkiness abounds.\n");
-               }
-               write_unlock_irq(&bad_naa_lock);
-       }
-}
-#endif
 
        /* Strip the SNAP header from ARP packets since we don't
         * pass them through to the 802.2/SNAP layers.
index 3e6f5d8609e8e513b38e5110bc7719a3fce5c1d0..d74ec46aa032220f3159739667b6f039620f77a8 100644 (file)
@@ -406,19 +406,6 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
                /* Set the default CFI lock/unlock addresses */
                cfi->addr_unlock1 = 0x555;
                cfi->addr_unlock2 = 0x2aa;
-               /* Modify the unlock address if we are in compatibility mode */
-               if (    /* x16 in x8 mode */
-                       ((cfi->device_type == CFI_DEVICETYPE_X8) &&
-                               (cfi->cfiq->InterfaceDesc ==
-                                       CFI_INTERFACE_X8_BY_X16_ASYNC)) ||
-                       /* x32 in x16 mode */
-                       ((cfi->device_type == CFI_DEVICETYPE_X16) &&
-                               (cfi->cfiq->InterfaceDesc ==
-                                       CFI_INTERFACE_X16_BY_X32_ASYNC)))
-               {
-                       cfi->addr_unlock1 = 0xaaa;
-                       cfi->addr_unlock2 = 0x555;
-               }
 
        } /* CFI mode */
        else if (cfi->cfi_mode == CFI_MODE_JEDEC) {
index f84ab6182148a97976262097fa5d0692b6080883..2f3f2f719ba497026a7a6f304fdcab4d03bbe5bd 100644 (file)
@@ -1808,9 +1808,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, uint32_t base,
         * several first banks can contain 0x7f instead of actual ID
         */
        do {
-               uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8),
-                                                 cfi_interleave(cfi),
-                                                 cfi->device_type);
+               uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi);
                mask = (1 << (cfi->device_type * 8)) - 1;
                result = map_read(map, base + ofs);
                bank++;
@@ -1824,7 +1822,7 @@ static inline u32 jedec_read_id(struct map_info *map, uint32_t base,
 {
        map_word result;
        unsigned long mask;
-       u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type);
+       u32 ofs = cfi_build_cmd_addr(1, map, cfi);
        mask = (1 << (cfi->device_type * 8)) -1;
        result = map_read(map, base + ofs);
        return result.x[0] & mask;
@@ -2067,8 +2065,8 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
 
        }
        /* Ensure the unlock addresses we try stay inside the map */
-       probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, cfi_interleave(cfi), cfi->device_type);
-       probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, cfi_interleave(cfi), cfi->device_type);
+       probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, map, cfi);
+       probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, map, cfi);
        if (    ((base + probe_offset1 + map_bankwidth(map)) >= map->size) ||
                ((base + probe_offset2 + map_bankwidth(map)) >= map->size))
                goto retry;
index 8387e05daae2186ec32627407f9ee28eda757bd8..e39b21d3e168e5bb3cabf1a076193bca3f33bcab 100644 (file)
@@ -38,7 +38,6 @@
 #include <asm/arch/gpmc.h>
 #include <asm/arch/onenand.h>
 #include <asm/arch/gpio.h>
-#include <asm/arch/gpmc.h>
 #include <asm/arch/pm.h>
 
 #include <linux/dma-mapping.h>
index f749b40f954e65e7ed5965320749c8261e76842e..11f143f4adf6d379682833679bb9ffa7cb99346c 100644 (file)
@@ -2010,9 +2010,13 @@ config IGB_LRO
          If in doubt, say N.
 
 config IGB_DCA
-       bool "Enable DCA"
+       bool "Direct Cache Access (DCA) Support"
        default y
        depends on IGB && DCA && !(IGB=y && DCA=m)
+       ---help---
+         Say Y here if you want to use Direct Cache Access (DCA) in the
+         driver.  DCA is a method for warming the CPU cache before data
+         is used, with the intent of lessening the impact of cache misses.
 
 source "drivers/net/ixp2000/Kconfig"
 
@@ -2437,9 +2441,13 @@ config IXGBE
          will be called ixgbe.
 
 config IXGBE_DCA
-       bool
+       bool "Direct Cache Access (DCA) Support"
        default y
        depends on IXGBE && DCA && !(IXGBE=y && DCA=m)
+       ---help---
+         Say Y here if you want to use Direct Cache Access (DCA) in the
+         driver.  DCA is a method for warming the CPU cache before data
+         is used, with the intent of lessening the impact of cache misses.
 
 config IXGB
        tristate "Intel(R) PRO/10GbE support"
@@ -2489,9 +2497,13 @@ config MYRI10GE
          will be called myri10ge.
 
 config MYRI10GE_DCA
-       bool
+       bool "Direct Cache Access (DCA) Support"
        default y
        depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m)
+       ---help---
+         Say Y here if you want to use Direct Cache Access (DCA) in the
+         driver.  DCA is a method for warming the CPU cache before data
+         is used, with the intent of lessening the impact of cache misses.
 
 config NETXEN_NIC
        tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC"
index b645fa0f3f64db3b3c2bc4bb9889517aecc328ce..c49550d507a0b4c9789a46fb275c0efdc00993eb 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/tcp.h>
-#include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/workqueue.h>
index 130927cfc75b63c79f986280029ddc4596f81c46..a6c0b3abba290a9cd75c7b7c4a764874c4e55801 100644 (file)
@@ -564,14 +564,15 @@ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = {
 
 static void bnx2x_init_pxp(struct bnx2x *bp)
 {
+       u16 devctl;
        int r_order, w_order;
        u32 val, i;
 
        pci_read_config_word(bp->pdev,
-                            bp->pcie_cap + PCI_EXP_DEVCTL, (u16 *)&val);
-       DP(NETIF_MSG_HW, "read 0x%x from devctl\n", (u16)val);
-       w_order = ((val & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
-       r_order = ((val & PCI_EXP_DEVCTL_READRQ) >> 12);
+                            bp->pcie_cap + PCI_EXP_DEVCTL, &devctl);
+       DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl);
+       w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);
+       r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12);
 
        if (r_order > MAX_RD_ORD) {
                DP(NETIF_MSG_HW, "read order of %d  order adjusted to %d\n",
index fce745148ff9a9896640be5e4c4fa780d3fc6b72..600210d7eff95da4f60840b530f149cec8259e45 100644 (file)
@@ -59,8 +59,8 @@
 #include "bnx2x.h"
 #include "bnx2x_init.h"
 
-#define DRV_MODULE_VERSION     "1.45.22"
-#define DRV_MODULE_RELDATE     "2008/09/09"
+#define DRV_MODULE_VERSION     "1.45.23"
+#define DRV_MODULE_RELDATE     "2008/11/03"
 #define BNX2X_BC_VER           0x040200
 
 /* Time in jiffies before concluding the transmitter is hung */
@@ -6481,6 +6481,7 @@ load_int_disable:
        bnx2x_free_irq(bp);
 load_error:
        bnx2x_free_mem(bp);
+       bp->port.pmf = 0;
 
        /* TBD we really need to reset the chip
           if we want to recover from this */
@@ -6791,6 +6792,7 @@ unload_error:
        /* Report UNLOAD_DONE to MCP */
        if (!BP_NOMCP(bp))
                bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE);
+       bp->port.pmf = 0;
 
        /* Free SKBs, SGEs, TPA pool and driver internals */
        bnx2x_free_skbs(bp);
@@ -10204,8 +10206,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
                return -ENOMEM;
        }
 
-       netif_carrier_off(dev);
-
        bp = netdev_priv(dev);
        bp->msglevel = debug;
 
@@ -10229,6 +10229,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
                goto init_one_exit;
        }
 
+       netif_carrier_off(dev);
+
        bp->common.name = board_info[ent->driver_data].name;
        printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx,"
               " IRQ %d, ", dev->name, bp->common.name,
index cb51c1fb0338e722334dcab4f72e6f9abb79137d..a6f49d02578711ed090a7625a34152e4b36655bc 100644 (file)
@@ -1099,7 +1099,9 @@ static int __devinit fs_enet_probe(struct of_device *ofdev,
        ndev->stop = fs_enet_close;
        ndev->get_stats = fs_enet_get_stats;
        ndev->set_multicast_list = fs_set_multicast_list;
-
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       ndev->poll_controller = fs_enet_netpoll;
+#endif
        if (fpi->use_napi)
                netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
                               fpi->napi_weight);
@@ -1209,7 +1211,7 @@ static void __exit fs_cleanup(void)
 static void fs_enet_netpoll(struct net_device *dev)
 {
        disable_irq(dev->irq);
-       fs_enet_interrupt(dev->irq, dev, NULL);
+       fs_enet_interrupt(dev->irq, dev);
        enable_irq(dev->irq);
 }
 #endif
index a9c8c08044b1847ebe560964433ad3ee4a564322..b9dcdbd369f87b87e5e9e12650e50d7ada6d9465 100644 (file)
@@ -1066,9 +1066,12 @@ static int smi_wait_ready(struct mv643xx_eth_shared_private *msp)
                return 0;
        }
 
-       if (!wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
-                               msecs_to_jiffies(100)))
-               return -ETIMEDOUT;
+       if (!smi_is_done(msp)) {
+               wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp),
+                                  msecs_to_jiffies(100));
+               if (!smi_is_done(msp))
+                       return -ETIMEDOUT;
+       }
 
        return 0;
 }
index ebc81270290339d09b94c3f6e46a8a921a68b2a4..9acb5d70a3ae310c4ac179469a7d5f18ae721b32 100644 (file)
@@ -8667,7 +8667,6 @@ static void __devinit niu_device_announce(struct niu *np)
 static int __devinit niu_pci_init_one(struct pci_dev *pdev,
                                      const struct pci_device_id *ent)
 {
-       unsigned long niureg_base, niureg_len;
        union niu_parent_id parent_id;
        struct net_device *dev;
        struct niu *np;
@@ -8758,10 +8757,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev,
 
        dev->features |= (NETIF_F_SG | NETIF_F_HW_CSUM);
 
-       niureg_base = pci_resource_start(pdev, 0);
-       niureg_len = pci_resource_len(pdev, 0);
-
-       np->regs = ioremap_nocache(niureg_base, niureg_len);
+       np->regs = pci_ioremap_bar(pdev, 0);
        if (!np->regs) {
                dev_err(&pdev->dev, PFX "Cannot map device registers, "
                        "aborting.\n");
index f59c7772f34435a13eb91cfccbd399210205a83a..5051554ff05b06f6c90c0a7f2ed006b96e3fafc0 100644 (file)
@@ -499,7 +499,7 @@ static void smc911x_hardware_send_pkt(struct net_device *dev)
 #else
        SMC_PUSH_DATA(lp, buf, len);
        dev->trans_start = jiffies;
-       dev_kfree_skb(skb);
+       dev_kfree_skb_irq(skb);
 #endif
        if (!lp->tx_throttle) {
                netif_wake_queue(dev);
index 6f9895d4e5bdf3016b5930d8b6716a81bf714ed7..fc80f250da31e8940bcc2d89d781de5eca66d7f2 100644 (file)
@@ -2060,6 +2060,7 @@ static int smc_request_attrib(struct platform_device *pdev,
                              struct net_device *ndev)
 {
        struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+       struct smc_local *lp __maybe_unused = netdev_priv(ndev);
 
        if (!res)
                return 0;
@@ -2074,6 +2075,7 @@ static void smc_release_attrib(struct platform_device *pdev,
                               struct net_device *ndev)
 {
        struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+       struct smc_local *lp __maybe_unused = netdev_priv(ndev);
 
        if (res)
                release_mem_region(res->start, ATTRIB_SIZE);
index cfbbfee55836b2f951ffafe304bdfc18e4ab7a45..85f38a6b6a49f9d744a1c90785042d16845910db 100644 (file)
@@ -37,7 +37,6 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/types.h>
-#include <asm/uaccess.h>
 
 #include "ucc_geth.h"
 #include "ucc_geth_mii.h"
index 9e47d727e2206ff28c647f648bb29caf4888057d..cfd4d052d666ea8cbda45b37c541cb2592dad3a0 100644 (file)
@@ -2942,8 +2942,10 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
                sc->opmode != NL80211_IFTYPE_MESH_POINT &&
                test_bit(ATH_STAT_PROMISC, sc->status))
                rfilt |= AR5K_RX_FILTER_PROM;
-       if (sc->opmode == NL80211_IFTYPE_ADHOC)
+       if (sc->opmode == NL80211_IFTYPE_STATION ||
+               sc->opmode == NL80211_IFTYPE_ADHOC) {
                rfilt |= AR5K_RX_FILTER_BEACON;
+       }
 
        /* Set filters */
        ath5k_hw_set_rx_filter(ah,rfilt);
index dd1374052ba9187bb92cc2626ae52694ad63d89a..5e362a7a362007aec0c8bf6800de1d97a587166d 100644 (file)
@@ -531,10 +531,10 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
                AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
        rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
                AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
-       rs->rs_antenna = rx_status->rx_status_0 &
-               AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-       rs->rs_more = rx_status->rx_status_0 &
-               AR5K_5210_RX_DESC_STATUS0_MORE;
+       rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+               AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+       rs->rs_more = !!(rx_status->rx_status_0 &
+               AR5K_5210_RX_DESC_STATUS0_MORE);
        /* TODO: this timestamp is 13 bit, later on we assume 15 bit */
        rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
                AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
@@ -607,10 +607,10 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
                AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
        rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
                AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
-       rs->rs_antenna = rx_status->rx_status_0 &
-               AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA;
-       rs->rs_more = rx_status->rx_status_0 &
-               AR5K_5212_RX_DESC_STATUS0_MORE;
+       rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
+               AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
+       rs->rs_more = !!(rx_status->rx_status_0 &
+               AR5K_5212_RX_DESC_STATUS0_MORE);
        rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
                AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
        rs->rs_status = 0;
index 321dbc8c034a9d608fff552fc90cafc3c1480777..8d690a0eb1a967722508942d9fdd90225c98be47 100644 (file)
@@ -3252,7 +3252,11 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
                return;
        }
 
-       iwl_scan_cancel_timeout(priv, 100);
+       if (iwl_scan_cancel(priv)) {
+               /* cancel scan failed, just live w/ bad key and rely
+                  briefly on SW decryption */
+               return;
+       }
 
        key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
        key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
index 3b0bee331a3350634c3179e86888900e562075c5..c89365e2ca58e3f4c5d142e9f9d11ed75d7642cc 100644 (file)
@@ -896,6 +896,13 @@ static void iwl_bg_request_scan(struct work_struct *data)
        return;
 
  done:
+       /* Cannot perform scan. Make sure we clear scanning
+       * bits from status so next scan request can be performed.
+       * If we don't clear scanning status bit here all next scan
+       * will fail
+       */
+       clear_bit(STATUS_SCAN_HW, &priv->status);
+       clear_bit(STATUS_SCANNING, &priv->status);
        /* inform mac80211 scan aborted */
        queue_work(priv->workqueue, &priv->scan_completed);
        mutex_unlock(&priv->mutex);
index d15a2c9979549983316a1981bdc07edf27581c54..285b53e7e261af8b70cbc447382b0e5369b86bbe 100644 (file)
@@ -5768,7 +5768,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
        if (priv->error_recovering)
                iwl3945_error_recovery(priv);
 
-       ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
        return;
 
  restart:
@@ -6013,6 +6012,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
        mutex_lock(&priv->mutex);
        iwl3945_alive_start(priv);
        mutex_unlock(&priv->mutex);
+       ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC);
 }
 
 static void iwl3945_bg_rf_kill(struct work_struct *work)
@@ -6256,6 +6256,11 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
                                              n_probes,
                        (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
 
+       if (scan->channel_count == 0) {
+               IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count);
+               goto done;
+       }
+
        cmd.len += le16_to_cpu(scan->tx_cmd.len) +
            scan->channel_count * sizeof(struct iwl3945_scan_channel);
        cmd.data = scan;
@@ -6273,6 +6278,14 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
        return;
 
  done:
+       /* can not perform scan make sure we clear scanning
+        * bits from status so next scan request can be performed.
+        * if we dont clear scanning status bit here all next scan
+        * will fail
+       */
+       clear_bit(STATUS_SCAN_HW, &priv->status);
+       clear_bit(STATUS_SCANNING, &priv->status);
+
        /* inform mac80211 scan aborted */
        queue_work(priv->workqueue, &priv->scan_completed);
        mutex_unlock(&priv->mutex);
index a60ae86bd5c9bddf5a9e8663ffdac0004d6183c8..a3ccd8c1c716957bd669ec678681bc2fcfe1f806 100644 (file)
@@ -61,6 +61,7 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
        /* ZD1211B */
        { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
@@ -82,6 +83,7 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
        /* "Driverless" devices that need ejecting */
        { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
        { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
index 478a4a739c00dabdc3ccf3a4689b2e84c32d5ce6..c3f1c8e9d2545a4859d984ed7237455ec8e8ca36 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/types.h>
-#include <linux/pnp.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
index 85edf945ab86a9a3f9c5c93d1484794f0b1acc93..204158cf7a55eda807715b4c59f0512f2a1f96bb 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
+#include <asm/smp.h>
 #include <asm/time.h>
 #include <asm/ps3.h>
 #include <asm/lv1call.h>
index 7af60b98d8a45b3f075cd231b04371cdd5975f66..a04c1b6b1575ba28b94ccb8027007123731977d4 100644 (file)
@@ -271,7 +271,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
                dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
                do {
                        alarm->time.tm_year++;
-               } while (!rtc_valid_tm(&alarm->time));
+               } while (rtc_valid_tm(&alarm->time) != 0);
                break;
 
        default:
index 5549231179a2dacb955357e69cd6b521d5e7954f..6cf8e282338f5cb5cfedeb94bf9cb7ecd1ca79d3 100644 (file)
@@ -794,7 +794,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
                goto cleanup2;
        }
 
-       pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n",
+       pr_info("%s: alarms up to one %s%s, %zd bytes nvram%s\n",
                        cmos_rtc.rtc->dev.bus_id,
                        is_valid_irq(rtc_irq)
                                ?  (cmos_rtc.mon_alrm
index 2bec9ccc02938d25ae9b366ad4c05e1889fe52c5..a9a9893a5f95b4867328b9396e2e097071e428ba 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/genhd.h>
 #include <linux/blkdev.h>
 
index 61fb8b6d19af77be5a9b180532725c22df68d44d..d5efd6c77904aef0dbb74641820b8937890f4ae5 100644 (file)
@@ -1258,6 +1258,8 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port,
                atmel_port->clk = clk_get(&pdev->dev, "usart");
                clk_enable(atmel_port->clk);
                port->uartclk = clk_get_rate(atmel_port->clk);
+               clk_disable(atmel_port->clk);
+               /* only enable clock when USART is in use */
        }
 
        atmel_port->use_dma_rx = data->use_dma_rx;
@@ -1379,6 +1381,8 @@ static int __init atmel_console_setup(struct console *co, char *options)
                return -ENODEV;
        }
 
+       clk_enable(atmel_ports[co->index].clk);
+
        UART_PUT_IDR(port, -1);
        UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
        UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
@@ -1403,7 +1407,7 @@ static struct console atmel_console = {
        .data           = &atmel_uart,
 };
 
-#define ATMEL_CONSOLE_DEVICE   &atmel_console
+#define ATMEL_CONSOLE_DEVICE   (&atmel_console)
 
 /*
  * Early console initialization (before VM subsystem initialized).
@@ -1534,6 +1538,15 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
        if (ret)
                goto err_add_port;
 
+       if (atmel_is_console_port(&port->uart)
+                       && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
+               /*
+                * The serial core enabled the clock for us, so undo
+                * the clk_enable() in atmel_console_setup()
+                */
+               clk_disable(port->clk);
+       }
+
        device_init_wakeup(&pdev->dev, 1);
        platform_set_drvdata(pdev, port);
 
@@ -1544,7 +1557,6 @@ err_add_port:
        port->rx_ring.buf = NULL;
 err_alloc_ring:
        if (!atmel_is_console_port(&port->uart)) {
-               clk_disable(port->clk);
                clk_put(port->clk);
                port->clk = NULL;
        }
@@ -1568,7 +1580,6 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
 
        /* "port" is allocated statically, so we shouldn't free it */
 
-       clk_disable(atmel_port->clk);
        clk_put(atmel_port->clk);
 
        return ret;
index b8f2c5e9dee5e575e6e3a5053f9f186c92a4cb19..fd4007e329e7dfe632c5b5ad56d63e1edf17a6e2 100644 (file)
 
 #include <linux/kernel.h>      /* We're doing kernel work */
 #include <linux/module.h>
-#include <linux/kernel.h>
 #include <linux/slab.h>
 
 #include "bit_operations.h"
index cf8b01bcac8d18d25e5c18e1afe55d9f8d82fa8b..0394e2709278cae3c00ad94e3daa21ca5d21b309 100644 (file)
@@ -39,7 +39,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
 
 /* Include-File for the Meilhaus ME-4000 I/O board */
 #include "me4000.h"
index 0f13448c6f799b05fdebd78e67031610ff25514e..3f3ce13fef431450909e12cb91646534c68cf46f 100644 (file)
@@ -2083,6 +2083,38 @@ config FB_METRONOME
          controller. The pre-release name for this device was 8track
          and could also have been called by some vendors as PVI-nnnn.
 
+config FB_MB862XX
+       tristate "Fujitsu MB862xx GDC support"
+       depends on FB
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+         Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers.
+
+config FB_MB862XX_PCI_GDC
+       bool "Carmine/Coral-P(A) GDC"
+       depends on PCI && FB_MB862XX
+       ---help---
+         This enables framebuffer support for Fujitsu Carmine/Coral-P(A)
+         PCI graphics controller devices.
+
+config FB_MB862XX_LIME
+       bool "Lime GDC"
+       depends on FB_MB862XX
+       depends on OF && !FB_MB862XX_PCI_GDC
+       select FB_FOREIGN_ENDIAN
+       select FB_LITTLE_ENDIAN
+       ---help---
+         Framebuffer support for Fujitsu Lime GDC on host CPU bus.
+
+config FB_PRE_INIT_FB
+       bool "Don't reinitialize, use bootloader's GDC/Display configuration"
+       depends on FB_MB862XX_LIME
+       ---help---
+         Select this option if display contents should be inherited as set by
+         the bootloader.
+
 source "drivers/video/omap/Kconfig"
 
 source "drivers/video/backlight/Kconfig"
index 248bddc8d0b0bb0e7e970d30dc2427f51b6d6e76..e39e33e797da70d447f4f4b090ad9bb9163fe157 100644 (file)
@@ -122,6 +122,7 @@ obj-$(CONFIG_FB_SH_MOBILE_LCDC)       += sh_mobile_lcdcfb.o
 obj-$(CONFIG_FB_OMAP)             += omap/
 obj-$(CONFIG_XEN_FBDEV_FRONTEND)  += xen-fbfront.o
 obj-$(CONFIG_FB_CARMINE)          += carminefb.o
+obj-$(CONFIG_FB_MB862XX)         += mb862xx/
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
index 6048b55f2878b8755179c0641785ac89fe217b4b..1d5ae39cb271ecb3219f9089ef9366f532f93efe 100644 (file)
@@ -1002,13 +1002,9 @@ fb_blank(struct fb_info *info, int blank)
        return ret;
 }
 
-static long
-fb_ioctl(struct file *file, unsigned int cmd,
-        unsigned long arg)
+static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
+                       unsigned long arg)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       int fbidx = iminor(inode);
-       struct fb_info *info;
        struct fb_ops *fb;
        struct fb_var_screeninfo var;
        struct fb_fix_screeninfo fix;
@@ -1018,14 +1014,10 @@ fb_ioctl(struct file *file, unsigned int cmd,
        void __user *argp = (void __user *)arg;
        long ret = 0;
 
-       info = registered_fb[fbidx];
-       mutex_lock(&info->lock);
        fb = info->fbops;
-
-       if (!fb) {
-               mutex_unlock(&info->lock);
+       if (!fb)
                return -ENODEV;
-       }
+
        switch (cmd) {
        case FBIOGET_VSCREENINFO:
                ret = copy_to_user(argp, &info->var,
@@ -1126,6 +1118,21 @@ fb_ioctl(struct file *file, unsigned int cmd,
                else
                        ret = fb->fb_ioctl(info, cmd, arg);
        }
+       return ret;
+}
+
+static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+__acquires(&info->lock)
+__releases(&info->lock)
+{
+       struct inode *inode = file->f_path.dentry->d_inode;
+       int fbidx = iminor(inode);
+       struct fb_info *info;
+       long ret;
+
+       info = registered_fb[fbidx];
+       mutex_lock(&info->lock);
+       ret = do_fb_ioctl(info, cmd, arg);
        mutex_unlock(&info->lock);
        return ret;
 }
@@ -1157,8 +1164,8 @@ struct fb_cmap32 {
        compat_caddr_t  transp;
 };
 
-static int fb_getput_cmap(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
+                         unsigned long arg)
 {
        struct fb_cmap_user __user *cmap;
        struct fb_cmap32 __user *cmap32;
@@ -1181,7 +1188,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file,
            put_user(compat_ptr(data), &cmap->transp))
                return -EFAULT;
 
-       err = fb_ioctl(file, cmd, (unsigned long) cmap);
+       err = do_fb_ioctl(info, cmd, (unsigned long) cmap);
 
        if (!err) {
                if (copy_in_user(&cmap32->start,
@@ -1223,8 +1230,8 @@ static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
        return err;
 }
 
-static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
-                               unsigned int cmd, unsigned long arg)
+static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
+                             unsigned long arg)
 {
        mm_segment_t old_fs;
        struct fb_fix_screeninfo fix;
@@ -1235,7 +1242,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
 
        old_fs = get_fs();
        set_fs(KERNEL_DS);
-       err = fb_ioctl(file, cmd, (unsigned long) &fix);
+       err = do_fb_ioctl(info, cmd, (unsigned long) &fix);
        set_fs(old_fs);
 
        if (!err)
@@ -1244,8 +1251,10 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
        return err;
 }
 
-static long
-fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long fb_compat_ioctl(struct file *file, unsigned int cmd,
+                           unsigned long arg)
+__acquires(&info->lock)
+__releases(&info->lock)
 {
        struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
@@ -1262,16 +1271,16 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case FBIOPUT_CON2FBMAP:
                arg = (unsigned long) compat_ptr(arg);
        case FBIOBLANK:
-               mutex_unlock(&info->lock);
-               return fb_ioctl(file, cmd, arg);
+               ret = do_fb_ioctl(info, cmd, arg);
+               break;
 
        case FBIOGET_FSCREENINFO:
-               ret = fb_get_fscreeninfo(inode, file, cmd, arg);
+               ret = fb_get_fscreeninfo(info, cmd, arg);
                break;
 
        case FBIOGETCMAP:
        case FBIOPUTCMAP:
-               ret = fb_getput_cmap(inode, file, cmd, arg);
+               ret = fb_getput_cmap(info, cmd, arg);
                break;
 
        default:
@@ -1286,6 +1295,8 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 static int
 fb_mmap(struct file *file, struct vm_area_struct * vma)
+__acquires(&info->lock)
+__releases(&info->lock)
 {
        int fbidx = iminor(file->f_path.dentry->d_inode);
        struct fb_info *info = registered_fb[fbidx];
@@ -1339,6 +1350,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
 
 static int
 fb_open(struct inode *inode, struct file *file)
+__acquires(&info->lock)
+__releases(&info->lock)
 {
        int fbidx = iminor(inode);
        struct fb_info *info;
@@ -1374,6 +1387,8 @@ out:
 
 static int 
 fb_release(struct inode *inode, struct file *file)
+__acquires(&info->lock)
+__releases(&info->lock)
 {
        struct fb_info * const info = file->private_data;
 
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile
new file mode 100644 (file)
index 0000000..0766481
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the MB862xx framebuffer driver
+#
+
+obj-$(CONFIG_FB_MB862XX)       := mb862xxfb.o
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h
new file mode 100644 (file)
index 0000000..2ba65e1
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Fujitsu MB862xx Graphics Controller Registers/Bits
+ */
+
+#ifndef _MB862XX_REG_H
+#define _MB862XX_REG_H
+
+#ifdef MB862XX_MMIO_BOTTOM
+#define MB862XX_MMIO_BASE      0x03fc0000
+#else
+#define MB862XX_MMIO_BASE      0x01fc0000
+#endif
+#define MB862XX_I2C_BASE       0x0000c000
+#define MB862XX_DISP_BASE      0x00010000
+#define MB862XX_CAP_BASE       0x00018000
+#define MB862XX_DRAW_BASE      0x00030000
+#define MB862XX_GEO_BASE       0x00038000
+#define MB862XX_PIO_BASE       0x00038000
+#define MB862XX_MMIO_SIZE      0x40000
+
+/* Host interface/pio registers */
+#define GC_IST                 0x00000020
+#define GC_IMASK               0x00000024
+#define GC_SRST                        0x0000002c
+#define GC_CCF                 0x00000038
+#define GC_CID                 0x000000f0
+#define GC_REVISION            0x00000084
+
+#define GC_CCF_CGE_100         0x00000000
+#define GC_CCF_CGE_133         0x00040000
+#define GC_CCF_CGE_166         0x00080000
+#define GC_CCF_COT_100         0x00000000
+#define GC_CCF_COT_133         0x00010000
+#define GC_CID_CNAME_MSK       0x0000ff00
+#define GC_CID_VERSION_MSK     0x000000ff
+
+/* define enabled interrupts hereby */
+#define GC_INT_EN              0x00000000
+
+/* Memory interface mode register */
+#define GC_MMR                 0x0000fffc
+
+/* Display Controller registers */
+#define GC_DCM0                        0x00000000
+#define GC_HTP                 0x00000004
+#define GC_HDB_HDP             0x00000008
+#define GC_VSW_HSW_HSP         0x0000000c
+#define GC_VTR                 0x00000010
+#define GC_VDP_VSP             0x00000014
+#define GC_WY_WX               0x00000018
+#define GC_WH_WW               0x0000001c
+#define GC_L0M                 0x00000020
+#define GC_L0OA0               0x00000024
+#define GC_L0DA0               0x00000028
+#define GC_L0DY_L0DX           0x0000002c
+#define GC_DCM1                        0x00000100
+#define GC_L0EM                        0x00000110
+#define GC_L0WY_L0WX           0x00000114
+#define GC_L0WH_L0WW           0x00000118
+#define GC_DCM2                        0x00000104
+#define GC_DCM3                        0x00000108
+#define GC_CPM_CUTC            0x000000a0
+#define GC_CUOA0               0x000000a4
+#define GC_CUY0_CUX0           0x000000a8
+#define GC_CUOA1               0x000000ac
+#define GC_CUY1_CUX1           0x000000b0
+#define GC_L0PAL0              0x00000400
+
+#define GC_CPM_CEN0            0x00100000
+#define GC_CPM_CEN1            0x00200000
+
+#define GC_DCM01_ESY           0x00000004
+#define GC_DCM01_SC            0x00003f00
+#define GC_DCM01_RESV          0x00004000
+#define GC_DCM01_CKS           0x00008000
+#define GC_DCM01_L0E           0x00010000
+#define GC_DCM01_DEN           0x80000000
+#define GC_L0M_L0C_8           0x00000000
+#define GC_L0M_L0C_16          0x80000000
+#define GC_L0EM_L0EC_24                0x40000000
+#define GC_L0M_L0W_UNIT                64
+
+#define GC_DISP_REFCLK_400     400
+
+/* Carmine specific */
+#define MB86297_DRAW_BASE              0x00020000
+#define MB86297_DISP0_BASE             0x00100000
+#define MB86297_DISP1_BASE             0x00140000
+#define MB86297_WRBACK_BASE            0x00180000
+#define MB86297_CAP0_BASE              0x00200000
+#define MB86297_CAP1_BASE              0x00280000
+#define MB86297_DRAMCTRL_BASE          0x00300000
+#define MB86297_CTRL_BASE              0x00400000
+#define MB86297_I2C_BASE               0x00500000
+
+#define GC_CTRL_STATUS                 0x00000000
+#define GC_CTRL_INT_MASK               0x00000004
+#define GC_CTRL_CLK_ENABLE             0x0000000c
+#define GC_CTRL_SOFT_RST               0x00000010
+
+#define GC_CTRL_CLK_EN_DRAM            0x00000001
+#define GC_CTRL_CLK_EN_2D3D            0x00000002
+#define GC_CTRL_CLK_EN_DISP0           0x00000020
+#define GC_CTRL_CLK_EN_DISP1           0x00000040
+
+#define GC_2D3D_REV                    0x000004b4
+#define GC_RE_REVISION                 0x24240200
+
+/* define enabled interrupts hereby */
+#define GC_CARMINE_INT_EN              0x00000004
+
+/* DRAM controller */
+#define GC_DCTL_MODE_ADD               0x00000000
+#define GC_DCTL_SETTIME1_EMODE         0x00000004
+#define GC_DCTL_REFRESH_SETTIME2       0x00000008
+#define GC_DCTL_RSV0_STATES            0x0000000C
+#define GC_DCTL_RSV2_RSV1              0x00000010
+#define GC_DCTL_DDRIF2_DDRIF1          0x00000014
+#define GC_DCTL_IOCONT1_IOCONT0                0x00000024
+
+#define GC_DCTL_STATES_MSK             0x0000000f
+#define GC_DCTL_INIT_WAIT_CNT          3000
+#define GC_DCTL_INIT_WAIT_INTERVAL     1
+
+/* DRAM ctrl values for Carmine PCI Eval. board */
+#define GC_EVB_DCTL_MODE_ADD           0x012105c3
+#define GC_EVB_DCTL_MODE_ADD_AFT_RST   0x002105c3
+#define GC_EVB_DCTL_SETTIME1_EMODE     0x47498000
+#define GC_EVB_DCTL_REFRESH_SETTIME2   0x00422a22
+#define GC_EVB_DCTL_RSV0_STATES                0x00200003
+#define GC_EVB_DCTL_RSV0_STATES_AFT_RST        0x00200002
+#define GC_EVB_DCTL_RSV2_RSV1          0x0000000f
+#define GC_EVB_DCTL_DDRIF2_DDRIF1      0x00556646
+#define GC_EVB_DCTL_IOCONT1_IOCONT0    0x05550555
+
+#define GC_DISP_REFCLK_533             533
+
+#endif
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
new file mode 100644 (file)
index 0000000..38718d9
--- /dev/null
@@ -0,0 +1,1061 @@
+/*
+ * drivers/mb862xx/mb862xxfb.c
+ *
+ * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver
+ *
+ * (C) 2008 Anatolij Gustschin <agust@denx.de>
+ * DENX Software Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#if defined(CONFIG_PPC_OF)
+#include <linux/of_platform.h>
+#endif
+#include "mb862xxfb.h"
+#include "mb862xx_reg.h"
+
+#define NR_PALETTE             256
+#define MB862XX_MEM_SIZE       0x1000000
+#define CORALP_MEM_SIZE                0x4000000
+#define CARMINE_MEM_SIZE       0x8000000
+#define DRV_NAME               "mb862xxfb"
+
+#if defined(CONFIG_LWMON5)
+static struct mb862xx_gc_mode lwmon5_gc_mode = {
+       /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */
+       { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 },
+       /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */
+       16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2
+};
+#endif
+
+#if defined(CONFIG_SOCRATES)
+static struct mb862xx_gc_mode socrates_gc_mode = {
+       /* Mode for Prime View PM070WL4 TFT LCD Panel */
+       { "800x480", 45, 800, 480, 40000, 86, 42, 33, 10, 128, 2, 0, 0, 0 },
+       /* 16 bits/pixel, 16MB, 133MHz, SDRAM memory mode value */
+       16, 0x1000000, GC_CCF_COT_133, 0x4157ba63
+};
+#endif
+
+/* Helpers */
+static inline int h_total(struct fb_var_screeninfo *var)
+{
+       return var->xres + var->left_margin +
+               var->right_margin + var->hsync_len;
+}
+
+static inline int v_total(struct fb_var_screeninfo *var)
+{
+       return var->yres + var->upper_margin +
+               var->lower_margin + var->vsync_len;
+}
+
+static inline int hsp(struct fb_var_screeninfo *var)
+{
+       return var->xres + var->right_margin - 1;
+}
+
+static inline int vsp(struct fb_var_screeninfo *var)
+{
+       return var->yres + var->lower_margin - 1;
+}
+
+static inline int d_pitch(struct fb_var_screeninfo *var)
+{
+       return var->xres * var->bits_per_pixel / 8;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan,
+                                        struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+static int mb862xxfb_setcolreg(unsigned regno,
+                              unsigned red, unsigned green, unsigned blue,
+                              unsigned transp, struct fb_info *info)
+{
+       struct mb862xxfb_par *par = info->par;
+       unsigned int val;
+
+       switch (info->fix.visual) {
+       case FB_VISUAL_TRUECOLOR:
+               if (regno < 16) {
+                       val  = chan_to_field(red,   &info->var.red);
+                       val |= chan_to_field(green, &info->var.green);
+                       val |= chan_to_field(blue,  &info->var.blue);
+                       par->pseudo_palette[regno] = val;
+               }
+               break;
+       case FB_VISUAL_PSEUDOCOLOR:
+               if (regno < 256) {
+                       val = (red >> 8) << 16;
+                       val |= (green >> 8) << 8;
+                       val |= blue >> 8;
+                       outreg(disp, GC_L0PAL0 + (regno * 4), val);
+               }
+               break;
+       default:
+               return 1;   /* unsupported type */
+       }
+       return 0;
+}
+
+static int mb862xxfb_check_var(struct fb_var_screeninfo *var,
+                              struct fb_info *fbi)
+{
+       unsigned long tmp;
+
+       if (fbi->dev)
+               dev_dbg(fbi->dev, "%s\n", __func__);
+
+       /* check if these values fit into the registers */
+       if (var->hsync_len > 255 || var->vsync_len > 255)
+               return -EINVAL;
+
+       if ((var->xres + var->right_margin) >= 4096)
+               return -EINVAL;
+
+       if ((var->yres + var->lower_margin) > 4096)
+               return -EINVAL;
+
+       if (h_total(var) > 4096 || v_total(var) > 4096)
+               return -EINVAL;
+
+       if (var->xres_virtual > 4096 || var->yres_virtual > 4096)
+               return -EINVAL;
+
+       if (var->bits_per_pixel <= 8)
+               var->bits_per_pixel = 8;
+       else if (var->bits_per_pixel <= 16)
+               var->bits_per_pixel = 16;
+       else if (var->bits_per_pixel <= 32)
+               var->bits_per_pixel = 32;
+
+       /*
+        * can cope with 8,16 or 24/32bpp if resulting
+        * pitch is divisible by 64 without remainder
+        */
+       if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) {
+               int r;
+
+               var->bits_per_pixel = 0;
+               do {
+                       var->bits_per_pixel += 8;
+                       r = d_pitch(&fbi->var) % GC_L0M_L0W_UNIT;
+               } while (r && var->bits_per_pixel <= 32);
+
+               if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT)
+                       return -EINVAL;
+       }
+
+       /* line length is going to be 128 bit aligned */
+       tmp = (var->xres * var->bits_per_pixel) / 8;
+       if ((tmp & 15) != 0)
+               return -EINVAL;
+
+       /* set r/g/b positions and validate bpp */
+       switch (var->bits_per_pixel) {
+       case 8:
+               var->red.length         = var->bits_per_pixel;
+               var->green.length       = var->bits_per_pixel;
+               var->blue.length        = var->bits_per_pixel;
+               var->red.offset         = 0;
+               var->green.offset       = 0;
+               var->blue.offset        = 0;
+               var->transp.length      = 0;
+               break;
+       case 16:
+               var->red.length         = 5;
+               var->green.length       = 5;
+               var->blue.length        = 5;
+               var->red.offset         = 10;
+               var->green.offset       = 5;
+               var->blue.offset        = 0;
+               var->transp.length      = 0;
+               break;
+       case 24:
+       case 32:
+               var->transp.length      = 8;
+               var->red.length         = 8;
+               var->green.length       = 8;
+               var->blue.length        = 8;
+               var->transp.offset      = 24;
+               var->red.offset         = 16;
+               var->green.offset       = 8;
+               var->blue.offset        = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * set display parameters
+ */
+static int mb862xxfb_set_par(struct fb_info *fbi)
+{
+       struct mb862xxfb_par *par = fbi->par;
+       unsigned long reg, sc;
+
+       dev_dbg(par->dev, "%s\n", __func__);
+
+       if (par->pre_init)
+               return 0;
+
+       /* disp off */
+       reg = inreg(disp, GC_DCM1);
+       reg &= ~GC_DCM01_DEN;
+       outreg(disp, GC_DCM1, reg);
+
+       /* set display reference clock div. */
+       sc = par->refclk / (1000000 / fbi->var.pixclock) - 1;
+       reg = inreg(disp, GC_DCM1);
+       reg &= ~(GC_DCM01_CKS | GC_DCM01_RESV | GC_DCM01_SC);
+       reg |= sc << 8;
+       outreg(disp, GC_DCM1, reg);
+       dev_dbg(par->dev, "SC 0x%lx\n", sc);
+
+       /* disp dimension, format */
+       reg =  pack(d_pitch(&fbi->var) / GC_L0M_L0W_UNIT,
+                   (fbi->var.yres - 1));
+       if (fbi->var.bits_per_pixel == 16)
+               reg |= GC_L0M_L0C_16;
+       outreg(disp, GC_L0M, reg);
+
+       if (fbi->var.bits_per_pixel == 32) {
+               reg = inreg(disp, GC_L0EM);
+               outreg(disp, GC_L0EM, reg | GC_L0EM_L0EC_24);
+       }
+       outreg(disp, GC_WY_WX, 0);
+       reg = pack(fbi->var.yres - 1, fbi->var.xres);
+       outreg(disp, GC_WH_WW, reg);
+       outreg(disp, GC_L0OA0, 0);
+       outreg(disp, GC_L0DA0, 0);
+       outreg(disp, GC_L0DY_L0DX, 0);
+       outreg(disp, GC_L0WY_L0WX, 0);
+       outreg(disp, GC_L0WH_L0WW, reg);
+
+       /* both HW-cursors off */
+       reg = inreg(disp, GC_CPM_CUTC);
+       reg &= ~(GC_CPM_CEN0 | GC_CPM_CEN1);
+       outreg(disp, GC_CPM_CUTC, reg);
+
+       /* timings */
+       reg = pack(fbi->var.xres - 1, fbi->var.xres - 1);
+       outreg(disp, GC_HDB_HDP, reg);
+       reg = pack((fbi->var.yres - 1), vsp(&fbi->var));
+       outreg(disp, GC_VDP_VSP, reg);
+       reg = ((fbi->var.vsync_len - 1) << 24) |
+             pack((fbi->var.hsync_len - 1), hsp(&fbi->var));
+       outreg(disp, GC_VSW_HSW_HSP, reg);
+       outreg(disp, GC_HTP, pack(h_total(&fbi->var) - 1, 0));
+       outreg(disp, GC_VTR, pack(v_total(&fbi->var) - 1, 0));
+
+       /* display on */
+       reg = inreg(disp, GC_DCM1);
+       reg |= GC_DCM01_DEN | GC_DCM01_L0E;
+       reg &= ~GC_DCM01_ESY;
+       outreg(disp, GC_DCM1, reg);
+       return 0;
+}
+
+static int mb862xxfb_pan(struct fb_var_screeninfo *var,
+                        struct fb_info *info)
+{
+       struct mb862xxfb_par *par = info->par;
+       unsigned long reg;
+
+       reg = pack(var->yoffset, var->xoffset);
+       outreg(disp, GC_L0WY_L0WX, reg);
+
+       reg = pack(var->yres_virtual, var->xres_virtual);
+       outreg(disp, GC_L0WH_L0WW, reg);
+       return 0;
+}
+
+static int mb862xxfb_blank(int mode, struct fb_info *fbi)
+{
+       struct mb862xxfb_par  *par = fbi->par;
+       unsigned long reg;
+
+       dev_dbg(fbi->dev, "blank mode=%d\n", mode);
+
+       switch (mode) {
+       case FB_BLANK_POWERDOWN:
+               reg = inreg(disp, GC_DCM1);
+               reg &= ~GC_DCM01_DEN;
+               outreg(disp, GC_DCM1, reg);
+               break;
+       case FB_BLANK_UNBLANK:
+               reg = inreg(disp, GC_DCM1);
+               reg |= GC_DCM01_DEN;
+               outreg(disp, GC_DCM1, reg);
+               break;
+       case FB_BLANK_NORMAL:
+       case FB_BLANK_VSYNC_SUSPEND:
+       case FB_BLANK_HSYNC_SUSPEND:
+       default:
+               return 1;
+       }
+       return 0;
+}
+
+/* framebuffer ops */
+static struct fb_ops mb862xxfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = mb862xxfb_check_var,
+       .fb_set_par     = mb862xxfb_set_par,
+       .fb_setcolreg   = mb862xxfb_setcolreg,
+       .fb_blank       = mb862xxfb_blank,
+       .fb_pan_display = mb862xxfb_pan,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+};
+
+/* initialize fb_info data */
+static int mb862xxfb_init_fbinfo(struct fb_info *fbi)
+{
+       struct mb862xxfb_par *par = fbi->par;
+       struct mb862xx_gc_mode *mode = par->gc_mode;
+       unsigned long reg;
+
+       fbi->fbops = &mb862xxfb_ops;
+       fbi->pseudo_palette = par->pseudo_palette;
+       fbi->screen_base = par->fb_base;
+       fbi->screen_size = par->mapped_vram;
+
+       strcpy(fbi->fix.id, DRV_NAME);
+       fbi->fix.smem_start = (unsigned long)par->fb_base_phys;
+       fbi->fix.smem_len = par->mapped_vram;
+       fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys;
+       fbi->fix.mmio_len = par->mmio_len;
+       fbi->fix.accel = FB_ACCEL_NONE;
+       fbi->fix.type = FB_TYPE_PACKED_PIXELS;
+       fbi->fix.type_aux = 0;
+       fbi->fix.xpanstep = 1;
+       fbi->fix.ypanstep = 1;
+       fbi->fix.ywrapstep = 0;
+
+       reg = inreg(disp, GC_DCM1);
+       if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) {
+               /* get the disp mode from active display cfg */
+               unsigned long sc = ((reg & GC_DCM01_SC) >> 8) + 1;
+               unsigned long hsp, vsp, ht, vt;
+
+               dev_dbg(par->dev, "using bootloader's disp. mode\n");
+               fbi->var.pixclock = (sc * 1000000) / par->refclk;
+               fbi->var.xres = (inreg(disp, GC_HDB_HDP) & 0x0fff) + 1;
+               reg = inreg(disp, GC_VDP_VSP);
+               fbi->var.yres = ((reg >> 16) & 0x0fff) + 1;
+               vsp = (reg & 0x0fff) + 1;
+               fbi->var.xres_virtual = fbi->var.xres;
+               fbi->var.yres_virtual = fbi->var.yres;
+               reg = inreg(disp, GC_L0EM);
+               if (reg & GC_L0EM_L0EC_24) {
+                       fbi->var.bits_per_pixel = 32;
+               } else {
+                       reg = inreg(disp, GC_L0M);
+                       if (reg & GC_L0M_L0C_16)
+                               fbi->var.bits_per_pixel = 16;
+                       else
+                               fbi->var.bits_per_pixel = 8;
+               }
+               reg = inreg(disp, GC_VSW_HSW_HSP);
+               fbi->var.hsync_len = ((reg & 0xff0000) >> 16) + 1;
+               fbi->var.vsync_len = ((reg & 0x3f000000) >> 24) + 1;
+               hsp = (reg & 0xffff) + 1;
+               ht = ((inreg(disp, GC_HTP) & 0xfff0000) >> 16) + 1;
+               fbi->var.right_margin = hsp - fbi->var.xres;
+               fbi->var.left_margin = ht - hsp - fbi->var.hsync_len;
+               vt = ((inreg(disp, GC_VTR) & 0xfff0000) >> 16) + 1;
+               fbi->var.lower_margin = vsp - fbi->var.yres;
+               fbi->var.upper_margin = vt - vsp - fbi->var.vsync_len;
+       } else if (mode) {
+               dev_dbg(par->dev, "using supplied mode\n");
+               fb_videomode_to_var(&fbi->var, (struct fb_videomode *)mode);
+               fbi->var.bits_per_pixel = mode->def_bpp ? mode->def_bpp : 8;
+       } else {
+               int ret;
+
+               ret = fb_find_mode(&fbi->var, fbi, "640x480-16@60",
+                                  NULL, 0, NULL, 16);
+               if (ret == 0 || ret == 4) {
+                       dev_err(par->dev,
+                               "failed to get initial mode\n");
+                       return -EINVAL;
+               }
+       }
+
+       fbi->var.xoffset = 0;
+       fbi->var.yoffset = 0;
+       fbi->var.grayscale = 0;
+       fbi->var.nonstd = 0;
+       fbi->var.height = -1;
+       fbi->var.width = -1;
+       fbi->var.accel_flags = 0;
+       fbi->var.vmode = FB_VMODE_NONINTERLACED;
+       fbi->var.activate = FB_ACTIVATE_NOW;
+       fbi->flags = FBINFO_DEFAULT |
+#ifdef __BIG_ENDIAN
+                    FBINFO_FOREIGN_ENDIAN |
+#endif
+                    FBINFO_HWACCEL_XPAN |
+                    FBINFO_HWACCEL_YPAN;
+
+       /* check and possibly fix bpp */
+       if ((fbi->fbops->fb_check_var)(&fbi->var, fbi))
+               dev_err(par->dev, "check_var() failed on initial setup?\n");
+
+       fbi->fix.visual = fbi->var.bits_per_pixel == 8 ?
+                        FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+       fbi->fix.line_length = (fbi->var.xres_virtual *
+                               fbi->var.bits_per_pixel) / 8;
+       return 0;
+}
+
+/*
+ * show some display controller and cursor registers
+ */
+static ssize_t mb862xxfb_show_dispregs(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+       struct fb_info *fbi = dev_get_drvdata(dev);
+       struct mb862xxfb_par *par = fbi->par;
+       char *ptr = buf;
+       unsigned int reg;
+
+       for (reg = GC_DCM0; reg <= GC_L0DY_L0DX; reg += 4)
+               ptr += sprintf(ptr, "%08x = %08x\n",
+                              reg, inreg(disp, reg));
+
+       for (reg = GC_CPM_CUTC; reg <= GC_CUY1_CUX1; reg += 4)
+               ptr += sprintf(ptr, "%08x = %08x\n",
+                              reg, inreg(disp, reg));
+
+       for (reg = GC_DCM1; reg <= GC_L0WH_L0WW; reg += 4)
+               ptr += sprintf(ptr, "%08x = %08x\n",
+                              reg, inreg(disp, reg));
+
+       return ptr - buf;
+}
+
+static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL);
+
+irqreturn_t mb862xx_intr(int irq, void *dev_id)
+{
+       struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id;
+       unsigned long reg_ist, mask;
+
+       if (!par)
+               return IRQ_NONE;
+
+       if (par->type == BT_CARMINE) {
+               /* Get Interrupt Status */
+               reg_ist = inreg(ctrl, GC_CTRL_STATUS);
+               mask = inreg(ctrl, GC_CTRL_INT_MASK);
+               if (reg_ist == 0)
+                       return IRQ_HANDLED;
+
+               reg_ist &= mask;
+               if (reg_ist == 0)
+                       return IRQ_HANDLED;
+
+               /* Clear interrupt status */
+               outreg(ctrl, 0x0, reg_ist);
+       } else {
+               /* Get status */
+               reg_ist = inreg(host, GC_IST);
+               mask = inreg(host, GC_IMASK);
+
+               reg_ist &= mask;
+               if (reg_ist == 0)
+                       return IRQ_HANDLED;
+
+               /* Clear status */
+               outreg(host, GC_IST, ~reg_ist);
+       }
+       return IRQ_HANDLED;
+}
+
+#if defined(CONFIG_FB_MB862XX_LIME)
+/*
+ * GDC (Lime, Coral(B/Q), Mint, ...) on host bus
+ */
+static int mb862xx_gdc_init(struct mb862xxfb_par *par)
+{
+       unsigned long ccf, mmr;
+       unsigned long ver, rev;
+
+       if (!par)
+               return -ENODEV;
+
+#if defined(CONFIG_FB_PRE_INIT_FB)
+       par->pre_init = 1;
+#endif
+       par->host = par->mmio_base;
+       par->i2c = par->mmio_base + MB862XX_I2C_BASE;
+       par->disp = par->mmio_base + MB862XX_DISP_BASE;
+       par->cap = par->mmio_base + MB862XX_CAP_BASE;
+       par->draw = par->mmio_base + MB862XX_DRAW_BASE;
+       par->geo = par->mmio_base + MB862XX_GEO_BASE;
+       par->pio = par->mmio_base + MB862XX_PIO_BASE;
+
+       par->refclk = GC_DISP_REFCLK_400;
+
+       ver = inreg(host, GC_CID);
+       rev = inreg(pio, GC_REVISION);
+       if ((ver == 0x303) && (rev & 0xffffff00) == 0x20050100) {
+               dev_info(par->dev, "Fujitsu Lime v1.%d found\n",
+                        (int)rev & 0xff);
+               par->type = BT_LIME;
+               ccf = par->gc_mode ? par->gc_mode->ccf : GC_CCF_COT_100;
+               mmr = par->gc_mode ? par->gc_mode->mmr : 0x414fb7f2;
+       } else {
+               dev_info(par->dev, "? GDC, CID/Rev.: 0x%lx/0x%lx \n", ver, rev);
+               return -ENODEV;
+       }
+
+       if (!par->pre_init) {
+               outreg(host, GC_CCF, ccf);
+               udelay(200);
+               outreg(host, GC_MMR, mmr);
+               udelay(10);
+       }
+
+       /* interrupt status */
+       outreg(host, GC_IST, 0);
+       outreg(host, GC_IMASK, GC_INT_EN);
+       return 0;
+}
+
+static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev,
+                                              const struct of_device_id *id)
+{
+       struct device_node *np = ofdev->node;
+       struct device *dev = &ofdev->dev;
+       struct mb862xxfb_par *par;
+       struct fb_info *info;
+       struct resource res;
+       resource_size_t res_size;
+       unsigned long ret = -ENODEV;
+
+       if (of_address_to_resource(np, 0, &res)) {
+               dev_err(dev, "Invalid address\n");
+               return -ENXIO;
+       }
+
+       info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
+       if (info == NULL) {
+               dev_err(dev, "cannot allocate framebuffer\n");
+               return -ENOMEM;
+       }
+
+       par = info->par;
+       par->info = info;
+       par->dev = dev;
+
+       par->irq = irq_of_parse_and_map(np, 0);
+       if (par->irq == NO_IRQ) {
+               dev_err(dev, "failed to map irq\n");
+               ret = -ENODEV;
+               goto fbrel;
+       }
+
+       res_size = 1 + res.end - res.start;
+       par->res = request_mem_region(res.start, res_size, DRV_NAME);
+       if (par->res == NULL) {
+               dev_err(dev, "Cannot claim framebuffer/mmio\n");
+               ret = -ENXIO;
+               goto irqdisp;
+       }
+
+#if defined(CONFIG_LWMON5)
+       par->gc_mode = &lwmon5_gc_mode;
+#endif
+
+#if defined(CONFIG_SOCRATES)
+       par->gc_mode = &socrates_gc_mode;
+#endif
+
+       par->fb_base_phys = res.start;
+       par->mmio_base_phys = res.start + MB862XX_MMIO_BASE;
+       par->mmio_len = MB862XX_MMIO_SIZE;
+       if (par->gc_mode)
+               par->mapped_vram = par->gc_mode->max_vram;
+       else
+               par->mapped_vram = MB862XX_MEM_SIZE;
+
+       par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
+       if (par->fb_base == NULL) {
+               dev_err(dev, "Cannot map framebuffer\n");
+               goto rel_reg;
+       }
+
+       par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
+       if (par->mmio_base == NULL) {
+               dev_err(dev, "Cannot map registers\n");
+               goto fb_unmap;
+       }
+
+       dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
+               (u64)par->fb_base_phys, (ulong)par->mapped_vram);
+       dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n",
+               (u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq);
+
+       if (mb862xx_gdc_init(par))
+               goto io_unmap;
+
+       if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED,
+                       DRV_NAME, (void *)par)) {
+               dev_err(dev, "Cannot request irq\n");
+               goto io_unmap;
+       }
+
+       mb862xxfb_init_fbinfo(info);
+
+       if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
+               dev_err(dev, "Could not allocate cmap for fb_info.\n");
+               goto free_irq;
+       }
+
+       if ((info->fbops->fb_set_par)(info))
+               dev_err(dev, "set_var() failed on initial setup?\n");
+
+       if (register_framebuffer(info)) {
+               dev_err(dev, "failed to register framebuffer\n");
+               goto rel_cmap;
+       }
+
+       dev_set_drvdata(dev, info);
+
+       if (device_create_file(dev, &dev_attr_dispregs))
+               dev_err(dev, "Can't create sysfs regdump file\n");
+       return 0;
+
+rel_cmap:
+       fb_dealloc_cmap(&info->cmap);
+free_irq:
+       outreg(host, GC_IMASK, 0);
+       free_irq(par->irq, (void *)par);
+io_unmap:
+       iounmap(par->mmio_base);
+fb_unmap:
+       iounmap(par->fb_base);
+rel_reg:
+       release_mem_region(res.start, res_size);
+irqdisp:
+       irq_dispose_mapping(par->irq);
+fbrel:
+       dev_set_drvdata(dev, NULL);
+       framebuffer_release(info);
+       return ret;
+}
+
+static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev)
+{
+       struct fb_info *fbi = dev_get_drvdata(&ofdev->dev);
+       struct mb862xxfb_par *par = fbi->par;
+       resource_size_t res_size = 1 + par->res->end - par->res->start;
+       unsigned long reg;
+
+       dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
+
+       /* display off */
+       reg = inreg(disp, GC_DCM1);
+       reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
+       outreg(disp, GC_DCM1, reg);
+
+       /* disable interrupts */
+       outreg(host, GC_IMASK, 0);
+
+       free_irq(par->irq, (void *)par);
+       irq_dispose_mapping(par->irq);
+
+       device_remove_file(&ofdev->dev, &dev_attr_dispregs);
+
+       unregister_framebuffer(fbi);
+       fb_dealloc_cmap(&fbi->cmap);
+
+       iounmap(par->mmio_base);
+       iounmap(par->fb_base);
+
+       dev_set_drvdata(&ofdev->dev, NULL);
+       release_mem_region(par->res->start, res_size);
+       framebuffer_release(fbi);
+       return 0;
+}
+
+/*
+ * common types
+ */
+static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = {
+       { .compatible = "fujitsu,MB86276", },
+       { .compatible = "fujitsu,lime", },
+       { .compatible = "fujitsu,MB86277", },
+       { .compatible = "fujitsu,mint", },
+       { .compatible = "fujitsu,MB86293", },
+       { .compatible = "fujitsu,MB86294", },
+       { .compatible = "fujitsu,coral", },
+       { /* end */ }
+};
+
+static struct of_platform_driver of_platform_mb862xxfb_driver = {
+       .owner          = THIS_MODULE,
+       .name           = DRV_NAME,
+       .match_table    = of_platform_mb862xx_tbl,
+       .probe          = of_platform_mb862xx_probe,
+       .remove         = __devexit_p(of_platform_mb862xx_remove),
+};
+#endif
+
+#if defined(CONFIG_FB_MB862XX_PCI_GDC)
+static int coralp_init(struct mb862xxfb_par *par)
+{
+       int cn, ver;
+
+       par->host = par->mmio_base;
+       par->i2c = par->mmio_base + MB862XX_I2C_BASE;
+       par->disp = par->mmio_base + MB862XX_DISP_BASE;
+       par->cap = par->mmio_base + MB862XX_CAP_BASE;
+       par->draw = par->mmio_base + MB862XX_DRAW_BASE;
+       par->geo = par->mmio_base + MB862XX_GEO_BASE;
+       par->pio = par->mmio_base + MB862XX_PIO_BASE;
+
+       par->refclk = GC_DISP_REFCLK_400;
+
+       ver = inreg(host, GC_CID);
+       cn = (ver & GC_CID_CNAME_MSK) >> 8;
+       ver = ver & GC_CID_VERSION_MSK;
+       if (cn == 3) {
+               dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\
+                        (ver == 6) ? "P" : (ver == 8) ? "PA" : "?",
+                        par->pdev->revision);
+               outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133);
+               udelay(200);
+               outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL);
+               udelay(10);
+               /* Clear interrupt status */
+               outreg(host, GC_IST, 0);
+       } else {
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static int init_dram_ctrl(struct mb862xxfb_par *par)
+{
+       unsigned long i = 0;
+
+       /*
+        * Set io mode first! Spec. says IC may be destroyed
+        * if not set to SSTL2/LVCMOS before init.
+        */
+       outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0);
+
+       /* DRAM init */
+       outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD);
+       outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE);
+       outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2,
+              GC_EVB_DCTL_REFRESH_SETTIME2);
+       outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1);
+       outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1);
+       outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES);
+
+       /* DLL reset done? */
+       while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) {
+               udelay(GC_DCTL_INIT_WAIT_INTERVAL);
+               if (i++ > GC_DCTL_INIT_WAIT_CNT) {
+                       dev_err(par->dev, "VRAM init failed.\n");
+                       return -EINVAL;
+               }
+       }
+       outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST);
+       outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST);
+       return 0;
+}
+
+static int carmine_init(struct mb862xxfb_par *par)
+{
+       unsigned long reg;
+
+       par->ctrl = par->mmio_base + MB86297_CTRL_BASE;
+       par->i2c = par->mmio_base + MB86297_I2C_BASE;
+       par->disp = par->mmio_base + MB86297_DISP0_BASE;
+       par->disp1 = par->mmio_base + MB86297_DISP1_BASE;
+       par->cap = par->mmio_base + MB86297_CAP0_BASE;
+       par->cap1 = par->mmio_base + MB86297_CAP1_BASE;
+       par->draw = par->mmio_base + MB86297_DRAW_BASE;
+       par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE;
+       par->wrback = par->mmio_base + MB86297_WRBACK_BASE;
+
+       par->refclk = GC_DISP_REFCLK_533;
+
+       /* warm up */
+       reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0;
+       outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
+
+       /* check for engine module revision */
+       if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION)
+               dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n",
+                        par->pdev->revision);
+       else
+               goto err_init;
+
+       reg &= ~GC_CTRL_CLK_EN_2D3D;
+       outreg(ctrl, GC_CTRL_CLK_ENABLE, reg);
+
+       /* set up vram */
+       if (init_dram_ctrl(par) < 0)
+               goto err_init;
+
+       outreg(ctrl, GC_CTRL_INT_MASK, 0);
+       return 0;
+
+err_init:
+       outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
+       return -EINVAL;
+}
+
+static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par)
+{
+       switch (par->type) {
+       case BT_CORALP:
+               return coralp_init(par);
+       case BT_CARMINE:
+               return carmine_init(par);
+       default:
+               return -ENODEV;
+       }
+}
+
+#define CHIP_ID(id)    \
+       { PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) }
+
+static struct pci_device_id mb862xx_pci_tbl[] __devinitdata = {
+       /* MB86295/MB86296 */
+       CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP),
+       CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA),
+       /* MB86297 */
+       CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE),
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl);
+
+static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
+                                      const struct pci_device_id *ent)
+{
+       struct mb862xxfb_par *par;
+       struct fb_info *info;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       ret = pci_enable_device(pdev);
+       if (ret < 0) {
+               dev_err(dev, "Cannot enable PCI device\n");
+               goto out;
+       }
+
+       info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev);
+       if (!info) {
+               dev_err(dev, "framebuffer alloc failed\n");
+               ret = -ENOMEM;
+               goto dis_dev;
+       }
+
+       par = info->par;
+       par->info = info;
+       par->dev = dev;
+       par->pdev = pdev;
+       par->irq = pdev->irq;
+
+       ret = pci_request_regions(pdev, DRV_NAME);
+       if (ret < 0) {
+               dev_err(dev, "Cannot reserve region(s) for PCI device\n");
+               goto rel_fb;
+       }
+
+       switch (pdev->device) {
+       case PCI_DEVICE_ID_FUJITSU_CORALP:
+       case PCI_DEVICE_ID_FUJITSU_CORALPA:
+               par->fb_base_phys = pci_resource_start(par->pdev, 0);
+               par->mapped_vram = CORALP_MEM_SIZE;
+               par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE;
+               par->mmio_len = MB862XX_MMIO_SIZE;
+               par->type = BT_CORALP;
+               break;
+       case PCI_DEVICE_ID_FUJITSU_CARMINE:
+               par->fb_base_phys = pci_resource_start(par->pdev, 2);
+               par->mmio_base_phys = pci_resource_start(par->pdev, 3);
+               par->mmio_len = pci_resource_len(par->pdev, 3);
+               par->mapped_vram = CARMINE_MEM_SIZE;
+               par->type = BT_CARMINE;
+               break;
+       default:
+               /* should never occur */
+               goto rel_reg;
+       }
+
+       par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
+       if (par->fb_base == NULL) {
+               dev_err(dev, "Cannot map framebuffer\n");
+               goto rel_reg;
+       }
+
+       par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len);
+       if (par->mmio_base == NULL) {
+               dev_err(dev, "Cannot map registers\n");
+               ret = -EIO;
+               goto fb_unmap;
+       }
+
+       dev_dbg(dev, "fb phys 0x%llx 0x%lx\n",
+               (u64)par->fb_base_phys, (ulong)par->mapped_vram);
+       dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
+               (u64)par->mmio_base_phys, (ulong)par->mmio_len);
+
+       if (mb862xx_pci_gdc_init(par))
+               goto io_unmap;
+
+       if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED,
+                       DRV_NAME, (void *)par)) {
+               dev_err(dev, "Cannot request irq\n");
+               goto io_unmap;
+       }
+
+       mb862xxfb_init_fbinfo(info);
+
+       if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) {
+               dev_err(dev, "Could not allocate cmap for fb_info.\n");
+               ret = -ENOMEM;
+               goto free_irq;
+       }
+
+       if ((info->fbops->fb_set_par)(info))
+               dev_err(dev, "set_var() failed on initial setup?\n");
+
+       ret = register_framebuffer(info);
+       if (ret < 0) {
+               dev_err(dev, "failed to register framebuffer\n");
+               goto rel_cmap;
+       }
+
+       pci_set_drvdata(pdev, info);
+
+       if (device_create_file(dev, &dev_attr_dispregs))
+               dev_err(dev, "Can't create sysfs regdump file\n");
+
+       if (par->type == BT_CARMINE)
+               outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN);
+       else
+               outreg(host, GC_IMASK, GC_INT_EN);
+
+       return 0;
+
+rel_cmap:
+       fb_dealloc_cmap(&info->cmap);
+free_irq:
+       free_irq(par->irq, (void *)par);
+io_unmap:
+       iounmap(par->mmio_base);
+fb_unmap:
+       iounmap(par->fb_base);
+rel_reg:
+       pci_release_regions(pdev);
+rel_fb:
+       framebuffer_release(info);
+dis_dev:
+       pci_disable_device(pdev);
+out:
+       return ret;
+}
+
+static void __devexit mb862xx_pci_remove(struct pci_dev *pdev)
+{
+       struct fb_info *fbi = pci_get_drvdata(pdev);
+       struct mb862xxfb_par *par = fbi->par;
+       unsigned long reg;
+
+       dev_dbg(fbi->dev, "%s release\n", fbi->fix.id);
+
+       /* display off */
+       reg = inreg(disp, GC_DCM1);
+       reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E);
+       outreg(disp, GC_DCM1, reg);
+
+       if (par->type == BT_CARMINE) {
+               outreg(ctrl, GC_CTRL_INT_MASK, 0);
+               outreg(ctrl, GC_CTRL_CLK_ENABLE, 0);
+       } else {
+               outreg(host, GC_IMASK, 0);
+       }
+
+       device_remove_file(&pdev->dev, &dev_attr_dispregs);
+
+       pci_set_drvdata(pdev, NULL);
+       unregister_framebuffer(fbi);
+       fb_dealloc_cmap(&fbi->cmap);
+
+       free_irq(par->irq, (void *)par);
+       iounmap(par->mmio_base);
+       iounmap(par->fb_base);
+
+       pci_release_regions(pdev);
+       framebuffer_release(fbi);
+       pci_disable_device(pdev);
+}
+
+static struct pci_driver mb862xxfb_pci_driver = {
+       .name           = DRV_NAME,
+       .id_table       = mb862xx_pci_tbl,
+       .probe          = mb862xx_pci_probe,
+       .remove         = __devexit_p(mb862xx_pci_remove),
+};
+#endif
+
+static int __devinit mb862xxfb_init(void)
+{
+       int ret = -ENODEV;
+
+#if defined(CONFIG_FB_MB862XX_LIME)
+       ret = of_register_platform_driver(&of_platform_mb862xxfb_driver);
+#endif
+#if defined(CONFIG_FB_MB862XX_PCI_GDC)
+       ret = pci_register_driver(&mb862xxfb_pci_driver);
+#endif
+       return ret;
+}
+
+static void __exit mb862xxfb_exit(void)
+{
+#if defined(CONFIG_FB_MB862XX_LIME)
+       of_unregister_platform_driver(&of_platform_mb862xxfb_driver);
+#endif
+#if defined(CONFIG_FB_MB862XX_PCI_GDC)
+       pci_unregister_driver(&mb862xxfb_pci_driver);
+#endif
+}
+
+module_init(mb862xxfb_init);
+module_exit(mb862xxfb_exit);
+
+MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h
new file mode 100644 (file)
index 0000000..c4c8f4d
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __MB862XX_H__
+#define __MB862XX_H__
+
+#define PCI_VENDOR_ID_FUJITSU_LIMITED  0x10cf
+#define PCI_DEVICE_ID_FUJITSU_CORALP   0x2019
+#define PCI_DEVICE_ID_FUJITSU_CORALPA  0x201e
+#define PCI_DEVICE_ID_FUJITSU_CARMINE  0x202b
+
+#define GC_MMR_CORALP_EVB_VAL          0x11d7fa13
+
+enum gdctype {
+       BT_NONE,
+       BT_LIME,
+       BT_MINT,
+       BT_CORAL,
+       BT_CORALP,
+       BT_CARMINE,
+};
+
+struct mb862xx_gc_mode {
+       struct fb_videomode     def_mode;       /* mode of connected display */
+       unsigned int            def_bpp;        /* default depth */
+       unsigned long           max_vram;       /* connected SDRAM size */
+       unsigned long           ccf;            /* gdc clk */
+       unsigned long           mmr;            /* memory mode for SDRAM */
+};
+
+/* private data */
+struct mb862xxfb_par {
+       struct fb_info          *info;          /* fb info head */
+       struct device           *dev;
+       struct pci_dev          *pdev;
+       struct resource         *res;           /* framebuffer/mmio resource */
+
+       resource_size_t         fb_base_phys;   /* fb base, 36-bit PPC440EPx */
+       resource_size_t         mmio_base_phys; /* io base addr */
+       void __iomem            *fb_base;       /* remapped framebuffer */
+       void __iomem            *mmio_base;     /* remapped registers */
+       size_t                  mapped_vram;    /* length of remapped vram */
+       size_t                  mmio_len;       /* length of register region */
+
+       void __iomem            *host;          /* relocatable reg. bases */
+       void __iomem            *i2c;
+       void __iomem            *disp;
+       void __iomem            *disp1;
+       void __iomem            *cap;
+       void __iomem            *cap1;
+       void __iomem            *draw;
+       void __iomem            *geo;
+       void __iomem            *pio;
+       void __iomem            *ctrl;
+       void __iomem            *dram_ctrl;
+       void __iomem            *wrback;
+
+       unsigned int            irq;
+       unsigned int            type;           /* GDC type */
+       unsigned int            refclk;         /* disp. reference clock */
+       struct mb862xx_gc_mode  *gc_mode;       /* GDC mode init data */
+       int                     pre_init;       /* don't init display if 1 */
+
+       u32                     pseudo_palette[16];
+};
+
+#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC)
+#error "Select Lime GDC or CoralP/Carmine support, but not both together"
+#endif
+#if defined(CONFIG_FB_MB862XX_LIME)
+#define gdc_read       __raw_readl
+#define gdc_write      __raw_writel
+#else
+#define gdc_read       readl
+#define gdc_write      writel
+#endif
+
+#define inreg(type, off)       \
+       gdc_read((par->type + (off)))
+
+#define outreg(type, off, val) \
+       gdc_write((val), (par->type + (off)))
+
+#define pack(a, b)     (((a) << 16) | (b))
+
+#endif
index 1a22fe782a27b57205a3ce21dfa1c440d84b1835..4fd3fa5546b12282e5b25e521e5a7d5bb5bb829e 100644 (file)
@@ -67,11 +67,11 @@ config AT91RM9200_WATCHDOG
          system when the timeout is reached.
 
 config AT91SAM9X_WATCHDOG
-       tristate "AT91SAM9X watchdog"
-       depends on WATCHDOG && (ARCH_AT91SAM9260 || ARCH_AT91SAM9261)
+       tristate "AT91SAM9X / AT91CAP9 watchdog"
+       depends on ARCH_AT91 && !ARCH_AT91RM9200
        help
-         Watchdog timer embedded into AT91SAM9X chips. This will reboot your
-         system when the timeout is reached.
+         Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will
+         reboot your system when the timeout is reached.
 
 config 21285_WATCHDOG
        tristate "DC21285 watchdog"
index b4babfc3158635bd0c98e069dcc0c4259db2f641..b1da287f90ecc24bc5395234a5d71198f0fb630a 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
 
-#include <asm/arch/at91_wdt.h>
+#include <mach/at91_wdt.h>
 
 #define DRV_NAME "AT91SAM9 Watchdog"
 
index 8c83abc73400c48ee6a21013af1548de8f275f57..a0fb5eac407c78b07f54f281db70664b78f761a6 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 #include <linux/mutex.h>
-#include <linux/highmem.h>
 #include <linux/list.h>
 #include <linux/sysdev.h>
 
index 2168c902d5ca61027236bb75812591d16575ec1d..d9f8afe6f0c4b806ab7af81f8bcbc286758297cd 100644 (file)
@@ -81,8 +81,6 @@ obj-$(CONFIG_HUGETLBFS)               += hugetlbfs/
 obj-$(CONFIG_CODA_FS)          += coda/
 obj-$(CONFIG_MINIX_FS)         += minix/
 obj-$(CONFIG_FAT_FS)           += fat/
-obj-$(CONFIG_MSDOS_FS)         += msdos/
-obj-$(CONFIG_VFAT_FS)          += vfat/
 obj-$(CONFIG_BFS_FS)           += bfs/
 obj-$(CONFIG_ISO9660_FS)       += isofs/
 obj-$(CONFIG_HFSPLUS_FS)       += hfsplus/ # Before hfs to find wrapped HFS+
index 625abf5422e2bb5f721b8921c0c89a2a5bec40a6..33bf8cbfd05172cc020200d4f4eec08d23eab420 100644 (file)
@@ -128,9 +128,10 @@ static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
  */
 static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
 {
-       int err = -EINVAL;
+       int err;
 
-       if (check_dev_ioctl_version(cmd, param)) {
+       err = check_dev_ioctl_version(cmd, param);
+       if (err) {
                AUTOFS_WARN("invalid device control module version "
                     "supplied for cmd(0x%08x)", cmd);
                goto out;
index cde2f8e8935a680bd62243dcc4b92f6909ea7789..4b6fb3f628c04be94a2863ad5f7ee05feace9c44 100644 (file)
@@ -56,12 +56,23 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
        mntget(mnt);
        dget(dentry);
 
-       if (!autofs4_follow_mount(&mnt, &dentry))
+       if (!follow_down(&mnt, &dentry))
                goto done;
 
-       /* This is an autofs submount, we can't expire it */
-       if (is_autofs4_dentry(dentry))
-               goto done;
+       if (is_autofs4_dentry(dentry)) {
+               struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+
+               /* This is an autofs submount, we can't expire it */
+               if (sbi->type == AUTOFS_TYPE_INDIRECT)
+                       goto done;
+
+               /*
+                * Otherwise it's an offset mount and we need to check
+                * if we can umount its mount, if there is one.
+                */
+               if (!d_mountpoint(dentry))
+                       goto done;
+       }
 
        /* Update the expiry counter if fs is busy */
        if (!may_umount_tree(mnt)) {
index 88a776fa0ef6e29bc67322f3184cb04f31b2248d..db831efbdbbdcc0d2b1298af4e3055916357fee2 100644 (file)
@@ -986,7 +986,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part);
 static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
 {
        struct gendisk *disk;
-       struct hd_struct *part = NULL;
        int ret;
        int partno;
        int perm = 0;
@@ -1004,24 +1003,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                return ret;
        }
 
-       ret = -ENXIO;
-
        lock_kernel();
 
+       ret = -ENXIO;
        disk = get_gendisk(bdev->bd_dev, &partno);
        if (!disk)
                goto out_unlock_kernel;
-       part = disk_get_part(disk, partno);
-       if (!part)
-               goto out_unlock_kernel;
 
        mutex_lock_nested(&bdev->bd_mutex, for_part);
        if (!bdev->bd_openers) {
                bdev->bd_disk = disk;
-               bdev->bd_part = part;
                bdev->bd_contains = bdev;
                if (!partno) {
                        struct backing_dev_info *bdi;
+
+                       ret = -ENXIO;
+                       bdev->bd_part = disk_get_part(disk, partno);
+                       if (!bdev->bd_part)
+                               goto out_clear;
+
                        if (disk->fops->open) {
                                ret = disk->fops->open(bdev, mode);
                                if (ret)
@@ -1049,18 +1049,17 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                        bdev->bd_contains = whole;
                        bdev->bd_inode->i_data.backing_dev_info =
                           whole->bd_inode->i_data.backing_dev_info;
+                       bdev->bd_part = disk_get_part(disk, partno);
                        if (!(disk->flags & GENHD_FL_UP) ||
-                           !part || !part->nr_sects) {
+                           !bdev->bd_part || !bdev->bd_part->nr_sects) {
                                ret = -ENXIO;
                                goto out_clear;
                        }
-                       bd_set_size(bdev, (loff_t)part->nr_sects << 9);
+                       bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
                }
        } else {
-               disk_put_part(part);
                put_disk(disk);
                module_put(disk->fops->owner);
-               part = NULL;
                disk = NULL;
                if (bdev->bd_contains == bdev) {
                        if (bdev->bd_disk->fops->open) {
@@ -1080,6 +1079,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
        return 0;
 
  out_clear:
+       disk_put_part(bdev->bd_part);
        bdev->bd_disk = NULL;
        bdev->bd_part = NULL;
        bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
@@ -1091,7 +1091,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
  out_unlock_kernel:
        unlock_kernel();
 
-       disk_put_part(part);
        if (disk)
                module_put(disk->fops->owner);
        put_disk(disk);
index 8f528ea24c4813fc9c780d2c600262210383db6f..8855331b2fba551984776b30b1747b80a98607f1 100644 (file)
@@ -4,7 +4,11 @@ Various fixes to make delete of open files behavior more predictable
 (when delete of an open file fails we mark the file as "delete-on-close"
 in a way that more servers accept, but only if we can first rename the
 file to a temporary name).  Add experimental support for more safely
-handling fcntl(F_SETLEASE).
+handling fcntl(F_SETLEASE).  Convert cifs to using blocking tcp
+sends, and also let tcp autotune the socket send and receive buffers.
+This reduces the number of EAGAIN errors returned by TCP/IP in
+high stress workloads (and the number of retries on socket writes
+when sending large SMBWriteX requests).
 
 Version 1.54
 ------------
index c791e5b5a914e087fa5c5a20a3a48d58f7fa4cc0..1cb1189f24e0e3417751d91838bf29e0968e5dea 100644 (file)
@@ -141,6 +141,8 @@ struct TCP_Server_Info {
        char versionMajor;
        char versionMinor;
        bool svlocal:1;                 /* local server or remote */
+       bool noblocksnd;                /* use blocking sendmsg */
+       bool noautotune;                /* do not autotune send buf sizes */
        atomic_t socketUseCount; /* number of open cifs sessions on socket */
        atomic_t inFlight;  /* number of requests on the wire to server */
 #ifdef CONFIG_CIFS_STATS2
index 0cff7fe986e8e4e39595b9da658789b84904a4ea..6f21ecb85ce517b07d36d973cfb030d478e08ebf 100644 (file)
@@ -36,7 +36,7 @@ extern void cifs_buf_release(void *);
 extern struct smb_hdr *cifs_small_buf_get(void);
 extern void cifs_small_buf_release(void *);
 extern int smb_send(struct socket *, struct smb_hdr *,
-                       unsigned int /* length */ , struct sockaddr *);
+                       unsigned int /* length */ , struct sockaddr *, bool);
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid));
index 843a85fb8b9ac8a1189016be9ac59f6b0b8767f4..d5eac48fc41525494d017afd84d14d3d550b1cd8 100644 (file)
@@ -1536,7 +1536,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        __u32 bytes_sent;
        __u16 byte_count;
 
-       /* cFYI(1,("write at %lld %d bytes",offset,count));*/
+       /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
        if (tcon->ses == NULL)
                return -ECONNABORTED;
 
index 71b7661e2260229efc1fa8eadd7ebf187a5ec8a7..e9f9248cb3feff13deeeb4d5eeae1d2a65f79ebe 100644 (file)
@@ -92,6 +92,8 @@ struct smb_vol {
        bool seal:1;       /* request transport encryption on share */
        bool nodfs:1;      /* Do not request DFS, even if available */
        bool local_lease:1; /* check leases only on local system, not remote */
+       bool noblocksnd:1;
+       bool noautotune:1;
        unsigned int rsize;
        unsigned int wsize;
        unsigned int sockopt;
@@ -102,9 +104,11 @@ struct smb_vol {
 static int ipv4_connect(struct sockaddr_in *psin_server,
                        struct socket **csocket,
                        char *netb_name,
-                       char *server_netb_name);
+                       char *server_netb_name,
+                       bool noblocksnd,
+                       bool nosndbuf); /* ipv6 never set sndbuf size */
 static int ipv6_connect(struct sockaddr_in6 *psin_server,
-                       struct socket **csocket);
+                       struct socket **csocket, bool noblocksnd);
 
 
        /*
@@ -191,12 +195,13 @@ cifs_reconnect(struct TCP_Server_Info *server)
                try_to_freeze();
                if (server->protocolType == IPV6) {
                        rc = ipv6_connect(&server->addr.sockAddr6,
-                                         &server->ssocket);
+                                         &server->ssocket, server->noautotune);
                } else {
                        rc = ipv4_connect(&server->addr.sockAddr,
                                        &server->ssocket,
                                        server->workstation_RFC1001_name,
-                                       server->server_RFC1001_name);
+                                       server->server_RFC1001_name,
+                                       server->noblocksnd, server->noautotune);
                }
                if (rc) {
                        cFYI(1, ("reconnect error %d", rc));
@@ -1192,6 +1197,10 @@ cifs_parse_mount_options(char *options, const char *devname,
                        /* ignore */
                } else if (strnicmp(data, "rw", 2) == 0) {
                        vol->rw = true;
+               } else if (strnicmp(data, "noblocksend", 11) == 0) {
+                       vol->noblocksnd = 1;
+               } else if (strnicmp(data, "noautotune", 10) == 0) {
+                       vol->noautotune = 1;
                } else if ((strnicmp(data, "suid", 4) == 0) ||
                                   (strnicmp(data, "nosuid", 6) == 0) ||
                                   (strnicmp(data, "exec", 4) == 0) ||
@@ -1518,7 +1527,8 @@ static void rfc1002mangle(char *target, char *source, unsigned int length)
 
 static int
 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
-            char *netbios_name, char *target_name)
+            char *netbios_name, char *target_name,
+            bool noblocksnd, bool noautotune)
 {
        int rc = 0;
        int connected = 0;
@@ -1590,11 +1600,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
                 (*csocket)->sk->sk_sndbuf,
                 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
        (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
+       if (!noblocksnd)
+               (*csocket)->sk->sk_sndtimeo = 3 * HZ;
+
        /* make the bufsizes depend on wsize/rsize and max requests */
-       if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
-               (*csocket)->sk->sk_sndbuf = 200 * 1024;
-       if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
-               (*csocket)->sk->sk_rcvbuf = 140 * 1024;
+       if (noautotune) {
+               if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
+                       (*csocket)->sk->sk_sndbuf = 200 * 1024;
+               if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
+                       (*csocket)->sk->sk_rcvbuf = 140 * 1024;
+       }
 
        /* send RFC1001 sessinit */
        if (psin_server->sin_port == htons(RFC1001_PORT)) {
@@ -1631,7 +1646,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
                        /* sizeof RFC1002_SESSION_REQUEST with no scope */
                        smb_buf->smb_buf_length = 0x81000044;
                        rc = smb_send(*csocket, smb_buf, 0x44,
-                               (struct sockaddr *)psin_server);
+                               (struct sockaddr *)psin_server, noblocksnd);
                        kfree(ses_init_buf);
                        msleep(1); /* RFC1001 layer in at least one server
                                      requires very short break before negprot
@@ -1651,7 +1666,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
 }
 
 static int
-ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
+ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket,
+            bool noblocksnd)
 {
        int rc = 0;
        int connected = 0;
@@ -1720,6 +1736,9 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
                the default. sock_setsockopt not used because it expects
                user space buffer */
        (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
+       if (!noblocksnd)
+               (*csocket)->sk->sk_sndtimeo = 3 * HZ;
+
 
        return rc;
 }
@@ -1983,11 +2002,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        cFYI(1, ("attempting ipv6 connect"));
                        /* BB should we allow ipv6 on port 139? */
                        /* other OS never observed in Wild doing 139 with v6 */
-                       rc = ipv6_connect(&sin_server6, &csocket);
+                       rc = ipv6_connect(&sin_server6, &csocket,
+                                       volume_info.noblocksnd);
                } else
                        rc = ipv4_connect(&sin_server, &csocket,
                                  volume_info.source_rfc1001_name,
-                                 volume_info.target_rfc1001_name);
+                                 volume_info.target_rfc1001_name,
+                                 volume_info.noblocksnd,
+                                 volume_info.noautotune);
                if (rc < 0) {
                        cERROR(1, ("Error connecting to IPv4 socket. "
                                   "Aborting operation"));
@@ -2002,6 +2024,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                        sock_release(csocket);
                        goto out;
                } else {
+                       srvTcp->noblocksnd = volume_info.noblocksnd;
+                       srvTcp->noautotune = volume_info.noautotune;
                        memcpy(&srvTcp->addr.sockAddr, &sin_server,
                                sizeof(struct sockaddr_in));
                        atomic_set(&srvTcp->inFlight, 0);
index 62d8bd8f14c086f1c9f53640b9144f1cca349289..ead1a3bb02564722f98e3f93aa068ade04022503 100644 (file)
@@ -1824,7 +1824,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
        pTcon = cifs_sb->tcon;
 
        pagevec_init(&lru_pvec, 0);
-               cFYI(DBG2, ("rpages: num pages %d", num_pages));
+       cFYI(DBG2, ("rpages: num pages %d", num_pages));
        for (i = 0; i < num_pages; ) {
                unsigned contig_pages;
                struct page *tmp_page;
index d54fa8aeaea9fda413091776021cbee00cccc4f8..ff8c68de4a9205a9d0cd592d8a0c58872b0e8e65 100644 (file)
@@ -1361,9 +1361,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
 
                if (tmprc == 0 && (info_buf_source->UniqueId ==
-                                  info_buf_target->UniqueId))
+                                  info_buf_target->UniqueId)) {
                        /* same file, POSIX says that this is a noop */
+                       rc = 0;
                        goto cifs_rename_exit;
+               }
        } /* else ... BB we could add the same check for Windows by
                     checking the UniqueId via FILE_INTERNAL_INFO */
 
index bf0e6d8e382a6a4286a61dc748bd73ef4810e48b..ff8243a8fe3e955757cf087d53c6dbd5bc6befc1 100644 (file)
@@ -161,7 +161,7 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
 
 int
 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
-        unsigned int smb_buf_length, struct sockaddr *sin)
+        unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd)
 {
        int rc = 0;
        int i = 0;
@@ -178,7 +178,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
        smb_msg.msg_namelen = sizeof(struct sockaddr);
        smb_msg.msg_control = NULL;
        smb_msg.msg_controllen = 0;
-       smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+       if (noblocksnd)
+               smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
+       else
+               smb_msg.msg_flags = MSG_NOSIGNAL;
 
        /* smb header is converted in header_assemble. bcc and rest of SMB word
           area, and byte area if necessary, is converted to littleendian in
@@ -229,8 +232,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
 }
 
 static int
-smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
-         struct sockaddr *sin)
+smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
+         struct sockaddr *sin, bool noblocksnd)
 {
        int rc = 0;
        int i = 0;
@@ -240,6 +243,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
        unsigned int total_len;
        int first_vec = 0;
        unsigned int smb_buf_length = smb_buffer->smb_buf_length;
+       struct socket *ssocket = server->ssocket;
 
        if (ssocket == NULL)
                return -ENOTSOCK; /* BB eventually add reconnect code here */
@@ -248,7 +252,10 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
        smb_msg.msg_namelen = sizeof(struct sockaddr);
        smb_msg.msg_control = NULL;
        smb_msg.msg_controllen = 0;
-       smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+       if (noblocksnd)
+               smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
+       else
+               smb_msg.msg_flags = MSG_NOSIGNAL;
 
        /* smb header is converted in header_assemble. bcc and rest of SMB word
           area, and byte area if necessary, is converted to littleendian in
@@ -283,8 +290,11 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
                if (rc < 0)
                        break;
 
-               if (rc >= total_len) {
-                       WARN_ON(rc > total_len);
+               if (rc == total_len) {
+                       total_len = 0;
+                       break;
+               } else if (rc > total_len) {
+                       cERROR(1, ("sent %d requested %d", rc, total_len));
                        break;
                }
                if (rc == 0) {
@@ -312,6 +322,16 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
                i = 0; /* in case we get ENOSPC on the next send */
        }
 
+       if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
+               cFYI(1, ("partial send (%d remaining), terminating session",
+                       total_len));
+               /* If we have only sent part of an SMB then the next SMB
+                  could be taken as the remainder of this one.  We need
+                  to kill the socket so the server throws away the partial
+                  SMB */
+               server->tcpStatus = CifsNeedReconnect;
+       }
+
        if (rc < 0) {
                cERROR(1, ("Error %d sending data on socket to server", rc));
        } else
@@ -518,8 +538,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 #ifdef CONFIG_CIFS_STATS2
        atomic_inc(&ses->server->inSend);
 #endif
-       rc = smb_send2(ses->server->ssocket, iov, n_vec,
-                     (struct sockaddr *) &(ses->server->addr.sockAddr));
+       rc = smb_send2(ses->server, iov, n_vec,
+                     (struct sockaddr *) &(ses->server->addr.sockAddr),
+                      ses->server->noblocksnd);
 #ifdef CONFIG_CIFS_STATS2
        atomic_dec(&ses->server->inSend);
        midQ->when_sent = jiffies;
@@ -711,7 +732,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
        atomic_inc(&ses->server->inSend);
 #endif
        rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
-                     (struct sockaddr *) &(ses->server->addr.sockAddr));
+                     (struct sockaddr *) &(ses->server->addr.sockAddr),
+                     ses->server->noblocksnd);
 #ifdef CONFIG_CIFS_STATS2
        atomic_dec(&ses->server->inSend);
        midQ->when_sent = jiffies;
@@ -851,7 +873,8 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
                return rc;
        }
        rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
-             (struct sockaddr *) &(ses->server->addr.sockAddr));
+             (struct sockaddr *) &(ses->server->addr.sockAddr),
+             ses->server->noblocksnd);
        up(&ses->server->tcpSem);
        return rc;
 }
@@ -941,7 +964,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
        atomic_inc(&ses->server->inSend);
 #endif
        rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
-                     (struct sockaddr *) &(ses->server->addr.sockAddr));
+                     (struct sockaddr *) &(ses->server->addr.sockAddr),
+                     ses->server->noblocksnd);
 #ifdef CONFIG_CIFS_STATS2
        atomic_dec(&ses->server->inSend);
        midQ->when_sent = jiffies;
index e5717a4fae67740459104b9da4ba8b1f6a79a4ef..5dec6d1356c4b07477bb40f68305c0d9de89258b 100644 (file)
@@ -2390,13 +2390,12 @@ static void ext3_write_super (struct super_block * sb)
 
 static int ext3_sync_fs(struct super_block *sb, int wait)
 {
-       tid_t target;
-
        sb->s_dirt = 0;
-       if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
-               if (wait)
-                       log_wait_commit(EXT3_SB(sb)->s_journal, target);
-       }
+       if (wait)
+               ext3_force_commit(sb);
+       else
+               journal_start_commit(EXT3_SB(sb)->s_journal, NULL);
+
        return 0;
 }
 
index fe34d74cfb19f89bd8435690511b54529982d984..2a117e286e5420c6d5567961a14b340162b14a67 100644 (file)
@@ -718,6 +718,8 @@ got:
                        gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT);
                        free = ext4_free_blocks_after_init(sb, group, gdp);
                        gdp->bg_free_blocks_count = cpu_to_le16(free);
+                       gdp->bg_checksum = ext4_group_desc_csum(sbi, group,
+                                                               gdp);
                }
                spin_unlock(sb_bgl_lock(sbi, group));
 
index 8dbf6953845ba61097703006553c34d1d83bd81f..be21a5ae33cb01261a8fe1ce0e2377654a940d3b 100644 (file)
@@ -2329,6 +2329,8 @@ static int ext4_da_writepage(struct page *page,
                        unlock_page(page);
                        return 0;
                }
+               /* now mark the buffer_heads as dirty and uptodate */
+               block_commit_write(page, 0, PAGE_CACHE_SIZE);
        }
 
        if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
@@ -4580,9 +4582,10 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
 static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk)
 {
        if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
-               return ext4_indirect_trans_blocks(inode, nrblocks, 0);
-       return ext4_ext_index_trans_blocks(inode, nrblocks, 0);
+               return ext4_indirect_trans_blocks(inode, nrblocks, chunk);
+       return ext4_ext_index_trans_blocks(inode, nrblocks, chunk);
 }
+
 /*
  * Account for index blocks, block groups bitmaps and block group
  * descriptor blocks if modify datablocks and index blocks
index dfe17a1340523c9c10d3c1f14a1077b4fd6939c9..444ad998f72e77ab663730c6f59e43a7b9ac1e57 100644 (file)
@@ -4441,6 +4441,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
                else if (block >= (entry->start_blk + entry->count))
                        n = &(*n)->rb_right;
                else {
+                       ext4_unlock_group(sb, group);
                        ext4_error(sb, __func__,
                            "Double free of blocks %d (%d %d)\n",
                            block, entry->start_blk, entry->count);
index 994859df010edb3205f8e86aa7366924a9d0b144..e4a241c65dbeb79d189d84b08010430274c6755f 100644 (file)
@@ -1458,9 +1458,8 @@ static int ext4_fill_flex_info(struct super_block *sb)
 
        /* We allocate both existing and potentially added groups */
        flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
-                           ((sbi->s_es->s_reserved_gdt_blocks +1 ) <<
-                             EXT4_DESC_PER_BLOCK_BITS(sb))) /
-                          groups_per_flex;
+                       ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
+                             EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex;
        sbi->s_flex_groups = kzalloc(flex_group_count *
                                     sizeof(struct flex_groups), GFP_KERNEL);
        if (sbi->s_flex_groups == NULL) {
@@ -2885,12 +2884,9 @@ int ext4_force_commit(struct super_block *sb)
 /*
  * Ext4 always journals updates to the superblock itself, so we don't
  * have to propagate any other updates to the superblock on disk at this
- * point.  Just start an async writeback to get the buffers on their way
- * to the disk.
- *
- * This implicitly triggers the writebehind on sync().
+ * point.  (We can probably nuke this function altogether, and remove
+ * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...)
  */
-
 static void ext4_write_super(struct super_block *sb)
 {
        if (mutex_trylock(&sb->s_lock) != 0)
@@ -2900,15 +2896,15 @@ static void ext4_write_super(struct super_block *sb)
 
 static int ext4_sync_fs(struct super_block *sb, int wait)
 {
-       tid_t target;
+       int ret = 0;
 
        trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
        sb->s_dirt = 0;
-       if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) {
-               if (wait)
-                       jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target);
-       }
-       return 0;
+       if (wait)
+               ret = ext4_force_commit(sb);
+       else
+               jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, NULL);
+       return ret;
 }
 
 /*
index bfb5f06cf2c8c86cd39b7704f8a5c6ca69763b94..e06190322c1c8af1544034c1476f3c779b165318 100644 (file)
@@ -3,5 +3,9 @@
 #
 
 obj-$(CONFIG_FAT_FS) += fat.o
+obj-$(CONFIG_VFAT_FS) += vfat.o
+obj-$(CONFIG_MSDOS_FS) += msdos.o
 
-fat-objs := cache.o dir.o fatent.o file.o inode.o misc.o
+fat-y := cache.o dir.o fatent.o file.o inode.o misc.o
+vfat-y := namei_vfat.o
+msdos-y := namei_msdos.o
index 3222f51c41cf0a88637760f2f45729ef1f6a31c4..b4260229808790859871d7cf0e013cdf2601116c 100644 (file)
@@ -9,8 +9,8 @@
  */
 
 #include <linux/fs.h>
-#include <linux/msdos_fs.h>
 #include <linux/buffer_head.h>
+#include "fat.h"
 
 /* this must be > 0. */
 #define FAT_MAX_CACHE  8
@@ -293,10 +293,12 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
 }
 
 int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
-            unsigned long *mapped_blocks)
+            unsigned long *mapped_blocks, int create)
 {
        struct super_block *sb = inode->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       const unsigned long blocksize = sb->s_blocksize;
+       const unsigned char blocksize_bits = sb->s_blocksize_bits;
        sector_t last_block;
        int cluster, offset;
 
@@ -309,10 +311,21 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
                }
                return 0;
        }
-       last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1))
-               >> sb->s_blocksize_bits;
-       if (sector >= last_block)
-               return 0;
+
+       last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
+       if (sector >= last_block) {
+               if (!create)
+                       return 0;
+
+               /*
+                * ->mmu_private can access on only allocation path.
+                * (caller must hold ->i_mutex)
+                */
+               last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1))
+                       >> blocksize_bits;
+               if (sector >= last_block)
+                       return 0;
+       }
 
        cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
        offset  = sector & (sbi->sec_per_clus - 1);
index bae1c3292522eddbb744bcf6e6f84bc56da349e3..67e0583570983ccb7683dcbf10dcdb6d67288909 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/time.h>
-#include <linux/msdos_fs.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/compat.h>
 #include <asm/uaccess.h>
+#include "fat.h"
 
 static inline loff_t fat_make_i_pos(struct super_block *sb,
                                    struct buffer_head *bh,
@@ -77,7 +77,7 @@ next:
 
        *bh = NULL;
        iblock = *pos >> sb->s_blocksize_bits;
-       err = fat_bmap(dir, iblock, &phys, &mapped_blocks);
+       err = fat_bmap(dir, iblock, &phys, &mapped_blocks, 0);
        if (err || !phys)
                return -1;      /* beyond EOF or error */
 
@@ -86,7 +86,7 @@ next:
        *bh = sb_bread(sb, phys);
        if (*bh == NULL) {
                printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
-                      (unsigned long long)phys);
+                      (llu)phys);
                /* skip this block */
                *pos = (iblock + 1) << sb->s_blocksize_bits;
                goto next;
@@ -373,9 +373,10 @@ parse_record:
                if (de->attr == ATTR_EXT) {
                        int status = fat_parse_long(inode, &cpos, &bh, &de,
                                                    &unicode, &nr_slots);
-                       if (status < 0)
-                               return status;
-                       else if (status == PARSE_INVALID)
+                       if (status < 0) {
+                               err = status;
+                               goto end_of_dir;
+                       } else if (status == PARSE_INVALID)
                                continue;
                        else if (status == PARSE_NOT_LONGNAME)
                                goto parse_record;
@@ -832,6 +833,7 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd,
 #endif /* CONFIG_COMPAT */
 
 const struct file_operations fat_dir_operations = {
+       .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .readdir        = fat_readdir,
        .ioctl          = fat_dir_ioctl,
@@ -1089,6 +1091,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
        struct msdos_dir_entry *de;
        sector_t blknr;
        __le16 date, time;
+       u8 time_cs;
        int err, cluster;
 
        err = fat_alloc_clusters(dir, &cluster, 1);
@@ -1102,7 +1105,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
                goto error_free;
        }
 
-       fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
+       fat_time_unix2fat(sbi, ts, &time, &date, &time_cs);
 
        de = (struct msdos_dir_entry *)bhs[0]->b_data;
        /* filling the new directory slots ("." and ".." entries) */
@@ -1112,13 +1115,14 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
        de[0].lcase = de[1].lcase = 0;
        de[0].time = de[1].time = time;
        de[0].date = de[1].date = date;
-       de[0].ctime_cs = de[1].ctime_cs = 0;
        if (sbi->options.isvfat) {
                /* extra timestamps */
                de[0].ctime = de[1].ctime = time;
+               de[0].ctime_cs = de[1].ctime_cs = time_cs;
                de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date;
        } else {
                de[0].ctime = de[1].ctime = 0;
+               de[0].ctime_cs = de[1].ctime_cs = 0;
                de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0;
        }
        de[0].start = cpu_to_le16(cluster);
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
new file mode 100644 (file)
index 0000000..ea440d6
--- /dev/null
@@ -0,0 +1,329 @@
+#ifndef _FAT_H
+#define _FAT_H
+
+#include <linux/buffer_head.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/msdos_fs.h>
+
+/*
+ * vfat shortname flags
+ */
+#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
+#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */
+#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */
+#define VFAT_SFN_CREATE_WIN95  0x0100 /* emulate win95 rule for create */
+#define VFAT_SFN_CREATE_WINNT  0x0200 /* emulate winnt rule for create */
+
+struct fat_mount_options {
+       uid_t fs_uid;
+       gid_t fs_gid;
+       unsigned short fs_fmask;
+       unsigned short fs_dmask;
+       unsigned short codepage;  /* Codepage for shortname conversions */
+       char *iocharset;          /* Charset used for filename input/display */
+       unsigned short shortname; /* flags for shortname display/create rule */
+       unsigned char name_check; /* r = relaxed, n = normal, s = strict */
+       unsigned short allow_utime;/* permission for setting the [am]time */
+       unsigned quiet:1,         /* set = fake successful chmods and chowns */
+                showexec:1,      /* set = only set x bit for com/exe/bat */
+                sys_immutable:1, /* set = system files are immutable */
+                dotsOK:1,        /* set = hidden and system files are named '.filename' */
+                isvfat:1,        /* 0=no vfat long filename support, 1=vfat support */
+                utf8:1,          /* Use of UTF-8 character set (Default) */
+                unicode_xlate:1, /* create escape sequences for unhandled Unicode */
+                numtail:1,       /* Does first alias have a numeric '~1' type tail? */
+                flush:1,         /* write things quickly */
+                nocase:1,        /* Does this need case conversion? 0=need case conversion*/
+                usefree:1,       /* Use free_clusters for FAT32 */
+                tz_utc:1,        /* Filesystem timestamps are in UTC */
+                rodir:1;         /* allow ATTR_RO for directory */
+};
+
+#define FAT_HASH_BITS  8
+#define FAT_HASH_SIZE  (1UL << FAT_HASH_BITS)
+
+/*
+ * MS-DOS file system in-core superblock data
+ */
+struct msdos_sb_info {
+       unsigned short sec_per_clus; /* sectors/cluster */
+       unsigned short cluster_bits; /* log2(cluster_size) */
+       unsigned int cluster_size;   /* cluster size */
+       unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
+       unsigned short fat_start;
+       unsigned long fat_length;    /* FAT start & length (sec.) */
+       unsigned long dir_start;
+       unsigned short dir_entries;  /* root dir start & entries */
+       unsigned long data_start;    /* first data sector */
+       unsigned long max_cluster;   /* maximum cluster number */
+       unsigned long root_cluster;  /* first cluster of the root directory */
+       unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */
+       struct mutex fat_lock;
+       unsigned int prev_free;      /* previously allocated cluster number */
+       unsigned int free_clusters;  /* -1 if undefined */
+       unsigned int free_clus_valid; /* is free_clusters valid? */
+       struct fat_mount_options options;
+       struct nls_table *nls_disk;  /* Codepage used on disk */
+       struct nls_table *nls_io;    /* Charset used for input and display */
+       const void *dir_ops;                 /* Opaque; default directory operations */
+       int dir_per_block;           /* dir entries per block */
+       int dir_per_block_bits;      /* log2(dir_per_block) */
+
+       int fatent_shift;
+       struct fatent_operations *fatent_ops;
+
+       spinlock_t inode_hash_lock;
+       struct hlist_head inode_hashtable[FAT_HASH_SIZE];
+};
+
+#define FAT_CACHE_VALID        0       /* special case for valid cache */
+
+/*
+ * MS-DOS file system inode data in memory
+ */
+struct msdos_inode_info {
+       spinlock_t cache_lru_lock;
+       struct list_head cache_lru;
+       int nr_caches;
+       /* for avoiding the race between fat_free() and fat_get_cluster() */
+       unsigned int cache_valid_id;
+
+       /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */
+       loff_t mmu_private;     /* physically allocated size */
+
+       int i_start;            /* first cluster or 0 */
+       int i_logstart;         /* logical first cluster */
+       int i_attrs;            /* unused attribute bits */
+       loff_t i_pos;           /* on-disk position of directory entry or 0 */
+       struct hlist_node i_fat_hash;   /* hash by i_location */
+       struct inode vfs_inode;
+};
+
+struct fat_slot_info {
+       loff_t i_pos;           /* on-disk position of directory entry */
+       loff_t slot_off;        /* offset for slot or de start */
+       int nr_slots;           /* number of slots + 1(de) in filename */
+       struct msdos_dir_entry *de;
+       struct buffer_head *bh;
+};
+
+static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb)
+{
+       return sb->s_fs_info;
+}
+
+static inline struct msdos_inode_info *MSDOS_I(struct inode *inode)
+{
+       return container_of(inode, struct msdos_inode_info, vfs_inode);
+}
+
+/*
+ * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to
+ * save ATTR_RO instead of ->i_mode.
+ *
+ * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only
+ * bit, it's just used as flag for app.
+ */
+static inline int fat_mode_can_hold_ro(struct inode *inode)
+{
+       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+       mode_t mask;
+
+       if (S_ISDIR(inode->i_mode)) {
+               if (!sbi->options.rodir)
+                       return 0;
+               mask = ~sbi->options.fs_dmask;
+       } else
+               mask = ~sbi->options.fs_fmask;
+
+       if (!(mask & S_IWUGO))
+               return 0;
+       return 1;
+}
+
+/* Convert attribute bits and a mask to the UNIX mode. */
+static inline mode_t fat_make_mode(struct msdos_sb_info *sbi,
+                                  u8 attrs, mode_t mode)
+{
+       if (attrs & ATTR_RO && !((attrs & ATTR_DIR) && !sbi->options.rodir))
+               mode &= ~S_IWUGO;
+
+       if (attrs & ATTR_DIR)
+               return (mode & ~sbi->options.fs_dmask) | S_IFDIR;
+       else
+               return (mode & ~sbi->options.fs_fmask) | S_IFREG;
+}
+
+/* Return the FAT attribute byte for this inode */
+static inline u8 fat_make_attrs(struct inode *inode)
+{
+       u8 attrs = MSDOS_I(inode)->i_attrs;
+       if (S_ISDIR(inode->i_mode))
+               attrs |= ATTR_DIR;
+       if (fat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO))
+               attrs |= ATTR_RO;
+       return attrs;
+}
+
+static inline void fat_save_attrs(struct inode *inode, u8 attrs)
+{
+       if (fat_mode_can_hold_ro(inode))
+               MSDOS_I(inode)->i_attrs = attrs & ATTR_UNUSED;
+       else
+               MSDOS_I(inode)->i_attrs = attrs & (ATTR_UNUSED | ATTR_RO);
+}
+
+static inline unsigned char fat_checksum(const __u8 *name)
+{
+       unsigned char s = name[0];
+       s = (s<<7) + (s>>1) + name[1];  s = (s<<7) + (s>>1) + name[2];
+       s = (s<<7) + (s>>1) + name[3];  s = (s<<7) + (s>>1) + name[4];
+       s = (s<<7) + (s>>1) + name[5];  s = (s<<7) + (s>>1) + name[6];
+       s = (s<<7) + (s>>1) + name[7];  s = (s<<7) + (s>>1) + name[8];
+       s = (s<<7) + (s>>1) + name[9];  s = (s<<7) + (s>>1) + name[10];
+       return s;
+}
+
+static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus)
+{
+       return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus
+               + sbi->data_start;
+}
+
+static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len)
+{
+#ifdef __BIG_ENDIAN
+       while (len--) {
+               *dst++ = src[0] | (src[1] << 8);
+               src += 2;
+       }
+#else
+       memcpy(dst, src, len * 2);
+#endif
+}
+
+static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
+{
+#ifdef __BIG_ENDIAN
+       while (len--) {
+               dst[0] = *src & 0x00FF;
+               dst[1] = (*src & 0xFF00) >> 8;
+               dst += 2;
+               src++;
+       }
+#else
+       memcpy(dst, src, len * 2);
+#endif
+}
+
+/* fat/cache.c */
+extern void fat_cache_inval_inode(struct inode *inode);
+extern int fat_get_cluster(struct inode *inode, int cluster,
+                          int *fclus, int *dclus);
+extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
+                   unsigned long *mapped_blocks, int create);
+
+/* fat/dir.c */
+extern const struct file_operations fat_dir_operations;
+extern int fat_search_long(struct inode *inode, const unsigned char *name,
+                          int name_len, struct fat_slot_info *sinfo);
+extern int fat_dir_empty(struct inode *dir);
+extern int fat_subdirs(struct inode *dir);
+extern int fat_scan(struct inode *dir, const unsigned char *name,
+                   struct fat_slot_info *sinfo);
+extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
+                               struct msdos_dir_entry **de, loff_t *i_pos);
+extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
+extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
+                          struct fat_slot_info *sinfo);
+extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
+
+/* fat/fatent.c */
+struct fat_entry {
+       int entry;
+       union {
+               u8 *ent12_p[2];
+               __le16 *ent16_p;
+               __le32 *ent32_p;
+       } u;
+       int nr_bhs;
+       struct buffer_head *bhs[2];
+};
+
+static inline void fatent_init(struct fat_entry *fatent)
+{
+       fatent->nr_bhs = 0;
+       fatent->entry = 0;
+       fatent->u.ent32_p = NULL;
+       fatent->bhs[0] = fatent->bhs[1] = NULL;
+}
+
+static inline void fatent_set_entry(struct fat_entry *fatent, int entry)
+{
+       fatent->entry = entry;
+       fatent->u.ent32_p = NULL;
+}
+
+static inline void fatent_brelse(struct fat_entry *fatent)
+{
+       int i;
+       fatent->u.ent32_p = NULL;
+       for (i = 0; i < fatent->nr_bhs; i++)
+               brelse(fatent->bhs[i]);
+       fatent->nr_bhs = 0;
+       fatent->bhs[0] = fatent->bhs[1] = NULL;
+}
+
+extern void fat_ent_access_init(struct super_block *sb);
+extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent,
+                       int entry);
+extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
+                        int new, int wait);
+extern int fat_alloc_clusters(struct inode *inode, int *cluster,
+                             int nr_cluster);
+extern int fat_free_clusters(struct inode *inode, int cluster);
+extern int fat_count_free_clusters(struct super_block *sb);
+
+/* fat/file.c */
+extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
+                            unsigned int cmd, unsigned long arg);
+extern const struct file_operations fat_file_operations;
+extern const struct inode_operations fat_file_inode_operations;
+extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
+extern void fat_truncate(struct inode *inode);
+extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
+                      struct kstat *stat);
+
+/* fat/inode.c */
+extern void fat_attach(struct inode *inode, loff_t i_pos);
+extern void fat_detach(struct inode *inode);
+extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
+extern struct inode *fat_build_inode(struct super_block *sb,
+                       struct msdos_dir_entry *de, loff_t i_pos);
+extern int fat_sync_inode(struct inode *inode);
+extern int fat_fill_super(struct super_block *sb, void *data, int silent,
+                       const struct inode_operations *fs_dir_inode_ops, int isvfat);
+
+extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
+                           struct inode *i2);
+/* fat/misc.c */
+extern void fat_fs_panic(struct super_block *s, const char *fmt, ...)
+       __attribute__ ((format (printf, 2, 3))) __cold;
+extern void fat_clusters_flush(struct super_block *sb);
+extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
+extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
+                             __le16 __time, __le16 __date, u8 time_cs);
+extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
+                             __le16 *time, __le16 *date, u8 *time_cs);
+extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
+
+int fat_cache_init(void);
+void fat_cache_destroy(void);
+
+/* helper for printk */
+typedef unsigned long long     llu;
+
+#endif /* !_FAT_H */
index fb98b3d847ed2d820e6b4425c44ef44e028a66eb..da6eea47872f448cb2f817e6471c56e0aebbbc1a 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
 #include <linux/blkdev.h>
+#include "fat.h"
 
 struct fatent_operations {
        void (*ent_blocknr)(struct super_block *, int, int *, sector_t *);
@@ -92,8 +93,7 @@ static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
 err_brelse:
        brelse(bhs[0]);
 err:
-       printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
-              (unsigned long long)blocknr);
+       printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", (llu)blocknr);
        return -EIO;
 }
 
@@ -106,7 +106,7 @@ static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
        fatent->bhs[0] = sb_bread(sb, blocknr);
        if (!fatent->bhs[0]) {
                printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
-                      (unsigned long long)blocknr);
+                      (llu)blocknr);
                return -EIO;
        }
        fatent->nr_bhs = 1;
@@ -316,10 +316,20 @@ static inline int fat_ent_update_ptr(struct super_block *sb,
        /* Is this fatent's blocks including this entry? */
        if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr)
                return 0;
-       /* Does this entry need the next block? */
-       if (sbi->fat_bits == 12 && (offset + 1) >= sb->s_blocksize) {
-               if (fatent->nr_bhs != 2 || bhs[1]->b_blocknr != (blocknr + 1))
-                       return 0;
+       if (sbi->fat_bits == 12) {
+               if ((offset + 1) < sb->s_blocksize) {
+                       /* This entry is on bhs[0]. */
+                       if (fatent->nr_bhs == 2) {
+                               brelse(bhs[1]);
+                               fatent->nr_bhs = 1;
+                       }
+               } else {
+                       /* This entry needs the next block. */
+                       if (fatent->nr_bhs != 2)
+                               return 0;
+                       if (bhs[1]->b_blocknr != (blocknr + 1))
+                               return 0;
+               }
        }
        ops->ent_set_ptr(fatent, offset);
        return 1;
index ddde37025ca674827d5dafe836a0956c70648f06..f06a4e525eceff2b758ba0ff62ebd6e6f2fca9bb 100644 (file)
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/time.h>
-#include <linux/msdos_fs.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/blkdev.h>
 #include <linux/fsnotify.h>
 #include <linux/security.h>
+#include "fat.h"
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg)
@@ -29,10 +29,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
        {
                u32 attr;
 
-               if (inode->i_ino == MSDOS_ROOT_INO)
-                       attr = ATTR_DIR;
-               else
-                       attr = fat_attr(inode);
+               mutex_lock(&inode->i_mutex);
+               attr = fat_make_attrs(inode);
+               mutex_unlock(&inode->i_mutex);
 
                return put_user(attr, user_attr);
        }
@@ -62,20 +61,16 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
                /* Merge in ATTR_VOLUME and ATTR_DIR */
                attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
                        (is_dir ? ATTR_DIR : 0);
-               oldattr = fat_attr(inode);
+               oldattr = fat_make_attrs(inode);
 
                /* Equivalent to a chmod() */
                ia.ia_valid = ATTR_MODE | ATTR_CTIME;
                ia.ia_ctime = current_fs_time(inode->i_sb);
-               if (is_dir) {
-                       ia.ia_mode = MSDOS_MKMODE(attr,
-                               S_IRWXUGO & ~sbi->options.fs_dmask)
-                               | S_IFDIR;
-               } else {
-                       ia.ia_mode = MSDOS_MKMODE(attr,
-                               (S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO))
-                               & ~sbi->options.fs_fmask)
-                               | S_IFREG;
+               if (is_dir)
+                       ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO);
+               else {
+                       ia.ia_mode = fat_make_mode(sbi, attr,
+                               S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO));
                }
 
                /* The root directory has no attributes */
@@ -115,7 +110,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp,
                                inode->i_flags &= S_IMMUTABLE;
                }
 
-               MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
+               fat_save_attrs(inode, attr);
                mark_inode_dirty(inode);
 up:
                mnt_drop_write(filp->f_path.mnt);
@@ -274,7 +269,7 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi,
 
        /*
         * Note, the basic check is already done by a caller of
-        * (attr->ia_mode & ~MSDOS_VALID_MODE)
+        * (attr->ia_mode & ~FAT_VALID_MODE)
         */
 
        if (S_ISREG(inode->i_mode))
@@ -287,11 +282,18 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi,
        /*
         * Of the r and x bits, all (subject to umask) must be present. Of the
         * w bits, either all (subject to umask) or none must be present.
+        *
+        * If fat_mode_can_hold_ro(inode) is false, can't change w bits.
         */
        if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
                return -EPERM;
-       if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
-               return -EPERM;
+       if (fat_mode_can_hold_ro(inode)) {
+               if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
+                       return -EPERM;
+       } else {
+               if ((perm & S_IWUGO) != (S_IWUGO & ~mask))
+                       return -EPERM;
+       }
 
        *mode_ptr &= S_IFMT | perm;
 
@@ -314,13 +316,15 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)
 }
 
 #define TIMES_SET_FLAGS        (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
+/* valid file mode bits */
+#define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO)
 
 int fat_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
        struct inode *inode = dentry->d_inode;
-       int error = 0;
        unsigned int ia_valid;
+       int error;
 
        /*
         * Expand the file. Since inode_setattr() updates ->i_size
@@ -356,7 +360,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
            ((attr->ia_valid & ATTR_GID) &&
             (attr->ia_gid != sbi->options.fs_gid)) ||
            ((attr->ia_valid & ATTR_MODE) &&
-            (attr->ia_mode & ~MSDOS_VALID_MODE)))
+            (attr->ia_mode & ~FAT_VALID_MODE)))
                error = -EPERM;
 
        if (error) {
@@ -374,7 +378,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)
                        attr->ia_valid &= ~ATTR_MODE;
        }
 
-       error = inode_setattr(inode, attr);
+       if (attr->ia_valid)
+               error = inode_setattr(inode, attr);
 out:
        return error;
 }
index 2b2eec1283bfa8d0d830fce2f6f9792e0dedbbca..bdd8fb7be2ca48e5ac4e49b5b2dd147375f6c8b2 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/seq_file.h>
-#include <linux/msdos_fs.h>
 #include <linux/pagemap.h>
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
@@ -27,7 +26,9 @@
 #include <linux/uio.h>
 #include <linux/writeback.h>
 #include <linux/log2.h>
+#include <linux/hash.h>
 #include <asm/unaligned.h>
+#include "fat.h"
 
 #ifndef CONFIG_FAT_DEFAULT_IOCHARSET
 /* if user don't select VFAT, this is undefined. */
@@ -63,7 +64,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
        sector_t phys;
        int err, offset;
 
-       err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
+       err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create);
        if (err)
                return err;
        if (phys) {
@@ -93,7 +94,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
        *max_blocks = min(mapped_blocks, *max_blocks);
        MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits;
 
-       err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
+       err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create);
        if (err)
                return err;
 
@@ -198,7 +199,14 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
 
 static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
 {
-       return generic_block_bmap(mapping, block, fat_get_block);
+       sector_t blocknr;
+
+       /* fat_get_cluster() assumes the requested blocknr isn't truncated. */
+       mutex_lock(&mapping->host->i_mutex);
+       blocknr = generic_block_bmap(mapping, block, fat_get_block);
+       mutex_unlock(&mapping->host->i_mutex);
+
+       return blocknr;
 }
 
 static const struct address_space_operations fat_aops = {
@@ -247,25 +255,21 @@ static void fat_hash_init(struct super_block *sb)
                INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
 }
 
-static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos)
+static inline unsigned long fat_hash(loff_t i_pos)
 {
-       unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb;
-       tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2);
-       return tmp & FAT_HASH_MASK;
+       return hash_32(i_pos, FAT_HASH_BITS);
 }
 
 void fat_attach(struct inode *inode, loff_t i_pos)
 {
-       struct super_block *sb = inode->i_sb;
-       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+       struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos);
 
        spin_lock(&sbi->inode_hash_lock);
        MSDOS_I(inode)->i_pos = i_pos;
-       hlist_add_head(&MSDOS_I(inode)->i_fat_hash,
-                       sbi->inode_hashtable + fat_hash(sb, i_pos));
+       hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head);
        spin_unlock(&sbi->inode_hash_lock);
 }
-
 EXPORT_SYMBOL_GPL(fat_attach);
 
 void fat_detach(struct inode *inode)
@@ -276,13 +280,12 @@ void fat_detach(struct inode *inode)
        hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
        spin_unlock(&sbi->inode_hash_lock);
 }
-
 EXPORT_SYMBOL_GPL(fat_detach);
 
 struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
-       struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos);
+       struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos);
        struct hlist_node *_p;
        struct msdos_inode_info *i;
        struct inode *inode = NULL;
@@ -341,8 +344,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 
        if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
                inode->i_generation &= ~1;
-               inode->i_mode = MSDOS_MKMODE(de->attr,
-                       S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR;
+               inode->i_mode = fat_make_mode(sbi, de->attr, S_IRWXUGO);
                inode->i_op = sbi->dir_ops;
                inode->i_fop = &fat_dir_operations;
 
@@ -359,10 +361,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                inode->i_nlink = fat_subdirs(inode);
        } else { /* not a directory */
                inode->i_generation |= 1;
-               inode->i_mode = MSDOS_MKMODE(de->attr,
-                   ((sbi->options.showexec && !is_exec(de->name + 8))
-                       ? S_IRUGO|S_IWUGO : S_IRWXUGO)
-                   & ~sbi->options.fs_fmask) | S_IFREG;
+               inode->i_mode = fat_make_mode(sbi, de->attr,
+                       ((sbi->options.showexec && !is_exec(de->name + 8))
+                        ? S_IRUGO|S_IWUGO : S_IRWXUGO));
                MSDOS_I(inode)->i_start = le16_to_cpu(de->start);
                if (sbi->fat_bits == 32)
                        MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16);
@@ -378,25 +379,16 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                if (sbi->options.sys_immutable)
                        inode->i_flags |= S_IMMUTABLE;
        }
-       MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
+       fat_save_attrs(inode, de->attr);
+
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
-       inode->i_mtime.tv_sec =
-               date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date),
-                             sbi->options.tz_utc);
-       inode->i_mtime.tv_nsec = 0;
+
+       fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0);
        if (sbi->options.isvfat) {
-               int secs = de->ctime_cs / 100;
-               int csecs = de->ctime_cs % 100;
-               inode->i_ctime.tv_sec  =
-                       date_dos2unix(le16_to_cpu(de->ctime),
-                                     le16_to_cpu(de->cdate),
-                                     sbi->options.tz_utc) + secs;
-               inode->i_ctime.tv_nsec = csecs * 10000000;
-               inode->i_atime.tv_sec =
-                       date_dos2unix(0, le16_to_cpu(de->adate),
-                                     sbi->options.tz_utc);
-               inode->i_atime.tv_nsec = 0;
+               fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime,
+                                 de->cdate, de->ctime_cs);
+               fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0);
        } else
                inode->i_ctime = inode->i_atime = inode->i_mtime;
 
@@ -443,13 +435,8 @@ static void fat_delete_inode(struct inode *inode)
 
 static void fat_clear_inode(struct inode *inode)
 {
-       struct super_block *sb = inode->i_sb;
-       struct msdos_sb_info *sbi = MSDOS_SB(sb);
-
-       spin_lock(&sbi->inode_hash_lock);
        fat_cache_inval_inode(inode);
-       hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
-       spin_unlock(&sbi->inode_hash_lock);
+       fat_detach(inode);
 }
 
 static void fat_write_super(struct super_block *sb)
@@ -555,6 +542,20 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
+static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi,
+                                   struct inode *inode)
+{
+       loff_t i_pos;
+#if BITS_PER_LONG == 32
+       spin_lock(&sbi->inode_hash_lock);
+#endif
+       i_pos = MSDOS_I(inode)->i_pos;
+#if BITS_PER_LONG == 32
+       spin_unlock(&sbi->inode_hash_lock);
+#endif
+       return i_pos;
+}
+
 static int fat_write_inode(struct inode *inode, int wait)
 {
        struct super_block *sb = inode->i_sb;
@@ -564,9 +565,12 @@ static int fat_write_inode(struct inode *inode, int wait)
        loff_t i_pos;
        int err;
 
+       if (inode->i_ino == MSDOS_ROOT_INO)
+               return 0;
+
 retry:
-       i_pos = MSDOS_I(inode)->i_pos;
-       if (inode->i_ino == MSDOS_ROOT_INO || !i_pos)
+       i_pos = fat_i_pos_read(sbi, inode);
+       if (!i_pos)
                return 0;
 
        bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);
@@ -588,19 +592,17 @@ retry:
                raw_entry->size = 0;
        else
                raw_entry->size = cpu_to_le32(inode->i_size);
-       raw_entry->attr = fat_attr(inode);
+       raw_entry->attr = fat_make_attrs(inode);
        raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
        raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
-       fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time,
-                         &raw_entry->date, sbi->options.tz_utc);
+       fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
+                         &raw_entry->date, NULL);
        if (sbi->options.isvfat) {
                __le16 atime;
-               fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime,
-                                 &raw_entry->cdate, sbi->options.tz_utc);
-               fat_date_unix2dos(inode->i_atime.tv_sec, &atime,
-                                 &raw_entry->adate, sbi->options.tz_utc);
-               raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
-                       inode->i_ctime.tv_nsec / 10000000;
+               fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,
+                                 &raw_entry->cdate, &raw_entry->ctime_cs);
+               fat_time_unix2fat(sbi, &inode->i_atime, &atime,
+                                 &raw_entry->adate, NULL);
        }
        spin_unlock(&sbi->inode_hash_lock);
        mark_buffer_dirty(bh);
@@ -819,8 +821,10 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
                        seq_puts(m, ",uni_xlate");
                if (!opts->numtail)
                        seq_puts(m, ",nonumtail");
+               if (opts->rodir)
+                       seq_puts(m, ",rodir");
        }
-       if (sbi->options.flush)
+       if (opts->flush)
                seq_puts(m, ",flush");
        if (opts->tz_utc)
                seq_puts(m, ",tz=UTC");
@@ -836,7 +840,7 @@ enum {
        Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
        Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
        Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
-       Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err,
+       Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err,
 };
 
 static const match_table_t fat_tokens = {
@@ -908,6 +912,7 @@ static const match_table_t vfat_tokens = {
        {Opt_nonumtail_yes, "nonumtail=yes"},
        {Opt_nonumtail_yes, "nonumtail=true"},
        {Opt_nonumtail_yes, "nonumtail"},
+       {Opt_rodir, "rodir"},
        {Opt_err, NULL}
 };
 
@@ -927,10 +932,13 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
        opts->allow_utime = -1;
        opts->codepage = fat_default_codepage;
        opts->iocharset = fat_default_iocharset;
-       if (is_vfat)
+       if (is_vfat) {
                opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95;
-       else
+               opts->rodir = 0;
+       } else {
                opts->shortname = 0;
+               opts->rodir = 1;
+       }
        opts->name_check = 'n';
        opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK =  0;
        opts->utf8 = opts->unicode_xlate = 0;
@@ -1081,6 +1089,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
                case Opt_nonumtail_yes:         /* empty or 1 or yes or true */
                        opts->numtail = 0;      /* negated option */
                        break;
+               case Opt_rodir:
+                       opts->rodir = 1;
+                       break;
 
                /* obsolete mount options */
                case Opt_obsolate:
@@ -1126,7 +1137,7 @@ static int fat_read_root(struct inode *inode)
        inode->i_gid = sbi->options.fs_gid;
        inode->i_version++;
        inode->i_generation = 0;
-       inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR;
+       inode->i_mode = fat_make_mode(sbi, ATTR_DIR, S_IRWXUGO);
        inode->i_op = sbi->dir_ops;
        inode->i_fop = &fat_dir_operations;
        if (sbi->fat_bits == 32) {
@@ -1143,7 +1154,7 @@ static int fat_read_root(struct inode *inode)
        MSDOS_I(inode)->i_logstart = 0;
        MSDOS_I(inode)->mmu_private = inode->i_size;
 
-       MSDOS_I(inode)->i_attrs = ATTR_NONE;
+       fat_save_attrs(inode, ATTR_DIR);
        inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
        inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
        inode->i_nlink = fat_subdirs(inode)+2;
index 79fb98ad36d4d2e2913c26bb5ab5b56358594eea..ac39ebcc149676b9eb35c15c8ddcff722f43a69f 100644 (file)
@@ -8,8 +8,8 @@
 
 #include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/msdos_fs.h>
 #include <linux/buffer_head.h>
+#include "fat.h"
 
 /*
  * fat_fs_panic reports a severe file system problem and sets the file system
@@ -124,8 +124,9 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
                        mark_inode_dirty(inode);
        }
        if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) {
-               fat_fs_panic(sb, "clusters badly computed (%d != %lu)",
-                       new_fclus, inode->i_blocks >> (sbi->cluster_bits - 9));
+               fat_fs_panic(sb, "clusters badly computed (%d != %llu)",
+                            new_fclus,
+                            (llu)(inode->i_blocks >> (sbi->cluster_bits - 9)));
                fat_cache_inval_inode(inode);
        }
        inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9);
@@ -135,65 +136,131 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
 
 extern struct timezone sys_tz;
 
+/*
+ * The epoch of FAT timestamp is 1980.
+ *     :  bits :     value
+ * date:  0 -  4: day  (1 -  31)
+ * date:  5 -  8: month        (1 -  12)
+ * date:  9 - 15: year (0 - 127) from 1980
+ * time:  0 -  4: sec  (0 -  29) 2sec counts
+ * time:  5 - 10: min  (0 -  59)
+ * time: 11 - 15: hour (0 -  23)
+ */
+#define SECS_PER_MIN   60
+#define SECS_PER_HOUR  (60 * 60)
+#define SECS_PER_DAY   (SECS_PER_HOUR * 24)
+#define UNIX_SECS_1980 315532800L
+#if BITS_PER_LONG == 64
+#define UNIX_SECS_2108 4354819200L
+#endif
+/* days between 1.1.70 and 1.1.80 (2 leap days) */
+#define DAYS_DELTA     (365 * 10 + 2)
+/* 120 (2100 - 1980) isn't leap year */
+#define YEAR_2100      120
+#define IS_LEAP_YEAR(y)        (!((y) & 3) && (y) != YEAR_2100)
+
 /* Linear day numbers of the respective 1sts in non-leap years. */
-static int day_n[] = {
-   /* Jan  Feb  Mar  Apr   May  Jun  Jul  Aug  Sep  Oct  Nov  Dec */
-       0,  31,  59,  90,  120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0
+static time_t days_in_year[] = {
+       /* Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec */
+       0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
 };
 
-/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-int date_dos2unix(unsigned short time, unsigned short date, int tz_utc)
+/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
+void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
+                      __le16 __time, __le16 __date, u8 time_cs)
 {
-       int month, year, secs;
+       u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date);
+       time_t second, day, leap_day, month, year;
 
-       /*
-        * first subtract and mask after that... Otherwise, if
-        * date == 0, bad things happen
-        */
-       month = ((date >> 5) - 1) & 15;
-       year = date >> 9;
-       secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
-           ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
-           month < 2 ? 1 : 0)+3653);
-                       /* days since 1.1.70 plus 80's leap day */
-       if (!tz_utc)
-               secs += sys_tz.tz_minuteswest*60;
-       return secs;
+       year  = date >> 9;
+       month = max(1, (date >> 5) & 0xf);
+       day   = max(1, date & 0x1f) - 1;
+
+       leap_day = (year + 3) / 4;
+       if (year > YEAR_2100)           /* 2100 isn't leap year */
+               leap_day--;
+       if (IS_LEAP_YEAR(year) && month > 2)
+               leap_day++;
+
+       second =  (time & 0x1f) << 1;
+       second += ((time >> 5) & 0x3f) * SECS_PER_MIN;
+       second += (time >> 11) * SECS_PER_HOUR;
+       second += (year * 365 + leap_day
+                  + days_in_year[month] + day
+                  + DAYS_DELTA) * SECS_PER_DAY;
+
+       if (!sbi->options.tz_utc)
+               second += sys_tz.tz_minuteswest * SECS_PER_MIN;
+
+       if (time_cs) {
+               ts->tv_sec = second + (time_cs / 100);
+               ts->tv_nsec = (time_cs % 100) * 10000000;
+       } else {
+               ts->tv_sec = second;
+               ts->tv_nsec = 0;
+       }
 }
 
-/* Convert linear UNIX date to a MS-DOS time/date pair. */
-void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int tz_utc)
+/* Convert linear UNIX date to a FAT time/date pair. */
+void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
+                      __le16 *time, __le16 *date, u8 *time_cs)
 {
-       int day, year, nl_day, month;
+       time_t second = ts->tv_sec;
+       time_t day, leap_day, month, year;
 
-       if (!tz_utc)
-               unix_date -= sys_tz.tz_minuteswest*60;
+       if (!sbi->options.tz_utc)
+               second -= sys_tz.tz_minuteswest * SECS_PER_MIN;
 
        /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
-       if (unix_date < 315532800)
-               unix_date = 315532800;
-
-       *time = cpu_to_le16((unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
-           (((unix_date/3600) % 24) << 11));
-       day = unix_date/86400-3652;
-       year = day/365;
-       if ((year+3)/4+365*year > day)
+       if (second < UNIX_SECS_1980) {
+               *time = 0;
+               *date = cpu_to_le16((0 << 9) | (1 << 5) | 1);
+               if (time_cs)
+                       *time_cs = 0;
+               return;
+       }
+#if BITS_PER_LONG == 64
+       if (second >= UNIX_SECS_2108) {
+               *time = cpu_to_le16((23 << 11) | (59 << 5) | 29);
+               *date = cpu_to_le16((127 << 9) | (12 << 5) | 31);
+               if (time_cs)
+                       *time_cs = 199;
+               return;
+       }
+#endif
+
+       day = second / SECS_PER_DAY - DAYS_DELTA;
+       year = day / 365;
+       leap_day = (year + 3) / 4;
+       if (year > YEAR_2100)           /* 2100 isn't leap year */
+               leap_day--;
+       if (year * 365 + leap_day > day)
                year--;
-       day -= (year+3)/4+365*year;
-       if (day == 59 && !(year & 3)) {
-               nl_day = day;
+       leap_day = (year + 3) / 4;
+       if (year > YEAR_2100)           /* 2100 isn't leap year */
+               leap_day--;
+       day -= year * 365 + leap_day;
+
+       if (IS_LEAP_YEAR(year) && day == days_in_year[3]) {
                month = 2;
        } else {
-               nl_day = (year & 3) || day <= 59 ? day : day-1;
-               for (month = 0; month < 12; month++) {
-                       if (day_n[month] > nl_day)
+               if (IS_LEAP_YEAR(year) && day > days_in_year[3])
+                       day--;
+               for (month = 1; month < 12; month++) {
+                       if (days_in_year[month + 1] > day)
                                break;
                }
        }
-       *date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9));
-}
+       day -= days_in_year[month];
 
-EXPORT_SYMBOL_GPL(fat_date_unix2dos);
+       *time = cpu_to_le16(((second / SECS_PER_HOUR) % 24) << 11
+                           | ((second / SECS_PER_MIN) % 60) << 5
+                           | (second % SECS_PER_MIN) >> 1);
+       *date = cpu_to_le16((year << 9) | (month << 5) | (day + 1));
+       if (time_cs)
+               *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000;
+}
+EXPORT_SYMBOL_GPL(fat_time_unix2fat);
 
 int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
 {
similarity index 97%
rename from fs/msdos/namei.c
rename to fs/fat/namei_msdos.c
index e844b9809d27de0aa1447dec920087b6978b8c7c..7ba03a4acbe07d7f8d426580e785f86075e1e7d0 100644 (file)
@@ -9,8 +9,8 @@
 #include <linux/module.h>
 #include <linux/time.h>
 #include <linux/buffer_head.h>
-#include <linux/msdos_fs.h>
 #include <linux/smp_lock.h>
+#include "fat.h"
 
 /* Characters that are undesirable in an MS-DOS file name */
 static unsigned char bad_chars[] = "*?<>|\"";
@@ -203,33 +203,37 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
 {
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
-       struct inode *inode = NULL;
-       int res;
-
-       dentry->d_op = &msdos_dentry_operations;
+       struct inode *inode;
+       int err;
 
        lock_super(sb);
-       res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
-       if (res == -ENOENT)
-               goto add;
-       if (res < 0)
-               goto out;
+
+       err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
+       if (err) {
+               if (err == -ENOENT) {
+                       inode = NULL;
+                       goto out;
+               }
+               goto error;
+       }
+
        inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
        brelse(sinfo.bh);
        if (IS_ERR(inode)) {
-               res = PTR_ERR(inode);
-               goto out;
+               err = PTR_ERR(inode);
+               goto error;
        }
-add:
-       res = 0;
+out:
+       unlock_super(sb);
+       dentry->d_op = &msdos_dentry_operations;
        dentry = d_splice_alias(inode, dentry);
        if (dentry)
                dentry->d_op = &msdos_dentry_operations;
-out:
+       return dentry;
+
+error:
        unlock_super(sb);
-       if (!res)
-               return dentry;
-       return ERR_PTR(res);
+       return ERR_PTR(err);
 }
 
 /***** Creates a directory entry (name is already formatted). */
@@ -247,7 +251,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
        if (is_hid)
                de.attr |= ATTR_HIDDEN;
        de.lcase = 0;
-       fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
+       fat_time_unix2fat(sbi, ts, &time, &date, NULL);
        de.cdate = de.adate = 0;
        de.ctime = 0;
        de.ctime_cs = 0;
similarity index 89%
rename from fs/vfat/namei.c
rename to fs/fat/namei_vfat.c
index 155c10b4adbd4a0d3e518b7558d07e4501bee11b..bf326d4356a3347ff9a143328cbef11c01792213 100644 (file)
  */
 
 #include <linux/module.h>
-
 #include <linux/jiffies.h>
-#include <linux/msdos_fs.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/namei.h>
+#include "fat.h"
 
-static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
+/*
+ * If new entry was created in the parent, it could create the 8.3
+ * alias (the shortname of logname).  So, the parent may have the
+ * negative-dentry which matches the created 8.3 alias.
+ *
+ * If it happened, the negative dentry isn't actually negative
+ * anymore.  So, drop it.
+ */
+static int vfat_revalidate_shortname(struct dentry *dentry)
 {
        int ret = 1;
-
-       if (!dentry->d_inode &&
-           nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_CREATE))
-               /*
-                * negative dentry is dropped, in order to make sure
-                * to use the name which a user desires if this is
-                * create path.
-                */
+       spin_lock(&dentry->d_lock);
+       if (dentry->d_time != dentry->d_parent->d_inode->i_version)
                ret = 0;
-       else {
-               spin_lock(&dentry->d_lock);
-               if (dentry->d_time != dentry->d_parent->d_inode->i_version)
-                       ret = 0;
-               spin_unlock(&dentry->d_lock);
-       }
+       spin_unlock(&dentry->d_lock);
        return ret;
 }
 
+static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+       /* This is not negative dentry. Always valid. */
+       if (dentry->d_inode)
+               return 1;
+       return vfat_revalidate_shortname(dentry);
+}
+
+static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
+{
+       /*
+        * This is not negative dentry. Always valid.
+        *
+        * Note, rename() to existing directory entry will have ->d_inode,
+        * and will use existing name which isn't specified name by user.
+        *
+        * We may be able to drop this positive dentry here. But dropping
+        * positive dentry isn't good idea. So it's unsupported like
+        * rename("filename", "FILENAME") for now.
+        */
+       if (dentry->d_inode)
+               return 1;
+
+       /*
+        * This may be nfsd (or something), anyway, we can't see the
+        * intent of this. So, since this can be for creation, drop it.
+        */
+       if (!nd)
+               return 0;
+
+       /*
+        * Drop the negative dentry, in order to make sure to use the
+        * case sensitive name which is specified by user if this is
+        * for creation.
+        */
+       if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
+               if (nd->flags & LOOKUP_CREATE)
+                       return 0;
+       }
+
+       return vfat_revalidate_shortname(dentry);
+}
+
 /* returns the length of a struct qstr, ignoring trailing dots */
 static unsigned int vfat_striptail_len(struct qstr *qstr)
 {
@@ -127,25 +166,16 @@ static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
        return 1;
 }
 
-static struct dentry_operations vfat_dentry_ops[4] = {
-       {
-               .d_hash         = vfat_hashi,
-               .d_compare      = vfat_cmpi,
-       },
-       {
-               .d_revalidate   = vfat_revalidate,
-               .d_hash         = vfat_hashi,
-               .d_compare      = vfat_cmpi,
-       },
-       {
-               .d_hash         = vfat_hash,
-               .d_compare      = vfat_cmp,
-       },
-       {
-               .d_revalidate   = vfat_revalidate,
-               .d_hash         = vfat_hash,
-               .d_compare      = vfat_cmp,
-       }
+static struct dentry_operations vfat_ci_dentry_ops = {
+       .d_revalidate   = vfat_revalidate_ci,
+       .d_hash         = vfat_hashi,
+       .d_compare      = vfat_cmpi,
+};
+
+static struct dentry_operations vfat_dentry_ops = {
+       .d_revalidate   = vfat_revalidate,
+       .d_hash         = vfat_hash,
+       .d_compare      = vfat_cmp,
 };
 
 /* Characters that are undesirable in an MS-DOS file name */
@@ -569,6 +599,7 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name,
        unsigned char msdos_name[MSDOS_NAME];
        wchar_t *uname;
        __le16 time, date;
+       u8 time_cs;
        int err, ulen, usize, i;
        loff_t offset;
 
@@ -621,10 +652,10 @@ shortname:
        memcpy(de->name, msdos_name, MSDOS_NAME);
        de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
        de->lcase = lcase;
-       fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc);
+       fat_time_unix2fat(sbi, ts, &time, &date, &time_cs);
        de->time = de->ctime = time;
        de->date = de->cdate = de->adate = date;
-       de->ctime_cs = 0;
+       de->ctime_cs = time_cs;
        de->start = cpu_to_le16(cluster);
        de->starthi = cpu_to_le16(cluster >> 16);
        de->size = 0;
@@ -683,46 +714,58 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
 {
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
-       struct inode *inode = NULL;
+       struct inode *inode;
        struct dentry *alias;
-       int err, table;
+       int err;
 
        lock_super(sb);
-       table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0;
-       dentry->d_op = &vfat_dentry_ops[table];
 
        err = vfat_find(dir, &dentry->d_name, &sinfo);
        if (err) {
-               table++;
+               if (err == -ENOENT) {
+                       inode = NULL;
+                       goto out;
+               }
                goto error;
        }
+
        inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
        brelse(sinfo.bh);
        if (IS_ERR(inode)) {
-               unlock_super(sb);
-               return ERR_CAST(inode);
+               err = PTR_ERR(inode);
+               goto error;
        }
-       alias = d_find_alias(inode);
-       if (alias) {
-               if (d_invalidate(alias) == 0)
-                       dput(alias);
-               else {
-                       iput(inode);
-                       unlock_super(sb);
-                       return alias;
-               }
 
+       alias = d_find_alias(inode);
+       if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) {
+               /*
+                * This inode has non DCACHE_DISCONNECTED dentry. This
+                * means, the user did ->lookup() by an another name
+                * (longname vs 8.3 alias of it) in past.
+                *
+                * Switch to new one for reason of locality if possible.
+                */
+               BUG_ON(d_unhashed(alias));
+               if (!S_ISDIR(inode->i_mode))
+                       d_move(alias, dentry);
+               iput(inode);
+               unlock_super(sb);
+               return alias;
        }
-error:
+out:
        unlock_super(sb);
-       dentry->d_op = &vfat_dentry_ops[table];
+       dentry->d_op = sb->s_root->d_op;
        dentry->d_time = dentry->d_parent->d_inode->i_version;
        dentry = d_splice_alias(inode, dentry);
        if (dentry) {
-               dentry->d_op = &vfat_dentry_ops[table];
+               dentry->d_op = sb->s_root->d_op;
                dentry->d_time = dentry->d_parent->d_inode->i_version;
        }
        return dentry;
+
+error:
+       unlock_super(sb);
+       return ERR_PTR(err);
 }
 
 static int vfat_create(struct inode *dir, struct dentry *dentry, int mode,
@@ -1014,9 +1057,9 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent)
                return res;
 
        if (MSDOS_SB(sb)->options.name_check != 's')
-               sb->s_root->d_op = &vfat_dentry_ops[0];
+               sb->s_root->d_op = &vfat_ci_dentry_ops;
        else
-               sb->s_root->d_op = &vfat_dentry_ops[2];
+               sb->s_root->d_op = &vfat_dentry_ops;
 
        return 0;
 }
index 1bd8d4acc6f2124a7574001d454a25b971fd9852..61f32f3868cd1833927e394009d780e7d371e6e2 100644 (file)
@@ -115,7 +115,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
  */
 void __log_wait_for_space(journal_t *journal)
 {
-       int nblocks;
+       int nblocks, space_left;
        assert_spin_locked(&journal->j_state_lock);
 
        nblocks = jbd_space_needed(journal);
@@ -128,25 +128,42 @@ void __log_wait_for_space(journal_t *journal)
                /*
                 * Test again, another process may have checkpointed while we
                 * were waiting for the checkpoint lock. If there are no
-                * outstanding transactions there is nothing to checkpoint and
-                * we can't make progress. Abort the journal in this case.
+                * transactions ready to be checkpointed, try to recover
+                * journal space by calling cleanup_journal_tail(), and if
+                * that doesn't work, by waiting for the currently committing
+                * transaction to complete.  If there is absolutely no way
+                * to make progress, this is either a BUG or corrupted
+                * filesystem, so abort the journal and leave a stack
+                * trace for forensic evidence.
                 */
                spin_lock(&journal->j_state_lock);
                spin_lock(&journal->j_list_lock);
                nblocks = jbd_space_needed(journal);
-               if (__log_space_left(journal) < nblocks) {
+               space_left = __log_space_left(journal);
+               if (space_left < nblocks) {
                        int chkpt = journal->j_checkpoint_transactions != NULL;
+                       tid_t tid = 0;
 
+                       if (journal->j_committing_transaction)
+                               tid = journal->j_committing_transaction->t_tid;
                        spin_unlock(&journal->j_list_lock);
                        spin_unlock(&journal->j_state_lock);
                        if (chkpt) {
                                log_do_checkpoint(journal);
+                       } else if (cleanup_journal_tail(journal) == 0) {
+                               /* We were able to recover space; yay! */
+                               ;
+                       } else if (tid) {
+                               log_wait_commit(journal, tid);
                        } else {
-                               printk(KERN_ERR "%s: no transactions\n",
-                                      __func__);
+                               printk(KERN_ERR "%s: needed %d blocks and "
+                                      "only had %d space available\n",
+                                      __func__, nblocks, space_left);
+                               printk(KERN_ERR "%s: no way to get more "
+                                      "journal space\n", __func__);
+                               WARN_ON(1);
                                journal_abort(journal, 0);
                        }
-
                        spin_lock(&journal->j_state_lock);
                } else {
                        spin_unlock(&journal->j_list_lock);
index 9203c3332f170887a2aff921c81946826ddd1cf9..9497718fe920dbdbd1311c812f6fb0c41fd60b49 100644 (file)
@@ -116,7 +116,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
  */
 void __jbd2_log_wait_for_space(journal_t *journal)
 {
-       int nblocks;
+       int nblocks, space_left;
        assert_spin_locked(&journal->j_state_lock);
 
        nblocks = jbd_space_needed(journal);
@@ -129,25 +129,43 @@ void __jbd2_log_wait_for_space(journal_t *journal)
                /*
                 * Test again, another process may have checkpointed while we
                 * were waiting for the checkpoint lock. If there are no
-                * outstanding transactions there is nothing to checkpoint and
-                * we can't make progress. Abort the journal in this case.
+                * transactions ready to be checkpointed, try to recover
+                * journal space by calling cleanup_journal_tail(), and if
+                * that doesn't work, by waiting for the currently committing
+                * transaction to complete.  If there is absolutely no way
+                * to make progress, this is either a BUG or corrupted
+                * filesystem, so abort the journal and leave a stack
+                * trace for forensic evidence.
                 */
                spin_lock(&journal->j_state_lock);
                spin_lock(&journal->j_list_lock);
                nblocks = jbd_space_needed(journal);
-               if (__jbd2_log_space_left(journal) < nblocks) {
+               space_left = __jbd2_log_space_left(journal);
+               if (space_left < nblocks) {
                        int chkpt = journal->j_checkpoint_transactions != NULL;
+                       tid_t tid = 0;
 
+                       if (journal->j_committing_transaction)
+                               tid = journal->j_committing_transaction->t_tid;
                        spin_unlock(&journal->j_list_lock);
                        spin_unlock(&journal->j_state_lock);
                        if (chkpt) {
                                jbd2_log_do_checkpoint(journal);
+                       } else if (jbd2_cleanup_journal_tail(journal) == 0) {
+                               /* We were able to recover space; yay! */
+                               ;
+                       } else if (tid) {
+                               jbd2_log_wait_commit(journal, tid);
                        } else {
-                               printk(KERN_ERR "%s: no transactions\n",
-                                      __func__);
+                               printk(KERN_ERR "%s: needed %d blocks and "
+                                      "only had %d space available\n",
+                                      __func__, nblocks, space_left);
+                               printk(KERN_ERR "%s: no way to get more "
+                                      "journal space in %s\n", __func__,
+                                      journal->j_devname);
+                               WARN_ON(1);
                                jbd2_journal_abort(journal, 0);
                        }
-
                        spin_lock(&journal->j_state_lock);
                } else {
                        spin_unlock(&journal->j_list_lock);
index 783de118de9235583bda263db9c9ce665333c4c3..e70d657a19f810ad5f3c714e6bfff6e5303d226d 100644 (file)
@@ -1089,6 +1089,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
        if (!journal->j_wbuf) {
                printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
                        __func__);
+               jbd2_stats_proc_exit(journal);
                kfree(journal);
                return NULL;
        }
@@ -1098,6 +1099,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
        if (err) {
                printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
                       __func__);
+               jbd2_stats_proc_exit(journal);
                kfree(journal);
                return NULL;
        }
index 8adebd3e43c690fbf0469cf9b235279998c252c8..3cceef4ad2b7df413e98b8171cadf074de83ad2d 100644 (file)
@@ -85,15 +85,15 @@ static int jffs2_garbage_collect_thread(void *_c)
        for (;;) {
                allow_signal(SIGHUP);
        again:
+               spin_lock(&c->erase_completion_lock);
                if (!jffs2_thread_should_wake(c)) {
                        set_current_state (TASK_INTERRUPTIBLE);
+                       spin_unlock(&c->erase_completion_lock);
                        D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n"));
-                       /* Yes, there's a race here; we checked jffs2_thread_should_wake()
-                          before setting current->state to TASK_INTERRUPTIBLE. But it doesn't
-                          matter - We don't care if we miss a wakeup, because the GC thread
-                          is only an optimisation anyway. */
                        schedule();
-               }
+               } else
+                       spin_unlock(&c->erase_completion_lock);
+                       
 
                /* This thread is purely an optimisation. But if it runs when
                   other things could be running, it actually makes things a
index 47b045797e42ff99a568279cfe6cf6dbc285cf5d..90cb60d0978767c305ce1ed888e712471b72b0d3 100644 (file)
@@ -19,7 +19,7 @@
 
 static void *lzo_mem;
 static void *lzo_compress_buf;
-static DEFINE_MUTEX(deflate_mutex);
+static DEFINE_MUTEX(deflate_mutex);    /* for lzo_mem and lzo_compress_buf */
 
 static void free_workspace(void)
 {
@@ -49,18 +49,21 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out,
 
        mutex_lock(&deflate_mutex);
        ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem);
-       mutex_unlock(&deflate_mutex);
-
        if (ret != LZO_E_OK)
-               return -1;
+               goto fail;
 
        if (compress_size > *dstlen)
-               return -1;
+               goto fail;
 
        memcpy(cpage_out, lzo_compress_buf, compress_size);
-       *dstlen = compress_size;
+       mutex_unlock(&deflate_mutex);
 
+       *dstlen = compress_size;
        return 0;
+
+ fail:
+       mutex_unlock(&deflate_mutex);
+       return -1;
 }
 
 static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
index 0875b60b4bf700cc8fda2fad76437d0dc9ea7420..21a052915aa9363acb0cd1e2b34567ef782b57f5 100644 (file)
@@ -261,9 +261,11 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
 
        jffs2_sum_reset_collected(c->summary); /* reset collected summary */
 
+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
        /* adjust write buffer offset, else we get a non contiguous write bug */
        if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len)
                c->wbuf_ofs = 0xffffffff;
+#endif
 
        D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset));
 
diff --git a/fs/msdos/Makefile b/fs/msdos/Makefile
deleted file mode 100644 (file)
index ea67646..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the Linux msdos filesystem routines.
-#
-
-obj-$(CONFIG_MSDOS_FS) += msdos.o
-
-msdos-y := namei.o
index 0c10a0b3f1460c5ff8d533de1c6304a657c097fd..df26aa88fa47cd46731f506d270d2faafc2e1fbd 100644 (file)
@@ -1,43 +1,45 @@
-#include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/sched.h>
-#include <linux/seq_file.h>
 #include <linux/time.h>
 #include <asm/cputime.h>
 
-static int uptime_proc_show(struct seq_file *m, void *v)
+static int proc_calc_metrics(char *page, char **start, off_t off,
+                                int count, int *eof, int len)
+{
+       if (len <= off + count)
+               *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len > count)
+               len = count;
+       if (len < 0)
+               len = 0;
+       return len;
+}
+
+static int uptime_read_proc(char *page, char **start, off_t off, int count,
+                           int *eof, void *data)
 {
        struct timespec uptime;
        struct timespec idle;
+       int len;
        cputime_t idletime = cputime_add(init_task.utime, init_task.stime);
 
        do_posix_clock_monotonic_gettime(&uptime);
        monotonic_to_bootbased(&uptime);
        cputime_to_timespec(idletime, &idle);
-       seq_printf(m, "%lu.%02lu %lu.%02lu\n",
+       len = sprintf(page, "%lu.%02lu %lu.%02lu\n",
                        (unsigned long) uptime.tv_sec,
                        (uptime.tv_nsec / (NSEC_PER_SEC / 100)),
                        (unsigned long) idle.tv_sec,
                        (idle.tv_nsec / (NSEC_PER_SEC / 100)));
-       return 0;
+       return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-static int uptime_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, uptime_proc_show, NULL);
-}
-
-static const struct file_operations uptime_proc_fops = {
-       .open           = uptime_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
 static int __init proc_uptime_init(void)
 {
-       proc_create("uptime", 0, NULL, &uptime_proc_fops);
+       create_proc_read_entry("uptime", 0, NULL, uptime_read_proc, NULL);
        return 0;
 }
 module_init(proc_uptime_init);
diff --git a/fs/vfat/Makefile b/fs/vfat/Makefile
deleted file mode 100644 (file)
index 40f2798..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the linux vfat-filesystem routines.
-#
-
-obj-$(CONFIG_VFAT_FS) += vfat.o
-
-vfat-y := namei.o
diff --git a/include/asm-x86/iomap.h b/include/asm-x86/iomap.h
new file mode 100644 (file)
index 0000000..c1f0628
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright Â© 2008 Ingo Molnar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+void *
+iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+
+void
+iounmap_atomic(void *kvaddr, enum km_type type);
index eb4b35031a55601ac333490650a4a48082b6faca..152b34da927c1d8117c42d06d90a3adc0d214109 100644 (file)
@@ -159,6 +159,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_SW_FINISH 0x20
 #define DRM_I915_GEM_SET_TILING        0x21
 #define DRM_I915_GEM_GET_TILING        0x22
+#define DRM_I915_GEM_GET_APERTURE 0x23
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -190,6 +191,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_SW_FINISH   DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish)
 #define DRM_IOCTL_I915_GEM_SET_TILING  DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling)
 #define DRM_IOCTL_I915_GEM_GET_TILING  DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
+#define DRM_IOCTL_I915_GEM_GET_APERTURE        DRM_IOR  (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -600,4 +602,15 @@ struct drm_i915_gem_get_tiling {
        uint32_t swizzle_mode;
 };
 
+struct drm_i915_gem_get_aperture {
+       /** Total size of the aperture used by i915_gem_execbuffer, in bytes */
+       uint64_t aper_size;
+
+       /**
+        * Available space in the aperture used by i915_gem_execbuffer, in
+        * bytes
+        */
+       uint64_t aper_available_size;
+};
+
 #endif                         /* _I915_DRM_H_ */
index 1c91a176b9ae8206f872a55a1318fb74048dbdec..6a642098e5c3524ad69fd15993268f35ef02cad9 100644 (file)
@@ -236,12 +236,16 @@ static inline void *bio_data(struct bio *bio)
 #define __BVEC_END(bio)                bio_iovec_idx((bio), (bio)->bi_vcnt - 1)
 #define __BVEC_START(bio)      bio_iovec_idx((bio), (bio)->bi_idx)
 
+/* Default implementation of BIOVEC_PHYS_MERGEABLE */
+#define __BIOVEC_PHYS_MERGEABLE(vec1, vec2)    \
+       ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
+
 /*
  * allow arch override, for eg virtualized architectures (put in asm/io.h)
  */
 #ifndef BIOVEC_PHYS_MERGEABLE
 #define BIOVEC_PHYS_MERGEABLE(vec1, vec2)      \
-       ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
+       __BIOVEC_PHYS_MERGEABLE(vec1, vec2)
 #endif
 
 #define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \
index 2b3645b1acf4609e55fa36f22368cca34d439a2a..07e510a3b00a89e78c2f48b591208b19dac6ef4e 100644 (file)
@@ -239,7 +239,7 @@ static inline void hrtimer_add_expires(struct hrtimer *timer, ktime_t time)
        timer->_softexpires = ktime_add_safe(timer->_softexpires, time);
 }
 
-static inline void hrtimer_add_expires_ns(struct hrtimer *timer, unsigned long ns)
+static inline void hrtimer_add_expires_ns(struct hrtimer *timer, u64 ns)
 {
        timer->_expires = ktime_add_ns(timer->_expires, ns);
        timer->_softexpires = ktime_add_ns(timer->_softexpires, ns);
index 9e7b49b8062d64ec5456a0d5ab3b71e97f5f16b9..a5cb0c3f6dcf263834115ef359b11f87803c23d5 100644 (file)
@@ -114,6 +114,8 @@ extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 
 extern int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                             u16 vlan_tci, int polling);
+extern int vlan_hwaccel_do_receive(struct sk_buff *skb);
+
 #else
 static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
@@ -133,6 +135,11 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
        BUG();
        return NET_XMIT_SUCCESS;
 }
+
+static inline int vlan_hwaccel_do_receive(struct sk_buff *skb)
+{
+       return 0;
+}
 #endif
 
 /**
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
new file mode 100644 (file)
index 0000000..82df317
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright Â© 2008 Keith Packard <keithp@keithp.com>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _LINUX_IO_MAPPING_H
+#define _LINUX_IO_MAPPING_H
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/iomap.h>
+
+/*
+ * The io_mapping mechanism provides an abstraction for mapping
+ * individual pages from an io device to the CPU in an efficient fashion.
+ *
+ * See Documentation/io_mapping.txt
+ */
+
+/* this struct isn't actually defined anywhere */
+struct io_mapping;
+
+#ifdef CONFIG_HAVE_ATOMIC_IOMAP
+
+/*
+ * For small address space machines, mapping large objects
+ * into the kernel virtual space isn't practical. Where
+ * available, use fixmap support to dynamically map pages
+ * of the object at run time.
+ */
+
+static inline struct io_mapping *
+io_mapping_create_wc(unsigned long base, unsigned long size)
+{
+       return (struct io_mapping *) base;
+}
+
+static inline void
+io_mapping_free(struct io_mapping *mapping)
+{
+}
+
+/* Atomic map/unmap */
+static inline void *
+io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset)
+{
+       offset += (unsigned long) mapping;
+       return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0,
+                                    __pgprot(__PAGE_KERNEL_WC));
+}
+
+static inline void
+io_mapping_unmap_atomic(void *vaddr)
+{
+       iounmap_atomic(vaddr, KM_USER0);
+}
+
+static inline void *
+io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
+{
+       offset += (unsigned long) mapping;
+       return ioremap_wc(offset, PAGE_SIZE);
+}
+
+static inline void
+io_mapping_unmap(void *vaddr)
+{
+       iounmap(vaddr);
+}
+
+#else
+
+/* Create the io_mapping object*/
+static inline struct io_mapping *
+io_mapping_create_wc(unsigned long base, unsigned long size)
+{
+       return (struct io_mapping *) ioremap_wc(base, size);
+}
+
+static inline void
+io_mapping_free(struct io_mapping *mapping)
+{
+       iounmap(mapping);
+}
+
+/* Atomic map/unmap */
+static inline void *
+io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset)
+{
+       return ((char *) mapping) + offset;
+}
+
+static inline void
+io_mapping_unmap_atomic(void *vaddr)
+{
+}
+
+/* Non-atomic map/unmap */
+static inline void *
+io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
+{
+       return ((char *) mapping) + offset;
+}
+
+static inline void
+io_mapping_unmap(void *vaddr)
+{
+}
+
+#endif /* HAVE_ATOMIC_IOMAP */
+
+#endif /* _LINUX_IO_MAPPING_H */
index f5441edee55f647be39b6432edb30f83bc81bb13..c7665a4134c552af7559ff1d4737eba9e33e30b3 100644 (file)
@@ -373,6 +373,8 @@ enum {
        ATA_HORKAGE_IVB         = (1 << 8),     /* cbl det validity bit bugs */
        ATA_HORKAGE_STUCK_ERR   = (1 << 9),     /* stuck ERR on next PACKET */
        ATA_HORKAGE_BRIDGE_OK   = (1 << 10),    /* no bridge limits */
+       ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands
+                                                   not multiple of 16 bytes */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
index ba63858056c7a5f0d3e7017fb19808e6e9dae5b1..e0a9b207920d37d5e9d6fd98ae8cc4dc809808eb 100644 (file)
 #define DELETED_FLAG   0xe5    /* marks file as deleted when in name[0] */
 #define IS_FREE(n)     (!*(n) || *(n) == DELETED_FLAG)
 
-/* valid file mode bits */
-#define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
-/* Convert attribute bits and a mask to the UNIX mode. */
-#define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
-
 #define MSDOS_NAME     11      /* maximum name length */
 #define MSDOS_LONGNAME 256     /* maximum name length */
 #define MSDOS_SLOTS    21      /* max # of slots for short and long names */
@@ -167,282 +162,10 @@ struct msdos_dir_slot {
 };
 
 #ifdef __KERNEL__
-
-#include <linux/buffer_head.h>
-#include <linux/string.h>
-#include <linux/nls.h>
-#include <linux/fs.h>
-#include <linux/mutex.h>
-
-/*
- * vfat shortname flags
- */
-#define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */
-#define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */
-#define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */
-#define VFAT_SFN_CREATE_WIN95  0x0100 /* emulate win95 rule for create */
-#define VFAT_SFN_CREATE_WINNT  0x0200 /* emulate winnt rule for create */
-
-struct fat_mount_options {
-       uid_t fs_uid;
-       gid_t fs_gid;
-       unsigned short fs_fmask;
-       unsigned short fs_dmask;
-       unsigned short codepage;  /* Codepage for shortname conversions */
-       char *iocharset;          /* Charset used for filename input/display */
-       unsigned short shortname; /* flags for shortname display/create rule */
-       unsigned char name_check; /* r = relaxed, n = normal, s = strict */
-       unsigned short allow_utime;/* permission for setting the [am]time */
-       unsigned quiet:1,         /* set = fake successful chmods and chowns */
-                showexec:1,      /* set = only set x bit for com/exe/bat */
-                sys_immutable:1, /* set = system files are immutable */
-                dotsOK:1,        /* set = hidden and system files are named '.filename' */
-                isvfat:1,        /* 0=no vfat long filename support, 1=vfat support */
-                utf8:1,          /* Use of UTF-8 character set (Default) */
-                unicode_xlate:1, /* create escape sequences for unhandled Unicode */
-                numtail:1,       /* Does first alias have a numeric '~1' type tail? */
-                flush:1,         /* write things quickly */
-                nocase:1,        /* Does this need case conversion? 0=need case conversion*/
-                usefree:1,       /* Use free_clusters for FAT32 */
-                tz_utc:1;        /* Filesystem timestamps are in UTC */
-};
-
-#define FAT_HASH_BITS  8
-#define FAT_HASH_SIZE  (1UL << FAT_HASH_BITS)
-#define FAT_HASH_MASK  (FAT_HASH_SIZE-1)
-
-/*
- * MS-DOS file system in-core superblock data
- */
-struct msdos_sb_info {
-       unsigned short sec_per_clus; /* sectors/cluster */
-       unsigned short cluster_bits; /* log2(cluster_size) */
-       unsigned int cluster_size;   /* cluster size */
-       unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
-       unsigned short fat_start;
-       unsigned long fat_length;    /* FAT start & length (sec.) */
-       unsigned long dir_start;
-       unsigned short dir_entries;  /* root dir start & entries */
-       unsigned long data_start;    /* first data sector */
-       unsigned long max_cluster;   /* maximum cluster number */
-       unsigned long root_cluster;  /* first cluster of the root directory */
-       unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */
-       struct mutex fat_lock;
-       unsigned int prev_free;      /* previously allocated cluster number */
-       unsigned int free_clusters;  /* -1 if undefined */
-       unsigned int free_clus_valid; /* is free_clusters valid? */
-       struct fat_mount_options options;
-       struct nls_table *nls_disk;  /* Codepage used on disk */
-       struct nls_table *nls_io;    /* Charset used for input and display */
-       const void *dir_ops;                 /* Opaque; default directory operations */
-       int dir_per_block;           /* dir entries per block */
-       int dir_per_block_bits;      /* log2(dir_per_block) */
-
-       int fatent_shift;
-       struct fatent_operations *fatent_ops;
-
-       spinlock_t inode_hash_lock;
-       struct hlist_head inode_hashtable[FAT_HASH_SIZE];
-};
-
-#define FAT_CACHE_VALID        0       /* special case for valid cache */
-
-/*
- * MS-DOS file system inode data in memory
- */
-struct msdos_inode_info {
-       spinlock_t cache_lru_lock;
-       struct list_head cache_lru;
-       int nr_caches;
-       /* for avoiding the race between fat_free() and fat_get_cluster() */
-       unsigned int cache_valid_id;
-
-       loff_t mmu_private;
-       int i_start;            /* first cluster or 0 */
-       int i_logstart;         /* logical first cluster */
-       int i_attrs;            /* unused attribute bits */
-       loff_t i_pos;           /* on-disk position of directory entry or 0 */
-       struct hlist_node i_fat_hash;   /* hash by i_location */
-       struct inode vfs_inode;
-};
-
-struct fat_slot_info {
-       loff_t i_pos;           /* on-disk position of directory entry */
-       loff_t slot_off;        /* offset for slot or de start */
-       int nr_slots;           /* number of slots + 1(de) in filename */
-       struct msdos_dir_entry *de;
-       struct buffer_head *bh;
-};
-
-static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb)
-{
-       return sb->s_fs_info;
-}
-
-static inline struct msdos_inode_info *MSDOS_I(struct inode *inode)
-{
-       return container_of(inode, struct msdos_inode_info, vfs_inode);
-}
-
-/* Return the FAT attribute byte for this inode */
-static inline u8 fat_attr(struct inode *inode)
-{
-       return ((inode->i_mode & S_IWUGO) ? ATTR_NONE : ATTR_RO) |
-               (S_ISDIR(inode->i_mode) ? ATTR_DIR : ATTR_NONE) |
-               MSDOS_I(inode)->i_attrs;
-}
-
-static inline unsigned char fat_checksum(const __u8 *name)
-{
-       unsigned char s = name[0];
-       s = (s<<7) + (s>>1) + name[1];  s = (s<<7) + (s>>1) + name[2];
-       s = (s<<7) + (s>>1) + name[3];  s = (s<<7) + (s>>1) + name[4];
-       s = (s<<7) + (s>>1) + name[5];  s = (s<<7) + (s>>1) + name[6];
-       s = (s<<7) + (s>>1) + name[7];  s = (s<<7) + (s>>1) + name[8];
-       s = (s<<7) + (s>>1) + name[9];  s = (s<<7) + (s>>1) + name[10];
-       return s;
-}
-
-static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus)
-{
-       return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus
-               + sbi->data_start;
-}
-
-static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len)
-{
-#ifdef __BIG_ENDIAN
-       while (len--) {
-               *dst++ = src[0] | (src[1] << 8);
-               src += 2;
-       }
-#else
-       memcpy(dst, src, len * 2);
-#endif
-}
-
-static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
-{
-#ifdef __BIG_ENDIAN
-       while (len--) {
-               dst[0] = *src & 0x00FF;
-               dst[1] = (*src & 0xFF00) >> 8;
-               dst += 2;
-               src++;
-       }
-#else
-       memcpy(dst, src, len * 2);
-#endif
-}
-
 /* media of boot sector */
 static inline int fat_valid_media(u8 media)
 {
        return 0xf8 <= media || media == 0xf0;
 }
-
-/* fat/cache.c */
-extern void fat_cache_inval_inode(struct inode *inode);
-extern int fat_get_cluster(struct inode *inode, int cluster,
-                          int *fclus, int *dclus);
-extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
-                   unsigned long *mapped_blocks);
-
-/* fat/dir.c */
-extern const struct file_operations fat_dir_operations;
-extern int fat_search_long(struct inode *inode, const unsigned char *name,
-                          int name_len, struct fat_slot_info *sinfo);
-extern int fat_dir_empty(struct inode *dir);
-extern int fat_subdirs(struct inode *dir);
-extern int fat_scan(struct inode *dir, const unsigned char *name,
-                   struct fat_slot_info *sinfo);
-extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
-                               struct msdos_dir_entry **de, loff_t *i_pos);
-extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
-extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
-                          struct fat_slot_info *sinfo);
-extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
-
-/* fat/fatent.c */
-struct fat_entry {
-       int entry;
-       union {
-               u8 *ent12_p[2];
-               __le16 *ent16_p;
-               __le32 *ent32_p;
-       } u;
-       int nr_bhs;
-       struct buffer_head *bhs[2];
-};
-
-static inline void fatent_init(struct fat_entry *fatent)
-{
-       fatent->nr_bhs = 0;
-       fatent->entry = 0;
-       fatent->u.ent32_p = NULL;
-       fatent->bhs[0] = fatent->bhs[1] = NULL;
-}
-
-static inline void fatent_set_entry(struct fat_entry *fatent, int entry)
-{
-       fatent->entry = entry;
-       fatent->u.ent32_p = NULL;
-}
-
-static inline void fatent_brelse(struct fat_entry *fatent)
-{
-       int i;
-       fatent->u.ent32_p = NULL;
-       for (i = 0; i < fatent->nr_bhs; i++)
-               brelse(fatent->bhs[i]);
-       fatent->nr_bhs = 0;
-       fatent->bhs[0] = fatent->bhs[1] = NULL;
-}
-
-extern void fat_ent_access_init(struct super_block *sb);
-extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent,
-                       int entry);
-extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
-                        int new, int wait);
-extern int fat_alloc_clusters(struct inode *inode, int *cluster,
-                             int nr_cluster);
-extern int fat_free_clusters(struct inode *inode, int cluster);
-extern int fat_count_free_clusters(struct super_block *sb);
-
-/* fat/file.c */
-extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
-                            unsigned int cmd, unsigned long arg);
-extern const struct file_operations fat_file_operations;
-extern const struct inode_operations fat_file_inode_operations;
-extern int fat_setattr(struct dentry * dentry, struct iattr * attr);
-extern void fat_truncate(struct inode *inode);
-extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
-                      struct kstat *stat);
-
-/* fat/inode.c */
-extern void fat_attach(struct inode *inode, loff_t i_pos);
-extern void fat_detach(struct inode *inode);
-extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
-extern struct inode *fat_build_inode(struct super_block *sb,
-                       struct msdos_dir_entry *de, loff_t i_pos);
-extern int fat_sync_inode(struct inode *inode);
-extern int fat_fill_super(struct super_block *sb, void *data, int silent,
-                       const struct inode_operations *fs_dir_inode_ops, int isvfat);
-
-extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
-                           struct inode *i2);
-/* fat/misc.c */
-extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
-extern void fat_clusters_flush(struct super_block *sb);
-extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
-extern int date_dos2unix(unsigned short time, unsigned short date, int tz_utc);
-extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date,
-                             int tz_utc);
-extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
-
-int fat_cache_init(void);
-void fat_cache_destroy(void);
-
-#endif /* __KERNEL__ */
-
-#endif
+#endif /* !__KERNEL__ */
+#endif /* !_LINUX_MSDOS_FS_H */
index ee5124ec319e4e036f1f139dff39c428c6732190..00e2b575021f6d8f6ee1fd819cf18137baf3fcd5 100644 (file)
@@ -282,9 +282,25 @@ struct cfi_private {
 /*
  * Returns the command address according to the given geometry.
  */
-static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type)
+static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs,
+                               struct map_info *map, struct cfi_private *cfi)
 {
-       return (cmd_ofs * type) * interleave;
+       unsigned bankwidth = map_bankwidth(map);
+       unsigned interleave = cfi_interleave(cfi);
+       unsigned type = cfi->device_type;
+       uint32_t addr;
+       
+       addr = (cmd_ofs * type) * interleave;
+
+       /* Modify the unlock address if we are in compatiblity mode.
+        * For 16bit devices on 8 bit busses
+        * and 32bit devices on 16 bit busses
+        * set the low bit of the alternating bit sequence of the address.
+        */
+       if (((type * interleave) > bankwidth) && ((uint8_t)cmd_ofs == 0xaa))
+               addr |= (type >> 1)*interleave;
+
+       return  addr;
 }
 
 /*
@@ -430,7 +446,7 @@ static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t
                                int type, map_word *prev_val)
 {
        map_word val;
-       uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
+       uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi);
        val = cfi_build_cmd(cmd, map, cfi);
 
        if (prev_val)
index b483f39a7112073e17c6ce8edc2fa0b17c9b61e1..295b7c756ca6107aee29ee4c12e3eb2f486c9f7e 100644 (file)
@@ -1349,6 +1349,8 @@ struct task_struct {
         */
        unsigned long timer_slack_ns;
        unsigned long default_timer_slack_ns;
+
+       struct list_head        *scm_work_list;
 };
 
 /*
index d4ba79248a27fab0f33a9697deebd02bfb9440e3..daf9685b861c05143b17c529b1b72e77aa49c4ee 100644 (file)
@@ -186,4 +186,9 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu);
 unsigned long round_jiffies(unsigned long j);
 unsigned long round_jiffies_relative(unsigned long j);
 
+unsigned long __round_jiffies_up(unsigned long j, int cpu);
+unsigned long __round_jiffies_up_relative(unsigned long j, int cpu);
+unsigned long round_jiffies_up(unsigned long j);
+unsigned long round_jiffies_up_relative(unsigned long j);
+
 #endif
index 2158fc0d5a56448001fa8a0cb569b66790cdd60a..117f1b7405cfc92ff1c342d2d92a9f35c2e9cbb5 100644 (file)
@@ -99,7 +99,7 @@ void arch_update_cpu_topology(void);
                                | SD_BALANCE_FORK       \
                                | SD_BALANCE_EXEC       \
                                | SD_WAKE_AFFINE        \
-                               | SD_WAKE_IDLE          \
+                               | SD_WAKE_BALANCE       \
                                | SD_SHARE_CPUPOWER,    \
        .last_balance           = jiffies,              \
        .balance_interval       = 1,                    \
@@ -120,10 +120,10 @@ void arch_update_cpu_topology(void);
        .wake_idx               = 1,                    \
        .forkexec_idx           = 1,                    \
        .flags                  = SD_LOAD_BALANCE       \
-                               | SD_BALANCE_NEWIDLE    \
                                | SD_BALANCE_FORK       \
                                | SD_BALANCE_EXEC       \
                                | SD_WAKE_AFFINE        \
+                               | SD_WAKE_BALANCE       \
                                | SD_SHARE_PKG_RESOURCES\
                                | BALANCE_FOR_MC_POWER, \
        .last_balance           = jiffies,              \
@@ -146,10 +146,10 @@ void arch_update_cpu_topology(void);
        .wake_idx               = 1,                    \
        .forkexec_idx           = 1,                    \
        .flags                  = SD_LOAD_BALANCE       \
-                               | SD_BALANCE_NEWIDLE    \
-                               | SD_BALANCE_FORK       \
                                | SD_BALANCE_EXEC       \
+                               | SD_BALANCE_FORK       \
                                | SD_WAKE_AFFINE        \
+                               | SD_WAKE_BALANCE       \
                                | BALANCE_FOR_PKG_POWER,\
        .last_balance           = jiffies,              \
        .balance_interval       = 1,                    \
index 06df126103cab8224d6cf7ae64c7f00e75f06e12..33e9986beb86dd95d6f3f962ca8a89281c874a9d 100644 (file)
@@ -14,8 +14,9 @@
 
 struct scm_fp_list
 {
-       int             count;
-       struct file     *fp[SCM_MAX_FD];
+       struct list_head        list;
+       int                     count;
+       struct file             *fp[SCM_MAX_FD];
 };
 
 struct scm_cookie
index 35eebd5510c2165c6f8daa2cef1fecab9187d6d0..358e77564e6f8b0b4c3964a36da48cc3051d6e73 100644 (file)
@@ -2497,7 +2497,6 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
        list_del(&cgrp->sibling);
        spin_lock(&cgrp->dentry->d_lock);
        d = dget(cgrp->dentry);
-       cgrp->dentry = NULL;
        spin_unlock(&d->d_lock);
 
        cgroup_d_remove_dir(d);
index e8819bc6f462c18761c11861b4808fd28223b431..57c933ffbee1aab4794c30f3690b8188e4ddf02a 100644 (file)
@@ -397,7 +397,7 @@ struct cfs_rq {
         * 'curr' points to currently running entity on this cfs_rq.
         * It is set to NULL otherwise (i.e when none are currently running).
         */
-       struct sched_entity *curr, *next;
+       struct sched_entity *curr, *next, *last;
 
        unsigned long nr_spread_over;
 
@@ -1805,7 +1805,9 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd)
        /*
         * Buddy candidates are cache hot:
         */
-       if (sched_feat(CACHE_HOT_BUDDY) && (&p->se == cfs_rq_of(&p->se)->next))
+       if (sched_feat(CACHE_HOT_BUDDY) &&
+                       (&p->se == cfs_rq_of(&p->se)->next ||
+                        &p->se == cfs_rq_of(&p->se)->last))
                return 1;
 
        if (p->sched_class != &fair_sched_class)
@@ -6875,15 +6877,17 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu)
        struct sched_domain *tmp;
 
        /* Remove the sched domains which do not contribute to scheduling. */
-       for (tmp = sd; tmp; tmp = tmp->parent) {
+       for (tmp = sd; tmp; ) {
                struct sched_domain *parent = tmp->parent;
                if (!parent)
                        break;
+
                if (sd_parent_degenerate(tmp, parent)) {
                        tmp->parent = parent->parent;
                        if (parent->parent)
                                parent->parent->child = tmp;
-               }
+               } else
+                       tmp = tmp->parent;
        }
 
        if (sd && sd_degenerate(sd)) {
@@ -7672,6 +7676,7 @@ static int __build_sched_domains(const cpumask_t *cpu_map,
 error:
        free_sched_groups(cpu_map, tmpmask);
        SCHED_CPUMASK_FREE((void *)allmasks);
+       kfree(rd);
        return -ENOMEM;
 #endif
 }
index ce514afd78ff7998338b6661ae22475e808fa3fa..51aa3e102acb7e3c838dccbef4bbc0c4756dd0e0 100644 (file)
@@ -341,23 +341,20 @@ static void __dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
                cfs_rq->rb_leftmost = next_node;
        }
 
-       if (cfs_rq->next == se)
-               cfs_rq->next = NULL;
-
        rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
 }
 
-static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq)
-{
-       return cfs_rq->rb_leftmost;
-}
-
 static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq)
 {
-       return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node);
+       struct rb_node *left = cfs_rq->rb_leftmost;
+
+       if (!left)
+               return NULL;
+
+       return rb_entry(left, struct sched_entity, run_node);
 }
 
-static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
+static struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
 {
        struct rb_node *last = rb_last(&cfs_rq->tasks_timeline);
 
@@ -741,6 +738,12 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep)
 #endif
        }
 
+       if (cfs_rq->last == se)
+               cfs_rq->last = NULL;
+
+       if (cfs_rq->next == se)
+               cfs_rq->next = NULL;
+
        if (se != cfs_rq->curr)
                __dequeue_entity(cfs_rq, se);
        account_entity_dequeue(cfs_rq, se);
@@ -794,24 +797,15 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 static int
 wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
 
-static struct sched_entity *
-pick_next(struct cfs_rq *cfs_rq, struct sched_entity *se)
-{
-       if (!cfs_rq->next || wakeup_preempt_entity(cfs_rq->next, se) == 1)
-               return se;
-
-       return cfs_rq->next;
-}
-
 static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
 {
-       struct sched_entity *se = NULL;
+       struct sched_entity *se = __pick_next_entity(cfs_rq);
 
-       if (first_fair(cfs_rq)) {
-               se = __pick_next_entity(cfs_rq);
-               se = pick_next(cfs_rq, se);
-               set_next_entity(cfs_rq, se);
-       }
+       if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, se) < 1)
+               return cfs_rq->next;
+
+       if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, se) < 1)
+               return cfs_rq->last;
 
        return se;
 }
@@ -1325,26 +1319,53 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se)
        return 0;
 }
 
+static void set_last_buddy(struct sched_entity *se)
+{
+       for_each_sched_entity(se)
+               cfs_rq_of(se)->last = se;
+}
+
+static void set_next_buddy(struct sched_entity *se)
+{
+       for_each_sched_entity(se)
+               cfs_rq_of(se)->next = se;
+}
+
 /*
  * Preempt the current task with a newly woken task if needed:
  */
 static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync)
 {
        struct task_struct *curr = rq->curr;
-       struct cfs_rq *cfs_rq = task_cfs_rq(curr);
        struct sched_entity *se = &curr->se, *pse = &p->se;
 
        if (unlikely(rt_prio(p->prio))) {
+               struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+
                update_rq_clock(rq);
                update_curr(cfs_rq);
                resched_task(curr);
                return;
        }
 
+       if (unlikely(p->sched_class != &fair_sched_class))
+               return;
+
        if (unlikely(se == pse))
                return;
 
-       cfs_rq_of(pse)->next = pse;
+       /*
+        * Only set the backward buddy when the current task is still on the
+        * rq. This can happen when a wakeup gets interleaved with schedule on
+        * the ->pre_schedule() or idle_balance() point, either of which can
+        * drop the rq lock.
+        *
+        * Also, during early boot the idle thread is in the fair class, for
+        * obvious reasons its a bad idea to schedule back to the idle thread.
+        */
+       if (sched_feat(LAST_BUDDY) && likely(se->on_rq && curr != rq->idle))
+               set_last_buddy(se);
+       set_next_buddy(pse);
 
        /*
         * We can come here with TIF_NEED_RESCHED already set from new task
@@ -1396,6 +1417,7 @@ static struct task_struct *pick_next_task_fair(struct rq *rq)
 
        do {
                se = pick_next_entity(cfs_rq);
+               set_next_entity(cfs_rq, se);
                cfs_rq = group_cfs_rq(se);
        } while (cfs_rq);
 
index fda016218296be0d09f54ca7d8d9e2294fb0dbbe..da5d93b5d2c6293ba2d14727964178552091184d 100644 (file)
@@ -12,3 +12,4 @@ SCHED_FEAT(LB_BIAS, 1)
 SCHED_FEAT(LB_WAKEUP_UPDATE, 1)
 SCHED_FEAT(ASYM_EFF_LOAD, 1)
 SCHED_FEAT(WAKEUP_OVERLAP, 0)
+SCHED_FEAT(LAST_BUDDY, 1)
index f362a85537777619d1ef22602042fba351a75e7d..75c8dde58c55fcdd2f0ae71f75ceb05213e0985e 100644 (file)
@@ -51,10 +51,6 @@ static void csd_flag_wait(struct call_single_data *data)
 {
        /* Wait for response */
        do {
-               /*
-                * We need to see the flags store in the IPI handler
-                */
-               smp_mb();
                if (!(data->flags & CSD_FLAG_WAIT))
                        break;
                cpu_relax();
@@ -76,6 +72,11 @@ static void generic_exec_single(int cpu, struct call_single_data *data)
        list_add_tail(&data->list, &dst->list);
        spin_unlock_irqrestore(&dst->lock, flags);
 
+       /*
+        * Make the list addition visible before sending the ipi.
+        */
+       smp_mb();
+
        if (ipi)
                arch_send_call_function_single_ipi(cpu);
 
@@ -157,7 +158,7 @@ void generic_smp_call_function_single_interrupt(void)
         * Need to see other stores to list head for checking whether
         * list is empty without holding q->lock
         */
-       smp_mb();
+       smp_read_barrier_depends();
        while (!list_empty(&q->list)) {
                unsigned int data_flags;
 
@@ -191,7 +192,7 @@ void generic_smp_call_function_single_interrupt(void)
                /*
                 * See comment on outer loop
                 */
-               smp_mb();
+               smp_read_barrier_depends();
        }
 }
 
@@ -370,6 +371,11 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
        list_add_tail_rcu(&data->csd.list, &call_function_queue);
        spin_unlock_irqrestore(&call_function_lock, flags);
 
+       /*
+        * Make the list addition visible before sending the ipi.
+        */
+       smp_mb();
+
        /* Send a message to all CPUs in the map */
        arch_send_call_function_ipi(mask);
 
index 56becf373c589ba90c36a5b6e23df0527b227663..dbd50fabe4c74ab241523fbf2b427c596e2838c5 100644 (file)
@@ -112,27 +112,8 @@ timer_set_base(struct timer_list *timer, struct tvec_base *new_base)
                                      tbase_get_deferrable(timer->base));
 }
 
-/**
- * __round_jiffies - function to round jiffies to a full second
- * @j: the time in (absolute) jiffies that should be rounded
- * @cpu: the processor number on which the timeout will happen
- *
- * __round_jiffies() rounds an absolute time in the future (in jiffies)
- * up or down to (approximately) full seconds. This is useful for timers
- * for which the exact time they fire does not matter too much, as long as
- * they fire approximately every X seconds.
- *
- * By rounding these timers to whole seconds, all such timers will fire
- * at the same time, rather than at various times spread out. The goal
- * of this is to have the CPU wake up less, which saves power.
- *
- * The exact rounding is skewed for each processor to avoid all
- * processors firing at the exact same time, which could lead
- * to lock contention or spurious cache line bouncing.
- *
- * The return value is the rounded version of the @j parameter.
- */
-unsigned long __round_jiffies(unsigned long j, int cpu)
+static unsigned long round_jiffies_common(unsigned long j, int cpu,
+               bool force_up)
 {
        int rem;
        unsigned long original = j;
@@ -154,8 +135,9 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
         * due to delays of the timer irq, long irq off times etc etc) then
         * we should round down to the whole second, not up. Use 1/4th second
         * as cutoff for this rounding as an extreme upper bound for this.
+        * But never round down if @force_up is set.
         */
-       if (rem < HZ/4) /* round down */
+       if (rem < HZ/4 && !force_up) /* round down */
                j = j - rem;
        else /* round up */
                j = j - rem + HZ;
@@ -167,6 +149,31 @@ unsigned long __round_jiffies(unsigned long j, int cpu)
                return original;
        return j;
 }
+
+/**
+ * __round_jiffies - function to round jiffies to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * __round_jiffies() rounds an absolute time in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The exact rounding is skewed for each processor to avoid all
+ * processors firing at the exact same time, which could lead
+ * to lock contention or spurious cache line bouncing.
+ *
+ * The return value is the rounded version of the @j parameter.
+ */
+unsigned long __round_jiffies(unsigned long j, int cpu)
+{
+       return round_jiffies_common(j, cpu, false);
+}
 EXPORT_SYMBOL_GPL(__round_jiffies);
 
 /**
@@ -191,13 +198,10 @@ EXPORT_SYMBOL_GPL(__round_jiffies);
  */
 unsigned long __round_jiffies_relative(unsigned long j, int cpu)
 {
-       /*
-        * In theory the following code can skip a jiffy in case jiffies
-        * increments right between the addition and the later subtraction.
-        * However since the entire point of this function is to use approximate
-        * timeouts, it's entirely ok to not handle that.
-        */
-       return  __round_jiffies(j + jiffies, cpu) - jiffies;
+       unsigned long j0 = jiffies;
+
+       /* Use j0 because jiffies might change while we run */
+       return round_jiffies_common(j + j0, cpu, false) - j0;
 }
 EXPORT_SYMBOL_GPL(__round_jiffies_relative);
 
@@ -218,7 +222,7 @@ EXPORT_SYMBOL_GPL(__round_jiffies_relative);
  */
 unsigned long round_jiffies(unsigned long j)
 {
-       return __round_jiffies(j, raw_smp_processor_id());
+       return round_jiffies_common(j, raw_smp_processor_id(), false);
 }
 EXPORT_SYMBOL_GPL(round_jiffies);
 
@@ -243,6 +247,71 @@ unsigned long round_jiffies_relative(unsigned long j)
 }
 EXPORT_SYMBOL_GPL(round_jiffies_relative);
 
+/**
+ * __round_jiffies_up - function to round jiffies up to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * This is the same as __round_jiffies() except that it will never
+ * round down.  This is useful for timeouts for which the exact time
+ * of firing does not matter too much, as long as they don't fire too
+ * early.
+ */
+unsigned long __round_jiffies_up(unsigned long j, int cpu)
+{
+       return round_jiffies_common(j, cpu, true);
+}
+EXPORT_SYMBOL_GPL(__round_jiffies_up);
+
+/**
+ * __round_jiffies_up_relative - function to round jiffies up to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * This is the same as __round_jiffies_relative() except that it will never
+ * round down.  This is useful for timeouts for which the exact time
+ * of firing does not matter too much, as long as they don't fire too
+ * early.
+ */
+unsigned long __round_jiffies_up_relative(unsigned long j, int cpu)
+{
+       unsigned long j0 = jiffies;
+
+       /* Use j0 because jiffies might change while we run */
+       return round_jiffies_common(j + j0, cpu, true) - j0;
+}
+EXPORT_SYMBOL_GPL(__round_jiffies_up_relative);
+
+/**
+ * round_jiffies_up - function to round jiffies up to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ *
+ * This is the same as round_jiffies() except that it will never
+ * round down.  This is useful for timeouts for which the exact time
+ * of firing does not matter too much, as long as they don't fire too
+ * early.
+ */
+unsigned long round_jiffies_up(unsigned long j)
+{
+       return round_jiffies_common(j, raw_smp_processor_id(), true);
+}
+EXPORT_SYMBOL_GPL(round_jiffies_up);
+
+/**
+ * round_jiffies_up_relative - function to round jiffies up to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ *
+ * This is the same as round_jiffies_relative() except that it will never
+ * round down.  This is useful for timeouts for which the exact time
+ * of firing does not matter too much, as long as they don't fire too
+ * early.
+ */
+unsigned long round_jiffies_up_relative(unsigned long j)
+{
+       return __round_jiffies_up_relative(j, raw_smp_processor_id());
+}
+EXPORT_SYMBOL_GPL(round_jiffies_up_relative);
+
 
 static inline void set_running_timer(struct tvec_base *base,
                                        struct timer_list *timer)
index b58f43bec3636e050bc6129d1fa58341aac1c946..33dbefd471e88f9571f299f92b433188dd6697de 100644 (file)
@@ -25,7 +25,7 @@ config TRACING
        bool
        select DEBUG_FS
        select RING_BUFFER
-       select STACKTRACE
+       select STACKTRACE if STACKTRACE_SUPPORT
        select TRACEPOINTS
        select NOP_TRACER
 
index cedf4e2682855000f28c7f5ddbe3a8fabd2bc0d2..3f338063864628a3ae42f0269018388062132a1a 100644 (file)
@@ -1022,8 +1022,23 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer,
        struct ring_buffer_event *event;
        u64 ts, delta;
        int commit = 0;
+       int nr_loops = 0;
 
  again:
+       /*
+        * We allow for interrupts to reenter here and do a trace.
+        * If one does, it will cause this original code to loop
+        * back here. Even with heavy interrupts happening, this
+        * should only happen a few times in a row. If this happens
+        * 1000 times in a row, there must be either an interrupt
+        * storm or we have something buggy.
+        * Bail!
+        */
+       if (unlikely(++nr_loops > 1000)) {
+               RB_WARN_ON(cpu_buffer, 1);
+               return NULL;
+       }
+
        ts = ring_buffer_time_stamp(cpu_buffer->cpu);
 
        /*
@@ -1532,10 +1547,23 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
 {
        struct buffer_page *reader = NULL;
        unsigned long flags;
+       int nr_loops = 0;
 
        spin_lock_irqsave(&cpu_buffer->lock, flags);
 
  again:
+       /*
+        * This should normally only loop twice. But because the
+        * start of the reader inserts an empty page, it causes
+        * a case where we will loop three times. There should be no
+        * reason to loop four times (that I know of).
+        */
+       if (unlikely(++nr_loops > 3)) {
+               RB_WARN_ON(cpu_buffer, 1);
+               reader = NULL;
+               goto out;
+       }
+
        reader = cpu_buffer->reader_page;
 
        /* If there's more to read, return this page */
@@ -1665,6 +1693,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
        struct ring_buffer_per_cpu *cpu_buffer;
        struct ring_buffer_event *event;
        struct buffer_page *reader;
+       int nr_loops = 0;
 
        if (!cpu_isset(cpu, buffer->cpumask))
                return NULL;
@@ -1672,6 +1701,19 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
        cpu_buffer = buffer->buffers[cpu];
 
  again:
+       /*
+        * We repeat when a timestamp is encountered. It is possible
+        * to get multiple timestamps from an interrupt entering just
+        * as one timestamp is about to be written. The max times
+        * that this can happen is the number of nested interrupts we
+        * can have.  Nesting 10 deep of interrupts is clearly
+        * an anomaly.
+        */
+       if (unlikely(++nr_loops > 10)) {
+               RB_WARN_ON(cpu_buffer, 1);
+               return NULL;
+       }
+
        reader = rb_get_reader_page(cpu_buffer);
        if (!reader)
                return NULL;
@@ -1722,6 +1764,7 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
        struct ring_buffer *buffer;
        struct ring_buffer_per_cpu *cpu_buffer;
        struct ring_buffer_event *event;
+       int nr_loops = 0;
 
        if (ring_buffer_iter_empty(iter))
                return NULL;
@@ -1730,6 +1773,19 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
        buffer = cpu_buffer->buffer;
 
  again:
+       /*
+        * We repeat when a timestamp is encountered. It is possible
+        * to get multiple timestamps from an interrupt entering just
+        * as one timestamp is about to be written. The max times
+        * that this can happen is the number of nested interrupts we
+        * can have. Nesting 10 deep of interrupts is clearly
+        * an anomaly.
+        */
+       if (unlikely(++nr_loops > 10)) {
+               RB_WARN_ON(cpu_buffer, 1);
+               return NULL;
+       }
+
        if (rb_per_cpu_empty(cpu_buffer))
                return NULL;
 
index 8a499e2adaec2554218051c730f77ccc784ef184..9f3b478f91716bdd1cc48ac6872c2a3c1412dbb8 100644 (file)
@@ -705,6 +705,7 @@ static void ftrace_trace_stack(struct trace_array *tr,
                               unsigned long flags,
                               int skip, int pc)
 {
+#ifdef CONFIG_STACKTRACE
        struct ring_buffer_event *event;
        struct stack_entry *entry;
        struct stack_trace trace;
@@ -730,6 +731,7 @@ static void ftrace_trace_stack(struct trace_array *tr,
 
        save_stack_trace(&trace);
        ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
+#endif
 }
 
 void __trace_stack(struct trace_array *tr,
@@ -1086,17 +1088,20 @@ static void s_stop(struct seq_file *m, void *p)
        mutex_unlock(&trace_types_lock);
 }
 
-#define KRETPROBE_MSG "[unknown/kretprobe'd]"
-
 #ifdef CONFIG_KRETPROBES
-static inline int kretprobed(unsigned long addr)
+static inline const char *kretprobed(const char *name)
 {
-       return addr == (unsigned long)kretprobe_trampoline;
+       static const char tramp_name[] = "kretprobe_trampoline";
+       int size = sizeof(tramp_name);
+
+       if (strncmp(tramp_name, name, size) == 0)
+               return "[unknown/kretprobe'd]";
+       return name;
 }
 #else
-static inline int kretprobed(unsigned long addr)
+static inline const char *kretprobed(const char *name)
 {
-       return 0;
+       return name;
 }
 #endif /* CONFIG_KRETPROBES */
 
@@ -1105,10 +1110,13 @@ seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
 {
 #ifdef CONFIG_KALLSYMS
        char str[KSYM_SYMBOL_LEN];
+       const char *name;
 
        kallsyms_lookup(address, NULL, NULL, NULL, str);
 
-       return trace_seq_printf(s, fmt, str);
+       name = kretprobed(str);
+
+       return trace_seq_printf(s, fmt, name);
 #endif
        return 1;
 }
@@ -1119,9 +1127,12 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt,
 {
 #ifdef CONFIG_KALLSYMS
        char str[KSYM_SYMBOL_LEN];
+       const char *name;
 
        sprint_symbol(str, address);
-       return trace_seq_printf(s, fmt, str);
+       name = kretprobed(str);
+
+       return trace_seq_printf(s, fmt, name);
 #endif
        return 1;
 }
@@ -1375,10 +1386,7 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
 
                seq_print_ip_sym(s, field->ip, sym_flags);
                trace_seq_puts(s, " (");
-               if (kretprobed(field->parent_ip))
-                       trace_seq_puts(s, KRETPROBE_MSG);
-               else
-                       seq_print_ip_sym(s, field->parent_ip, sym_flags);
+               seq_print_ip_sym(s, field->parent_ip, sym_flags);
                trace_seq_puts(s, ")\n");
                break;
        }
@@ -1494,12 +1502,9 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
                        ret = trace_seq_printf(s, " <-");
                        if (!ret)
                                return TRACE_TYPE_PARTIAL_LINE;
-                       if (kretprobed(field->parent_ip))
-                               ret = trace_seq_puts(s, KRETPROBE_MSG);
-                       else
-                               ret = seq_print_ip_sym(s,
-                                                      field->parent_ip,
-                                                      sym_flags);
+                       ret = seq_print_ip_sym(s,
+                                              field->parent_ip,
+                                              sym_flags);
                        if (!ret)
                                return TRACE_TYPE_PARTIAL_LINE;
                }
index 421aee99b84a4da8120de8eaf1d9518fa57199c9..d143ab67be444119b6240c5f8461a72fe2fc9647 100644 (file)
@@ -354,11 +354,26 @@ static int vma_has_reserves(struct vm_area_struct *vma)
        return 0;
 }
 
+static void clear_gigantic_page(struct page *page,
+                       unsigned long addr, unsigned long sz)
+{
+       int i;
+       struct page *p = page;
+
+       might_sleep();
+       for (i = 0; i < sz/PAGE_SIZE; i++, p = mem_map_next(p, page, i)) {
+               cond_resched();
+               clear_user_highpage(p, addr + i * PAGE_SIZE);
+       }
+}
 static void clear_huge_page(struct page *page,
                        unsigned long addr, unsigned long sz)
 {
        int i;
 
+       if (unlikely(sz > MAX_ORDER_NR_PAGES))
+               return clear_gigantic_page(page, addr, sz);
+
        might_sleep();
        for (i = 0; i < sz/PAGE_SIZE; i++) {
                cond_resched();
@@ -366,12 +381,32 @@ static void clear_huge_page(struct page *page,
        }
 }
 
+static void copy_gigantic_page(struct page *dst, struct page *src,
+                          unsigned long addr, struct vm_area_struct *vma)
+{
+       int i;
+       struct hstate *h = hstate_vma(vma);
+       struct page *dst_base = dst;
+       struct page *src_base = src;
+       might_sleep();
+       for (i = 0; i < pages_per_huge_page(h); ) {
+               cond_resched();
+               copy_user_highpage(dst, src, addr + i*PAGE_SIZE, vma);
+
+               i++;
+               dst = mem_map_next(dst, dst_base, i);
+               src = mem_map_next(src, src_base, i);
+       }
+}
 static void copy_huge_page(struct page *dst, struct page *src,
                           unsigned long addr, struct vm_area_struct *vma)
 {
        int i;
        struct hstate *h = hstate_vma(vma);
 
+       if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES))
+               return copy_gigantic_page(dst, src, addr, vma);
+
        might_sleep();
        for (i = 0; i < pages_per_huge_page(h); i++) {
                cond_resched();
@@ -456,6 +491,8 @@ static void update_and_free_page(struct hstate *h, struct page *page)
 {
        int i;
 
+       VM_BUG_ON(h->order >= MAX_ORDER);
+
        h->nr_huge_pages--;
        h->nr_huge_pages_node[page_to_nid(page)]--;
        for (i = 0; i < pages_per_huge_page(h); i++) {
@@ -970,6 +1007,14 @@ found:
        return 1;
 }
 
+static void prep_compound_huge_page(struct page *page, int order)
+{
+       if (unlikely(order > (MAX_ORDER - 1)))
+               prep_compound_gigantic_page(page, order);
+       else
+               prep_compound_page(page, order);
+}
+
 /* Put bootmem huge pages into the standard lists after mem_map is up */
 static void __init gather_bootmem_prealloc(void)
 {
@@ -980,7 +1025,7 @@ static void __init gather_bootmem_prealloc(void)
                struct hstate *h = m->hstate;
                __ClearPageReserved(page);
                WARN_ON(page_count(page) != 1);
-               prep_compound_page(page, h->order);
+               prep_compound_huge_page(page, h->order);
                prep_new_huge_page(h, page, page_to_nid(page));
        }
 }
@@ -2130,7 +2175,7 @@ same_page:
                        if (zeropage_ok)
                                pages[i] = ZERO_PAGE(0);
                        else
-                               pages[i] = page + pfn_offset;
+                               pages[i] = mem_map_offset(page, pfn_offset);
                        get_page(pages[i]);
                }
 
index e4e728bdf324fc62a24ba0c951869989ab081ea1..13333bc2eb68ccb86749beb89df89d82a28b5e80 100644 (file)
@@ -17,6 +17,7 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
                unsigned long floor, unsigned long ceiling);
 
 extern void prep_compound_page(struct page *page, unsigned long order);
+extern void prep_compound_gigantic_page(struct page *page, unsigned long order);
 
 static inline void set_page_count(struct page *page, int v)
 {
@@ -175,6 +176,34 @@ static inline void free_page_mlock(struct page *page) { }
 
 #endif /* CONFIG_UNEVICTABLE_LRU */
 
+/*
+ * Return the mem_map entry representing the 'offset' subpage within
+ * the maximally aligned gigantic page 'base'.  Handle any discontiguity
+ * in the mem_map at MAX_ORDER_NR_PAGES boundaries.
+ */
+static inline struct page *mem_map_offset(struct page *base, int offset)
+{
+       if (unlikely(offset >= MAX_ORDER_NR_PAGES))
+               return pfn_to_page(page_to_pfn(base) + offset);
+       return base + offset;
+}
+
+/*
+ * Iterator over all subpages withing the maximally aligned gigantic
+ * page 'base'.  Handle any discontiguity in the mem_map.
+ */
+static inline struct page *mem_map_next(struct page *iter,
+                                               struct page *base, int offset)
+{
+       if (unlikely((offset & (MAX_ORDER_NR_PAGES - 1)) == 0)) {
+               unsigned long pfn = page_to_pfn(base) + offset;
+               if (!pfn_valid(pfn))
+                       return NULL;
+               return pfn_to_page(pfn);
+       }
+       return iter + 1;
+}
+
 /*
  * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node,
  * so all functions starting at paging_init should be marked __init
index 36f42573a3352fa6ba452eea2d76ed2021c8605c..e9493b1c1117a4090fa8998b9ea2e29c1239ebbc 100644 (file)
@@ -489,12 +489,6 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
        int err;
        struct vm_area_struct *first, *vma, *prev;
 
-       if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
-
-               err = migrate_prep();
-               if (err)
-                       return ERR_PTR(err);
-       }
 
        first = find_vma(mm, start);
        if (!first)
@@ -809,9 +803,13 @@ int do_migrate_pages(struct mm_struct *mm,
        const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags)
 {
        int busy = 0;
-       int err = 0;
+       int err;
        nodemask_t tmp;
 
+       err = migrate_prep();
+       if (err)
+               return err;
+
        down_read(&mm->mmap_sem);
 
        err = migrate_vmas(mm, from_nodes, to_nodes, flags);
@@ -974,6 +972,12 @@ static long do_mbind(unsigned long start, unsigned long len,
                 start, start + len, mode, mode_flags,
                 nmask ? nodes_addr(*nmask)[0] : -1);
 
+       if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) {
+
+               err = migrate_prep();
+               if (err)
+                       return err;
+       }
        down_write(&mm->mmap_sem);
        vma = check_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
index 6602941bfab0b03607f9bce6dd8e3f9ce1046bfe..385db89f0c33e48a421b8adf63e63b60b0e4881e 100644 (file)
@@ -841,12 +841,12 @@ static int do_move_page_to_node_array(struct mm_struct *mm,
        struct page_to_node *pp;
        LIST_HEAD(pagelist);
 
+       migrate_prep();
        down_read(&mm->mmap_sem);
 
        /*
         * Build a list of pages to migrate
         */
-       migrate_prep();
        for (pp = pm; pp->node != MAX_NUMNODES; pp++) {
                struct vm_area_struct *vma;
                struct page *page;
index 64e5b4bcd964cd912b5a5f6b22dc392621269d84..a0a01902f551dd45b19385b64435ec6708db249d 100644 (file)
@@ -38,7 +38,6 @@ static DEFINE_SPINLOCK(zone_scan_mutex);
  * badness - calculate a numeric value for how bad this task has been
  * @p: task struct of which task we should calculate
  * @uptime: current uptime in seconds
- * @mem: target memory controller
  *
  * The formula used is relatively simple and documented inline in the
  * function. The main rationale is that we want to select a good task
@@ -295,6 +294,8 @@ static void dump_tasks(const struct mem_cgroup *mem)
                        continue;
                if (mem && !task_in_mem_cgroup(p, mem))
                        continue;
+               if (!thread_group_leader(p))
+                       continue;
 
                task_lock(p);
                printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d     %3d %s\n",
index d0a240fbb8bfc34f5304ee896af7964442230d4d..54069e64e3a8a4b0c9a0450aba08b7f0fa21c5f9 100644 (file)
@@ -260,6 +260,23 @@ static void free_compound_page(struct page *page)
 }
 
 void prep_compound_page(struct page *page, unsigned long order)
+{
+       int i;
+       int nr_pages = 1 << order;
+
+       set_compound_page_dtor(page, free_compound_page);
+       set_compound_order(page, order);
+       __SetPageHead(page);
+       for (i = 1; i < nr_pages; i++) {
+               struct page *p = page + i;
+
+               __SetPageTail(p);
+               p->first_page = page;
+       }
+}
+
+#ifdef CONFIG_HUGETLBFS
+void prep_compound_gigantic_page(struct page *page, unsigned long order)
 {
        int i;
        int nr_pages = 1 << order;
@@ -268,19 +285,17 @@ void prep_compound_page(struct page *page, unsigned long order)
        set_compound_page_dtor(page, free_compound_page);
        set_compound_order(page, order);
        __SetPageHead(page);
-       for (i = 1; i < nr_pages; i++, p++) {
-               if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0))
-                       p = pfn_to_page(page_to_pfn(page) + i);
+       for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
                __SetPageTail(p);
                p->first_page = page;
        }
 }
+#endif
 
 static void destroy_compound_page(struct page *page, unsigned long order)
 {
        int i;
        int nr_pages = 1 << order;
-       struct page *p = page + 1;
 
        if (unlikely(compound_order(page) != order))
                bad_page(page);
@@ -288,9 +303,8 @@ static void destroy_compound_page(struct page *page, unsigned long order)
        if (unlikely(!PageHead(page)))
                        bad_page(page);
        __ClearPageHead(page);
-       for (i = 1; i < nr_pages; i++, p++) {
-               if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0))
-                       p = pfn_to_page(page_to_pfn(page) + i);
+       for (i = 1; i < nr_pages; i++) {
+               struct page *p = page + i;
 
                if (unlikely(!PageTail(p) |
                                (p->first_page != page)))
index b70a7fec1ff6c3a4aa2c210215185b31085c8f4d..5e0ffd967452083c8209dfa0a1334416ded99f68 100644 (file)
@@ -130,10 +130,11 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
                if (page && get_pageblock_migratetype(page) != MIGRATE_ISOLATE)
                        break;
        }
-       if (pfn < end_pfn)
+       page = __first_valid_page(start_pfn, end_pfn - start_pfn);
+       if ((pfn < end_pfn) || !page)
                return -EBUSY;
        /* Check all pages are free or Marked as ISOLATED */
-       zone = page_zone(pfn_to_page(pfn));
+       zone = page_zone(page);
        spin_lock_irqsave(&zone->lock, flags);
        ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn);
        spin_unlock_irqrestore(&zone->lock, flags);
index a91b5f8fcaf61e6dc50bfe0526e5b488c3c967c7..a13ea6401ae7428d967d15a3c5a0cf5472ee2240 100644 (file)
@@ -64,7 +64,7 @@ void __meminit vmemmap_verify(pte_t *pte, int node,
        unsigned long pfn = pte_pfn(*pte);
        int actual_node = early_pfn_to_nid(pfn);
 
-       if (actual_node != node)
+       if (node_distance(actual_node, node) > LOCAL_DISTANCE)
                printk(KERN_WARNING "[%lx-%lx] potential offnode "
                        "page_structs\n", start, end - 1);
 }
index f1cc03bbf6ac93e7dc4db183041f57a6f3364140..ba6b0f5f7fac6dcce7a9e8a7c71f00e0e691d193 100644 (file)
@@ -178,7 +178,7 @@ static int vmap_page_range(unsigned long addr, unsigned long end,
 static inline int is_vmalloc_or_module_addr(const void *x)
 {
        /*
-        * x86-64 and sparc64 put modules in a special place,
+        * ARM, x86-64 and sparc64 put modules in a special place,
         * and fall back on vmalloc() if that fails. Others
         * just put it in the vmalloc space.
         */
@@ -592,6 +592,8 @@ static void free_unmap_vmap_area_addr(unsigned long addr)
 
 #define VMAP_BLOCK_SIZE                (VMAP_BBMAP_BITS * PAGE_SIZE)
 
+static bool vmap_initialized __read_mostly = false;
+
 struct vmap_block_queue {
        spinlock_t lock;
        struct list_head free;
@@ -828,6 +830,9 @@ void vm_unmap_aliases(void)
        int cpu;
        int flush = 0;
 
+       if (unlikely(!vmap_initialized))
+               return;
+
        for_each_possible_cpu(cpu) {
                struct vmap_block_queue *vbq = &per_cpu(vmap_block_queue, cpu);
                struct vmap_block *vb;
@@ -942,6 +947,8 @@ void __init vmalloc_init(void)
                INIT_LIST_HEAD(&vbq->dirty);
                vbq->nr_dirty = 0;
        }
+
+       vmap_initialized = true;
 }
 
 void unmap_kernel_range(unsigned long addr, unsigned long size)
index 916061f681b6484a95af7900311977fca7752ebc..68ced4bf158c7558977e3c4a44ef4567157e80d5 100644 (file)
@@ -3,11 +3,20 @@
 #include <linux/if_vlan.h>
 #include "vlan.h"
 
+struct vlan_hwaccel_cb {
+       struct net_device       *dev;
+};
+
+static inline struct vlan_hwaccel_cb *vlan_hwaccel_cb(struct sk_buff *skb)
+{
+       return (struct vlan_hwaccel_cb *)skb->cb;
+}
+
 /* VLAN rx hw acceleration helper.  This acts like netif_{rx,receive_skb}(). */
 int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                      u16 vlan_tci, int polling)
 {
-       struct net_device_stats *stats;
+       struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb);
 
        if (skb_bond_should_drop(skb)) {
                dev_kfree_skb_any(skb);
@@ -15,23 +24,35 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
        }
 
        skb->vlan_tci = vlan_tci;
+       cb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK);
+
+       return (polling ? netif_receive_skb(skb) : netif_rx(skb));
+}
+EXPORT_SYMBOL(__vlan_hwaccel_rx);
+
+int vlan_hwaccel_do_receive(struct sk_buff *skb)
+{
+       struct vlan_hwaccel_cb *cb = vlan_hwaccel_cb(skb);
+       struct net_device *dev = cb->dev;
+       struct net_device_stats *stats;
+
        netif_nit_deliver(skb);
 
-       skb->dev = vlan_group_get_device(grp, vlan_tci & VLAN_VID_MASK);
-       if (skb->dev == NULL) {
-               dev_kfree_skb_any(skb);
-               /* Not NET_RX_DROP, this is not being dropped
-                * due to congestion. */
-               return NET_RX_SUCCESS;
+       if (dev == NULL) {
+               kfree_skb(skb);
+               return -1;
        }
-       skb->dev->last_rx = jiffies;
+
+       skb->dev = dev;
+       skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
        skb->vlan_tci = 0;
 
-       stats = &skb->dev->stats;
+       dev->last_rx = jiffies;
+
+       stats = &dev->stats;
        stats->rx_packets++;
        stats->rx_bytes += skb->len;
 
-       skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci);
        switch (skb->pkt_type) {
        case PACKET_BROADCAST:
                break;
@@ -43,13 +64,12 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,
                 * This allows the VLAN to have a different MAC than the
                 * underlying device, and still route correctly. */
                if (!compare_ether_addr(eth_hdr(skb)->h_dest,
-                                       skb->dev->dev_addr))
+                                       dev->dev_addr))
                        skb->pkt_type = PACKET_HOST;
                break;
        };
-       return (polling ? netif_receive_skb(skb) : netif_rx(skb));
+       return 0;
 }
-EXPORT_SYMBOL(__vlan_hwaccel_rx);
 
 struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
index 67717f69412e47c182f34715291ec83c979d6f73..4b529454616d0427020e5b8b30620249e400c268 100644 (file)
@@ -189,6 +189,9 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
                        printk(KERN_ERR "Couldn't grow tag array\n");
                        kfree(req->tc);
                        kfree(req->rc);
+                       kfree(req->wq);
+                       req->tc = req->rc = NULL;
+                       req->wq = NULL;
                        return ERR_PTR(-ENOMEM);
                }
                req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
@@ -311,12 +314,6 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r)
        r->status = REQ_STATUS_IDLE;
        if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool))
                p9_idpool_put(tag, c->tagpool);
-
-       /* if this was a flush request we have to free response fcall */
-       if (r->rc->id == P9_RFLUSH) {
-               kfree(r->tc);
-               kfree(r->rc);
-       }
 }
 
 /**
@@ -611,19 +608,21 @@ reterr:
 
 static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 {
-       int err;
+       int ret;
        struct p9_fid *fid;
+       unsigned long flags;
 
        P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt);
        fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
        if (!fid)
                return ERR_PTR(-ENOMEM);
 
-       fid->fid = p9_idpool_get(clnt->fidpool);
+       ret = p9_idpool_get(clnt->fidpool);
        if (fid->fid < 0) {
-               err = -ENOSPC;
+               ret = -ENOSPC;
                goto error;
        }
+       fid->fid = ret;
 
        memset(&fid->qid, 0, sizeof(struct p9_qid));
        fid->mode = -1;
@@ -632,27 +631,28 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
        fid->clnt = clnt;
        fid->aux = NULL;
 
-       spin_lock(&clnt->lock);
+       spin_lock_irqsave(&clnt->lock, flags);
        list_add(&fid->flist, &clnt->fidlist);
-       spin_unlock(&clnt->lock);
+       spin_unlock_irqrestore(&clnt->lock, flags);
 
        return fid;
 
 error:
        kfree(fid);
-       return ERR_PTR(err);
+       return ERR_PTR(ret);
 }
 
 static void p9_fid_destroy(struct p9_fid *fid)
 {
        struct p9_client *clnt;
+       unsigned long flags;
 
        P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid);
        clnt = fid->clnt;
        p9_idpool_put(fid->fid, clnt->fidpool);
-       spin_lock(&clnt->lock);
+       spin_lock_irqsave(&clnt->lock, flags);
        list_del(&fid->flist);
-       spin_unlock(&clnt->lock);
+       spin_unlock_irqrestore(&clnt->lock, flags);
        kfree(fid);
 }
 
@@ -818,7 +818,9 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
        }
 
        P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
-                                       qid.type, qid.path, qid.version);
+                                       qid.type,
+                                       (unsigned long long)qid.path,
+                                       qid.version);
 
        memmove(&fid->qid, &qid, sizeof(struct p9_qid));
 
@@ -865,7 +867,9 @@ p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname)
        }
 
        P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n",
-                                       qid.type, qid.path, qid.version);
+                                       qid.type,
+                                       (unsigned long long)qid.path,
+                                       qid.version);
 
        memmove(&afid->qid, &qid, sizeof(struct p9_qid));
        p9_free_req(clnt, req);
@@ -930,7 +934,8 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
 
        for (count = 0; count < nwqids; count++)
                P9_DPRINTK(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
-                       count, wqids[count].type, wqids[count].path,
+                       count, wqids[count].type,
+                       (unsigned long long)wqids[count].path,
                        wqids[count].version);
 
        if (nwname)
@@ -980,7 +985,9 @@ int p9_client_open(struct p9_fid *fid, int mode)
        }
 
        P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n",
-                               qid.type, qid.path, qid.version, iounit);
+                               qid.type,
+                               (unsigned long long)qid.path,
+                               qid.version, iounit);
 
        fid->mode = mode;
        fid->iounit = iounit;
@@ -1023,7 +1030,9 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
        }
 
        P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
-                               qid.type, qid.path, qid.version, iounit);
+                               qid.type,
+                               (unsigned long long)qid.path,
+                               qid.version, iounit);
 
        fid->mode = mode;
        fid->iounit = iounit;
@@ -1230,9 +1239,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
                "<<<    name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
                "<<<    uid=%d gid=%d n_muid=%d\n",
                ret->size, ret->type, ret->dev, ret->qid.type,
-               ret->qid.path, ret->qid.version, ret->mode,
-               ret->atime, ret->mtime, ret->length, ret->name,
-               ret->uid, ret->gid, ret->muid, ret->extension,
+               (unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
+               ret->atime, ret->mtime, (unsigned long long)ret->length,
+               ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
                ret->n_uid, ret->n_gid, ret->n_muid);
 
 free_and_error:
@@ -1255,9 +1264,9 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
                "     name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
                "     uid=%d gid=%d n_muid=%d\n",
                wst->size, wst->type, wst->dev, wst->qid.type,
-               wst->qid.path, wst->qid.version, wst->mode,
-               wst->atime, wst->mtime, wst->length, wst->name,
-               wst->uid, wst->gid, wst->muid, wst->extension,
+               (unsigned long long)wst->qid.path, wst->qid.version, wst->mode,
+               wst->atime, wst->mtime, (unsigned long long)wst->length,
+               wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
                wst->n_uid, wst->n_gid, wst->n_muid);
        err = 0;
        clnt = fid->clnt;
index 8d6cc4777aae143145de4c65c658e45004bc8460..2f1fe5fc1228273cce9b23b9a8a2cd31e184ec31 100644 (file)
@@ -45,7 +45,6 @@
 #include <net/9p/transport.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/rdma_cm.h>
-#include <rdma/ib_verbs.h>
 
 #define P9_PORT                        5640
 #define P9_RDMA_SQ_DEPTH       32
@@ -589,6 +588,9 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
        if (IS_ERR(rdma->cm_id))
                goto error;
 
+       /* Associate the client with the transport */
+       client->trans = rdma;
+
        /* Resolve the server's address */
        rdma->addr.sin_family = AF_INET;
        rdma->addr.sin_addr.s_addr = in_aton(addr);
@@ -669,7 +671,6 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args)
        if (err || (rdma->state != P9_RDMA_CONNECTED))
                goto error;
 
-       client->trans = rdma;
        client->status = Connected;
 
        return 0;
index d9038e328cc153b2257330934bacd78b12e0f3f1..9174c77d3112c65237cbbd2e063eb55b03b5c39e 100644 (file)
@@ -2218,6 +2218,9 @@ int netif_receive_skb(struct sk_buff *skb)
        int ret = NET_RX_DROP;
        __be16 type;
 
+       if (skb->vlan_tci && vlan_hwaccel_do_receive(skb))
+               return NET_RX_SUCCESS;
+
        /* if we've gotten here through NAPI, check netpoll */
        if (netpoll_receive_skb(skb))
                return NET_RX_DROP;
index 10f5c65f6a470cc914de500b43d63990e89db1b6..ab242cc1accaae7673b76784aa5838a76d9b10c4 100644 (file)
@@ -75,6 +75,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
                if (!fpl)
                        return -ENOMEM;
                *fplp = fpl;
+               INIT_LIST_HEAD(&fpl->list);
                fpl->count = 0;
        }
        fpp = &fpl->fp[fpl->count];
@@ -106,9 +107,25 @@ void __scm_destroy(struct scm_cookie *scm)
 
        if (fpl) {
                scm->fp = NULL;
-               for (i=fpl->count-1; i>=0; i--)
-                       fput(fpl->fp[i]);
-               kfree(fpl);
+               if (current->scm_work_list) {
+                       list_add_tail(&fpl->list, current->scm_work_list);
+               } else {
+                       LIST_HEAD(work_list);
+
+                       current->scm_work_list = &work_list;
+
+                       list_add(&fpl->list, &work_list);
+                       while (!list_empty(&work_list)) {
+                               fpl = list_first_entry(&work_list, struct scm_fp_list, list);
+
+                               list_del(&fpl->list);
+                               for (i=fpl->count-1; i>=0; i--)
+                                       fput(fpl->fp[i]);
+                               kfree(fpl);
+                       }
+
+                       current->scm_work_list = NULL;
+               }
        }
 }
 
@@ -284,6 +301,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
 
        new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
        if (new_fpl) {
+               INIT_LIST_HEAD(&new_fpl->list);
                for (i=fpl->count-1; i>=0; i--)
                        get_file(fpl->fp[i]);
                memcpy(new_fpl, fpl, sizeof(*fpl));
index eccb7165a80c180f56c42a1261597b361966396d..c5aca0bb116ae36ead0a824236ab4a5df9162d74 100644 (file)
@@ -1374,8 +1374,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                            sk->sk_state == TCP_CLOSE ||
                            (sk->sk_shutdown & RCV_SHUTDOWN) ||
                            !timeo ||
-                           signal_pending(current) ||
-                           (flags & MSG_PEEK))
+                           signal_pending(current))
                                break;
                } else {
                        if (sock_flag(sk, SOCK_DONE))
index 07735ed280d720f32ac7269c5099c1e840d866d7..55dc6beab9aa5344629021d04c526870fddd1fe4 100644 (file)
@@ -33,6 +33,7 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
        x->sel.dport_mask = htons(0xffff);
        x->sel.sport = xfrm_flowi_sport(fl);
        x->sel.sport_mask = htons(0xffff);
+       x->sel.family = AF_INET;
        x->sel.prefixlen_d = 32;
        x->sel.prefixlen_s = 32;
        x->sel.proto = fl->proto;
index eea9542728ca79b76b3c20427f74f9a5cad95079..d9da5eb9dcb20c81f9b04619b6b2f9c73c7f0ca7 100644 (file)
@@ -2483,8 +2483,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                        if (!idev && dev->mtu >= IPV6_MIN_MTU)
                                idev = ipv6_add_dev(dev);
 
-                       if (idev)
+                       if (idev) {
                                idev->if_flags |= IF_READY;
+                               run_pending = 1;
+                       }
                } else {
                        if (!addrconf_qdisc_ok(dev)) {
                                /* device is still not ready. */
index 71e259e866a16c93cad70fb65a9bab6313da4b93..8b48512ebf6ac98ce279a7ca69daa6639970f1e3 100644 (file)
@@ -138,6 +138,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        int peeked;
        int err;
        int is_udplite = IS_UDPLITE(sk);
+       int is_udp4;
 
        if (addr_len)
                *addr_len=sizeof(struct sockaddr_in6);
@@ -158,6 +159,8 @@ try_again:
        else if (copied < ulen)
                msg->msg_flags |= MSG_TRUNC;
 
+       is_udp4 = (skb->protocol == htons(ETH_P_IP));
+
        /*
         * If checksum is needed at all, try to do it while copying the
         * data.  If the data is truncated, or if we only want a partial
@@ -180,9 +183,14 @@ try_again:
        if (err)
                goto out_free;
 
-       if (!peeked)
-               UDP6_INC_STATS_USER(sock_net(sk),
-                               UDP_MIB_INDATAGRAMS, is_udplite);
+       if (!peeked) {
+               if (is_udp4)
+                       UDP_INC_STATS_USER(sock_net(sk),
+                                       UDP_MIB_INDATAGRAMS, is_udplite);
+               else
+                       UDP6_INC_STATS_USER(sock_net(sk),
+                                       UDP_MIB_INDATAGRAMS, is_udplite);
+       }
 
        sock_recv_timestamp(msg, sk, skb);
 
@@ -196,7 +204,7 @@ try_again:
                sin6->sin6_flowinfo = 0;
                sin6->sin6_scope_id = 0;
 
-               if (skb->protocol == htons(ETH_P_IP))
+               if (is_udp4)
                        ipv6_addr_set(&sin6->sin6_addr, 0, 0,
                                      htonl(0xffff), ip_hdr(skb)->saddr);
                else {
@@ -207,7 +215,7 @@ try_again:
                }
 
        }
-       if (skb->protocol == htons(ETH_P_IP)) {
+       if (is_udp4) {
                if (inet->cmsg_flags)
                        ip_cmsg_recv(msg, skb);
        } else {
@@ -228,8 +236,14 @@ out:
 
 csum_copy_err:
        lock_sock(sk);
-       if (!skb_kill_datagram(sk, skb, flags))
-               UDP6_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
+       if (!skb_kill_datagram(sk, skb, flags)) {
+               if (is_udp4)
+                       UDP_INC_STATS_USER(sock_net(sk),
+                                       UDP_MIB_INERRORS, is_udplite);
+               else
+                       UDP6_INC_STATS_USER(sock_net(sk),
+                                       UDP_MIB_INERRORS, is_udplite);
+       }
        release_sock(sk);
 
        if (flags & MSG_DONTWAIT)
index 89884a4f23aa27992e006846bf14dd5673fea675..60c78cfc273797247312c6846727fc7b10b9db21 100644 (file)
@@ -34,6 +34,7 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
        x->sel.dport_mask = htons(0xffff);
        x->sel.sport = xfrm_flowi_sport(fl);
        x->sel.sport_mask = htons(0xffff);
+       x->sel.family = AF_INET6;
        x->sel.prefixlen_d = 128;
        x->sel.prefixlen_s = 128;
        x->sel.proto = fl->proto;
index 9c06b9f86ad45a524c2b3e2fe1b522930ca70af0..c39b6a9941331c8fe6c6fe2a80130f04bd1b1129 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/rculist.h>
+#include <linux/rtnetlink.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
@@ -167,10 +168,12 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
         */
        synchronize_rcu();
 
+       rtnl_lock();
        spin_lock_bh(&nf_conntrack_lock);
        for_each_net(net)
                __nf_conntrack_helper_unregister(me, net);
        spin_unlock_bh(&nf_conntrack_lock);
+       rtnl_unlock();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
 
index a59a307e685d2b67393344168fb1253cb9aa9d61..592d73344d46b09e02162ee5653e436f890d4c28 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/notifier.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_l3proto.h>
@@ -221,8 +222,10 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
        synchronize_rcu();
 
        /* Remove all contrack entries for this protocol */
+       rtnl_lock();
        for_each_net(net)
                nf_ct_iterate_cleanup(net, kill_l3proto, proto);
+       rtnl_unlock();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister);
 
@@ -333,8 +336,10 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
        synchronize_rcu();
 
        /* Remove all contrack entries for this protocol */
+       rtnl_lock();
        for_each_net(net)
                nf_ct_iterate_cleanup(net, kill_l4proto, l4proto);
+       rtnl_unlock();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister);
 
index f949a482b0078b904d88b655da399d8706a48ca8..25ba3bd57e66405e64adef4455b66614fd273ea6 100644 (file)
@@ -603,7 +603,7 @@ static int rfkill_check_duplicity(const struct rfkill *rfkill)
        }
 
        /* 0: first switch of its kind */
-       return test_bit(rfkill->type, seen);
+       return (test_bit(rfkill->type, seen)) ? 1 : 0;
 }
 
 static int rfkill_add_switch(struct rfkill *rfkill)
index 25872747762ca76b7ccd889d72549db0f6a694a3..058f04f54b9024857eb418321d6842bd448c744a 100644 (file)
@@ -315,9 +315,9 @@ static void xfrm_policy_kill(struct xfrm_policy *policy)
                return;
        }
 
-       spin_lock(&xfrm_policy_gc_lock);
+       spin_lock_bh(&xfrm_policy_gc_lock);
        hlist_add_head(&policy->bydst, &xfrm_policy_gc_list);
-       spin_unlock(&xfrm_policy_gc_lock);
+       spin_unlock_bh(&xfrm_policy_gc_lock);
 
        schedule_work(&xfrm_policy_gc_work);
 }
index 4a8a1abb59ee8ae7c611d85def77d363ca96380e..a278a6f3b9913eedb9d80f8e46e930520704ae3f 100644 (file)
@@ -1816,7 +1816,7 @@ static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb)
        uk.family = k->family;
        uk.reserved = k->reserved;
        memcpy(&uk.local, &k->local, sizeof(uk.local));
-       memcpy(&uk.remote, &k->local, sizeof(uk.remote));
+       memcpy(&uk.remote, &k->remote, sizeof(uk.remote));
 
        return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk);
 }
index f84f3e505788f36d0ecaee4eb33b13cf60263383..fa8ab2815a982676d1f3a0ef3c47ebcec8f3ee39 100644 (file)
@@ -176,7 +176,7 @@ int soundbus_add_one(struct soundbus_dev *dev)
                return -EINVAL;
        }
 
-       snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount);
+       dev_set_name(&dev->ofdev.dev, "soundbus:%x", ++devcount);
        dev->ofdev.dev.bus = &soundbus_bus_type;
        return of_device_register(&dev->ofdev);
 }
index c4995c9f57303e0590ce5706676c2dc5918bf000..39672f68ce5d2a2c86b4b944377ea115a9c37032 100644 (file)
@@ -148,6 +148,8 @@ static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream)
 
 static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up)
 {
+       if (!substream->opened)
+               return;
        if (up) {
                tasklet_hi_schedule(&substream->runtime->tasklet);
        } else {
@@ -158,6 +160,8 @@ static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *subs
 
 static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
 {
+       if (!substream->opened)
+               return;
        substream->ops->trigger(substream, up);
        if (!up && substream->runtime->event)
                tasklet_kill(&substream->runtime->tasklet);
@@ -857,6 +861,8 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,
        int result = 0, count1;
        struct snd_rawmidi_runtime *runtime = substream->runtime;
 
+       if (!substream->opened)
+               return -EBADFD;
        if (runtime->buffer == NULL) {
                snd_printd("snd_rawmidi_receive: input is not active!!!\n");
                return -EINVAL;
@@ -1126,6 +1132,8 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
 int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
                         unsigned char *buffer, int count)
 {
+       if (!substream->opened)
+               return -EBADFD;
        count = snd_rawmidi_transmit_peek(substream, buffer, count);
        if (count < 0)
                return count;
index ecdbeb6d36033af8a9be9ee69dc0c9896f78cf82..7783843ca9ae95ce9dd2acee69eb970acd914348 100644 (file)
@@ -1153,7 +1153,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
        /* get irq */
        irq = platform_get_irq(pfdev, 0);
        if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
-                       pfdev->dev.bus_id, (void *)ml403_ac97cr)) {
+                       dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
                snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
                           "unable to grab IRQ %d\n",
                           irq);
@@ -1166,7 +1166,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
                   ml403_ac97cr->irq);
        irq = platform_get_irq(pfdev, 1);
        if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
-                       pfdev->dev.bus_id, (void *)ml403_ac97cr)) {
+                       dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
                snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
                           "unable to grab IRQ %d\n",
                           irq);
index cd9b83e7f7d136c1e8dc078b3aa8fa222fabb940..0444cdeb4becd93a35f8fe20ad6699e2c0a8e9f7 100644 (file)
@@ -24,13 +24,13 @@ static void pcspkr_do_sound(unsigned int count)
        spin_lock_irqsave(&i8253_lock, flags);
 
        if (count) {
-               /* enable counter 2 */
-               outb_p(inb_p(0x61) | 3, 0x61);
                /* set command for counter 2, 2 byte write */
                outb_p(0xB6, 0x43);
                /* select desired HZ */
                outb_p(count & 0xff, 0x42);
                outb((count >> 8) & 0xff, 0x42);
+               /* enable counter 2 */
+               outb_p(inb_p(0x61) | 3, 0x61);
        } else {
                /* disable counter 2 */
                outb(inb_p(0x61) & 0xFC, 0x61);
index b68d20edc20f2f1aa3ffb5d0a106b2591c2f77fd..223a6c038819217a2d5bfb74e81bfd6a56ba1d86 100644 (file)
@@ -70,15 +70,15 @@ static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
                return 0;
 
        if (port[n] == SNDRV_AUTO_PORT) {
-               snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
+               dev_err(dev, "please specify port\n");
                return 0;
        }
        if (irq[n] == SNDRV_AUTO_IRQ) {
-               snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id);
+               dev_err(dev, "please specify irq\n");
                return 0;       
        }
        if (dma1[n] == SNDRV_AUTO_DMA) {
-               snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id);
+               dev_err(dev, "please specify dma1\n");
                return 0;
        }
        return 1;
index efa8c80d05b69eecc9b03795e609b60b497bd77a..374b7177e111d2f806930d84cdb147c1ace28356 100644 (file)
@@ -36,7 +36,7 @@ static int __devinit snd_adlib_match(struct device *dev, unsigned int n)
                return 0;
 
        if (port[n] == SNDRV_AUTO_PORT) {
-               snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
+               dev_err(dev, "please specify port\n");
                return 0;
        }
        return 1;
@@ -55,13 +55,13 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
 
        card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
        if (!card) {
-               snd_printk(KERN_ERR "%s: could not create card\n", dev->bus_id);
+               dev_err(dev, "could not create card\n");
                return -EINVAL;
        }
 
        card->private_data = request_region(port[n], 4, CRD_NAME);
        if (!card->private_data) {
-               snd_printk(KERN_ERR "%s: could not grab ports\n", dev->bus_id);
+               dev_err(dev, "could not grab ports\n");
                error = -EBUSY;
                goto out;
        }
@@ -73,13 +73,13 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
 
        error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3);
        if (error < 0) {
-               snd_printk(KERN_ERR "%s: could not create OPL\n", dev->bus_id);
+               dev_err(dev, "could not create OPL\n");
                goto out;
        }
 
        error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
        if (error < 0) {
-               snd_printk(KERN_ERR "%s: could not create FM\n", dev->bus_id);
+               dev_err(dev, "could not create FM\n");
                goto out;
        }
 
@@ -87,7 +87,7 @@ static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
 
        error = snd_card_register(card);
        if (error < 0) {
-               snd_printk(KERN_ERR "%s: could not register card\n", dev->bus_id);
+               dev_err(dev, "could not register card\n");
                goto out;
        }
 
index ddd289120aa8e06fc6bc194102f39b1f2e740028..f019d449e2d65cd243c9a5aec5b51c35441c5e99 100644 (file)
@@ -74,15 +74,15 @@ static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
                return 0;
 
        if (port[n] == SNDRV_AUTO_PORT) {
-               snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
+               dev_err(dev, "please specify port\n");
                return 0;
        }
        if (irq[n] == SNDRV_AUTO_IRQ) {
-               snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id);
+               dev_err(dev, "please specify irq\n");
                return 0;
        }
        if (dma1[n] == SNDRV_AUTO_DMA) {
-               snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id);
+               dev_err(dev, "please specify dma1\n");
                return 0;
        }
        return 1;
@@ -133,7 +133,7 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
                                        mpu_port[n], 0, mpu_irq[n],
                                        mpu_irq[n] >= 0 ? IRQF_DISABLED : 0,
                                        NULL) < 0)
-                       printk(KERN_WARNING "%s: MPU401 not detected\n", dev->bus_id);
+                       dev_warn(dev, "MPU401 not detected\n");
        }
 
        snd_card_set_dev(card, dev);
index 91f9c15d3e30b8dfd29ce2bc5d68a33aa30d38d6..019c9401663eb9839787f63f4b32d0d9f1cba20b 100644 (file)
@@ -488,19 +488,19 @@ static int __devinit snd_cs423x_isa_match(struct device *pdev,
                return 0;
 
        if (port[dev] == SNDRV_AUTO_PORT) {
-               snd_printk(KERN_ERR "%s: please specify port\n", pdev->bus_id);
+               dev_err(pdev, "please specify port\n");
                return 0;
        }
        if (cport[dev] == SNDRV_AUTO_PORT) {
-               snd_printk(KERN_ERR "%s: please specify cport\n", pdev->bus_id);
+               dev_err(pdev, "please specify cport\n");
                return 0;
        }
        if (irq[dev] == SNDRV_AUTO_IRQ) {
-               snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id);
+               dev_err(pdev, "please specify irq\n");
                return 0;
        }
        if (dma1[dev] == SNDRV_AUTO_DMA) {
-               snd_printk(KERN_ERR "%s: please specify dma1\n", pdev->bus_id);
+               dev_err(pdev, "please specify dma1\n");
                return 0;
        }
        return 1;
index f88639ea64b214ddd976ef6577eab8100f2741f4..b46377139cf81d4ffc73d1e10572f6996c5ad4c3 100644 (file)
@@ -88,16 +88,14 @@ static int __devinit snd_es1688_legacy_create(struct snd_card *card,
        if (irq[n] == SNDRV_AUTO_IRQ) {
                irq[n] = snd_legacy_find_free_irq(possible_irqs);
                if (irq[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free IRQ\n",
-                               dev->bus_id);
+                       dev_err(dev, "unable to find a free IRQ\n");
                        return -EBUSY;
                }
        }
        if (dma8[n] == SNDRV_AUTO_DMA) {
                dma8[n] = snd_legacy_find_free_dma(possible_dmas);
                if (dma8[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free DMA\n",
-                               dev->bus_id);
+                       dev_err(dev, "unable to find a free DMA\n");
                        return -EBUSY;
                }
        }
@@ -147,8 +145,7 @@ static int __devinit snd_es1688_probe(struct device *dev, unsigned int n)
 
        if (snd_opl3_create(card, chip->port, chip->port + 2,
                        OPL3_HW_OPL3, 0, &opl3) < 0)
-               printk(KERN_WARNING "%s: opl3 not detected at 0x%lx\n",
-                       dev->bus_id, chip->port);
+               dev_warn(dev, "opl3 not detected at 0x%lx\n", chip->port);
        else {
                error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
                if (error < 0)
index 8f914b37bf8998eaa261127b9dc53901e6b2d8b5..426532a4d730cfdcc2fa053db7b7f83d84187581 100644 (file)
@@ -90,24 +90,21 @@ static int __devinit snd_gusclassic_create(struct snd_card *card,
        if (irq[n] == SNDRV_AUTO_IRQ) {
                irq[n] = snd_legacy_find_free_irq(possible_irqs);
                if (irq[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free IRQ\n",
-                               dev->bus_id);
+                       dev_err(dev, "unable to find a free IRQ\n");
                        return -EBUSY;
                }
        }
        if (dma1[n] == SNDRV_AUTO_DMA) {
                dma1[n] = snd_legacy_find_free_dma(possible_dmas);
                if (dma1[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free DMA1\n",
-                               dev->bus_id);
+                       dev_err(dev, "unable to find a free DMA1\n");
                        return -EBUSY;
                }
        }
        if (dma2[n] == SNDRV_AUTO_DMA) {
                dma2[n] = snd_legacy_find_free_dma(possible_dmas);
                if (dma2[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free DMA2\n",
-                               dev->bus_id);
+                       dev_err(dev, "unable to find a free DMA2\n");
                        return -EBUSY;
                }
        }
@@ -174,8 +171,8 @@ static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n)
 
        error = -ENODEV;
        if (gus->max_flag || gus->ess_flag) {
-               snd_printk(KERN_ERR "%s: GUS Classic or ACE soundcard was "
-                       "not detected at 0x%lx\n", dev->bus_id, gus->gf1.port);
+               dev_err(dev, "GUS Classic or ACE soundcard was "
+                       "not detected at 0x%lx\n", gus->gf1.port);
                goto out;
        }
 
index da13185eb0a034852117982d7069b108b0004bd8..7ad4c3b41a848092b2c7d4795d3e70aa1ebb0a4a 100644 (file)
@@ -106,16 +106,14 @@ static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
        if (irq[n] == SNDRV_AUTO_IRQ) {
                irq[n] = snd_legacy_find_free_irq(possible_irqs);
                if (irq[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free IRQ "
-                               "for ES1688\n", dev->bus_id);
+                       dev_err(dev, "unable to find a free IRQ for ES1688\n");
                        return -EBUSY;
                }
        }
        if (dma8[n] == SNDRV_AUTO_DMA) {
                dma8[n] = snd_legacy_find_free_dma(possible_dmas);
                if (dma8[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free DMA "
-                               "for ES1688\n", dev->bus_id);
+                       dev_err(dev, "unable to find a free DMA for ES1688\n");
                        return -EBUSY;
                }
        }
@@ -143,16 +141,14 @@ static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
        if (gf1_irq[n] == SNDRV_AUTO_IRQ) {
                gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs);
                if (gf1_irq[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free IRQ "
-                               "for GF1\n", dev->bus_id);
+                       dev_err(dev, "unable to find a free IRQ for GF1\n");
                        return -EBUSY;
                }
        }
        if (dma1[n] == SNDRV_AUTO_DMA) {
                dma1[n] = snd_legacy_find_free_dma(possible_dmas);
                if (dma1[n] < 0) {
-                       snd_printk(KERN_ERR "%s: unable to find a free DMA "
-                               "for GF1\n", dev->bus_id);
+                       dev_err(dev, "unable to find a free DMA for GF1\n");
                        return -EBUSY;
                }
        }
@@ -278,8 +274,8 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
 
        error = -ENODEV;
        if (!gus->ess_flag) {
-               snd_printk(KERN_ERR "%s: GUS Extreme soundcard was not "
-                       "detected at 0x%lx\n", dev->bus_id, gus->gf1.port);
+               dev_err(dev, "GUS Extreme soundcard was not "
+                       "detected at 0x%lx\n", gus->gf1.port);
                goto out;
        }
        gus->codec_flag = 1;
@@ -310,8 +306,7 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
 
        if (snd_opl3_create(card, es1688->port, es1688->port + 2,
                        OPL3_HW_OPL3, 0, &opl3) < 0)
-               printk(KERN_ERR "%s: opl3 not detected at 0x%lx\n",
-                       dev->bus_id, es1688->port);
+               dev_warn(dev, "opl3 not detected at 0x%lx\n", es1688->port);
        else {
                error = snd_opl3_hwdep_new(opl3, 0, 2, NULL);
                if (error < 0)
index 336a34277907f0ec74b30816187eb3d14c7909d3..667eccc676a40a8898f887ef21288cefa717624f 100644 (file)
@@ -85,11 +85,11 @@ static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
        if (!enable[dev])
                return 0;
        if (irq[dev] == SNDRV_AUTO_IRQ) {
-               snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id);
+               dev_err(pdev, "please specify irq\n");
                return 0;
        }
        if (dma8[dev] == SNDRV_AUTO_DMA) {
-               snd_printk(KERN_ERR "%s: please specify dma8\n", pdev->bus_id);
+               dev_err(pdev, "please specify dma8\n");
                return 0;
        }
        return 1;
index 2f283ea6ad9af4cd9762c0a5bb7fc116e4e79798..de5ee8f097f6d46a17d1961e20e200cade3af5a0 100644 (file)
@@ -1464,6 +1464,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0151_chip = 1,
         .spk71 = 1,
         .spdif_bug = 1,
+        .invert_shared_spdif = 1,      /* digital/analog switch swapped */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
         .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", 
@@ -1473,6 +1474,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0151_chip = 1,
         .spk71 = 1,
         .spdif_bug = 1,
+        .invert_shared_spdif = 1,      /* digital/analog switch swapped */
         .ac97_chip = 1} ,
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
         .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", 
@@ -1482,6 +1484,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0151_chip = 1,
         .spk71 = 1,
         .spdif_bug = 1,
+        .invert_shared_spdif = 1,      /* digital/analog switch swapped */
         .ac97_chip = 1} ,
        /* Audigy 2 */
        /* Tested by James@superbug.co.uk 3rd July 2005 */
index 4eceab9bd10985427d041a48c9401fae9cc271a4..a4666c96a44fbea80d021c0f8b57756fcb9b0b19 100644 (file)
@@ -829,6 +829,7 @@ static void alc_sku_automute(struct hda_codec *codec)
                            spec->jack_present ? 0 : PIN_OUT);
 }
 
+#if 0 /* it's broken in some acses -- temporarily disabled */
 static void alc_mic_automute(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -849,6 +850,9 @@ static void alc_mic_automute(struct hda_codec *codec)
        snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, capsrc_idx_fmic,
                         HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
 }
+#else
+#define alc_mic_automute(codec) /* NOP */
+#endif /* disabled */
 
 /* unsolicited event for HP jack sensing */
 static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -1058,12 +1062,14 @@ do_sku:
                        AC_VERB_SET_UNSOLICITED_ENABLE,
                        AC_USRSP_EN | ALC880_HP_EVENT);
 
+#if 0 /* it's broken in some acses -- temporarily disabled */
        if (spec->autocfg.input_pins[AUTO_PIN_MIC] &&
                spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC])
                snd_hda_codec_write(codec,
                        spec->autocfg.input_pins[AUTO_PIN_MIC], 0,
                        AC_VERB_SET_UNSOLICITED_ENABLE,
                        AC_USRSP_EN | ALC880_MIC_EVENT);
+#endif /* disabled */
 
        spec->unsol_event = alc_sku_unsol_event;
 }
@@ -8408,6 +8414,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
 static struct snd_pci_quirk alc883_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
+       SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
@@ -12238,8 +12245,26 @@ static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec,
        return 0;
 }
 
-#define alc269_auto_create_analog_input_ctls \
-       alc880_auto_create_analog_input_ctls
+static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec,
+                                               const struct auto_pin_cfg *cfg)
+{
+       int err;
+
+       err = alc880_auto_create_analog_input_ctls(spec, cfg);
+       if (err < 0)
+               return err;
+       /* digital-mic input pin is excluded in alc880_auto_create..()
+        * because it's under 0x18
+        */
+       if (cfg->input_pins[AUTO_PIN_MIC] == 0x12 ||
+           cfg->input_pins[AUTO_PIN_FRONT_MIC] == 0x12) {
+               struct hda_input_mux *imux = &spec->private_imux;
+               imux->items[imux->num_items].label = "Int Mic";
+               imux->items[imux->num_items].index = 0x05;
+               imux->num_items++;
+       }
+       return 0;
+}
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 #define alc269_loopbacks       alc880_loopbacks
index df9b0bc7f8785a82b6ca6ee0649b7c26ddc0659a..e6085915d86d16c0791ad9a261a1d0d1ccad7b81 100644 (file)
@@ -69,6 +69,7 @@ enum {
 enum {
        STAC_92HD73XX_REF,
        STAC_DELL_M6,
+       STAC_DELL_EQ,
        STAC_92HD73XX_MODELS
 };
 
@@ -773,9 +774,7 @@ static struct hda_verb dell_eq_core_init[] = {
 };
 
 static struct hda_verb dell_m6_core_init[] = {
-       /* set master volume to max value without distortion
-        * and direct control */
-       { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec},
+       { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
        /* setup audio connections */
        { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
        { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01},
@@ -1600,11 +1599,13 @@ static unsigned int dell_m6_pin_configs[13] = {
 static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
        [STAC_92HD73XX_REF]     = ref92hd73xx_pin_configs,
        [STAC_DELL_M6]  = dell_m6_pin_configs,
+       [STAC_DELL_EQ]  = dell_m6_pin_configs,
 };
 
 static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
        [STAC_92HD73XX_REF] = "ref",
        [STAC_DELL_M6] = "dell-m6",
+       [STAC_DELL_EQ] = "dell-eq",
 };
 
 static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
@@ -4131,12 +4132,17 @@ again:
                        sizeof(stac92hd73xx_dmux));
 
        switch (spec->board_config) {
-       case STAC_DELL_M6:
+       case STAC_DELL_EQ:
                spec->init = dell_eq_core_init;
+               /* fallthru */
+       case STAC_DELL_M6:
                spec->num_smuxes = 0;
                spec->mixer = &stac92hd73xx_6ch_mixer[DELL_M6_MIXER];
                spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP];
                spec->num_amps = 1;
+
+               if (!spec->init)
+                       spec->init = dell_m6_core_init;
                switch (codec->subsystem_id) {
                case 0x1028025e: /* Analog Mics */
                case 0x1028025f:
@@ -4146,8 +4152,6 @@ again:
                        break;
                case 0x10280271: /* Digital Mics */
                case 0x10280272:
-                       spec->init = dell_m6_core_init;
-                       /* fall-through */
                case 0x10280254:
                case 0x10280255:
                        stac92xx_set_config_reg(codec, 0x13, 0x90A60160);
index a3adbf06b1e5e6dc1d2f51efa2a0213ae4dc9083..16c7453f494691cd3f75b6d6fe4ef5b45c339c84 100644 (file)
@@ -95,8 +95,8 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
        codec->ac97->dev.parent = NULL;
        codec->ac97->dev.release = soc_ac97_device_release;
 
-       snprintf(codec->ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s",
-                codec->card->number, 0, codec->name);
+       dev_set_name(&codec->ac97->dev, "%d-%d:%s",
+                    codec->card->number, 0, codec->name);
        err = device_register(&codec->ac97->dev);
        if (err < 0) {
                snd_printk(KERN_ERR "Can't register ac97 bus\n");