Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 10 Feb 2008 22:09:44 +0000 (14:09 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sun, 10 Feb 2008 22:09:44 +0000 (14:09 -0800)
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (30 commits)
  [ARM] constify function pointer tables
  [ARM] 4823/1: AT91 section fix
  [ARM] 4824/1: pxa: clear RDH bit after any reset
  [ARM] pxa: remove debugging PM: printk
  ARM: OMAP1: Misc clean-up
  ARM: OMAP1: Update defconfigs for omap1
  ARM: OMAP1: Palm Tungsten E board clean-up
  ARM: OMAP1: Use I2C bus registration helper for omap1
  ARM: OMAP1: Remove omap_sram_idle()
  ARM: OMAP1: PM fixes for OMAP1
  ARM: OMAP1: Use MMC multislot structures for Siemens SX1 board
  ARM: OMAP1: Make omap1 use MMC multislot structures
  ARM: OMAP1: Change the comments to C style
  ARM: OMAP1: Make omap1 boards to use omap_nand_platform_data
  ARM: OMAP: Add helper module for board specific I2C bus registration
  ARM: OMAP: Add dmtimer support for OMAP3
  ARM: OMAP: Pre-3430 clean-up for dmtimer.c
  ARM: OMAP: Add DMA support for chaining and 3430
  ARM: OMAP: Add 24xx GPIO debounce support
  ARM: OMAP: Get rid of unnecessary ifdefs in GPIO code
  ...

278 files changed:
Documentation/00-INDEX
Documentation/feature-removal-schedule.txt
Documentation/laptops/00-INDEX [new file with mode: 0644]
Documentation/laptops/acer-wmi.txt [new file with mode: 0644]
Documentation/laptops/sony-laptop.txt [moved from Documentation/sony-laptop.txt with 99% similarity]
Documentation/laptops/sonypi.txt [moved from Documentation/sonypi.txt with 100% similarity]
Documentation/laptops/thinkpad-acpi.txt [moved from Documentation/thinkpad-acpi.txt with 100% similarity]
Documentation/sysctl/kernel.txt
MAINTAINERS
arch/alpha/Kconfig
arch/arm/Kconfig
arch/avr32/Kconfig
arch/blackfin/Kconfig
arch/cris/Kconfig
arch/frv/Kconfig
arch/h8300/Kconfig
arch/ia64/Kconfig
arch/ia64/pci/pci.c
arch/ia64/sn/pci/tioce_provider.c
arch/m32r/Kconfig
arch/m68k/Kconfig
arch/m68knommu/Kconfig
arch/mips/Kconfig
arch/parisc/Kconfig
arch/powerpc/Kconfig
arch/ppc/Kconfig
arch/s390/defconfig
arch/s390/kernel/binfmt_elf32.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/process.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/traps.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/s390/mm/mmap.c
arch/s390/mm/pgtable.c
arch/s390/mm/vmem.c
arch/sh/Kconfig
arch/sparc/Kconfig
arch/sparc/kernel/errtbls.c
arch/sparc/kernel/of_device.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc64/Kconfig
arch/sparc64/kernel/iommu.c
arch/sparc64/kernel/iommu_common.h
arch/sparc64/kernel/kprobes.c
arch/sparc64/kernel/of_device.c
arch/sparc64/kernel/pci_sun4v.c
arch/v850/Kconfig
arch/x86/Kconfig
arch/x86/Kconfig.debug
arch/x86/Makefile
arch/x86/boot/.gitignore
arch/x86/boot/printf.c
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/kernel/Makefile
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/geode_32.c
arch/x86/kernel/head_32.S
arch/x86/kernel/mfgpt_32.c
arch/x86/kernel/quirks.c
arch/x86/kernel/setup_32.c
arch/x86/kernel/topology.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/pageattr.c
arch/x86/pci/common.c
arch/x86/pci/direct.c
arch/x86/pci/fixup.c
arch/x86/pci/legacy.c
arch/x86/pci/mmconfig-shared.c
arch/x86/pci/mmconfig_32.c
arch/x86/pci/mmconfig_64.c
arch/x86/pci/pci.h
arch/x86/pci/visws.c
arch/x86/power/Makefile
arch/x86/power/cpu_32.c [moved from arch/x86/power/cpu.c with 99% similarity]
arch/x86/power/cpu_64.c [moved from arch/x86/kernel/suspend_64.c with 53% similarity]
arch/x86/power/hibernate_32.c [moved from arch/x86/power/suspend.c with 96% similarity]
arch/x86/power/hibernate_64.c [new file with mode: 0644]
arch/x86/power/hibernate_asm_32.S [moved from arch/x86/power/swsusp.S with 96% similarity]
arch/x86/power/hibernate_asm_64.S [moved from arch/x86/kernel/suspend_asm_64.S with 95% similarity]
arch/x86/xen/mmu.c
arch/x86/xen/time.c
arch/xtensa/Kconfig
drivers/Kconfig
drivers/Makefile
drivers/acpi/Makefile
drivers/acpi/bus.c
drivers/acpi/osl.c
drivers/acpi/sbs.c
drivers/acpi/sbshc.c
drivers/block/ub.c
drivers/char/Kconfig
drivers/cpuidle/cpuidle.c
drivers/ide/Kconfig
drivers/isdn/hisax/avm_a1p.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/hfc_sx.c
drivers/isdn/hisax/isac.c
drivers/isdn/hisax/isar.c
drivers/lguest/page_tables.c
drivers/media/video/em28xx/Kconfig
drivers/memstick/Kconfig [new file with mode: 0644]
drivers/memstick/Makefile [new file with mode: 0644]
drivers/memstick/core/Kconfig [new file with mode: 0644]
drivers/memstick/core/Makefile [new file with mode: 0644]
drivers/memstick/core/memstick.c [new file with mode: 0644]
drivers/memstick/core/mspro_block.c [new file with mode: 0644]
drivers/memstick/host/Kconfig [new file with mode: 0644]
drivers/memstick/host/Makefile [new file with mode: 0644]
drivers/memstick/host/tifm_ms.c [new file with mode: 0644]
drivers/misc/Kconfig
drivers/misc/acer-wmi.c
drivers/misc/tifm_7xx1.c
drivers/misc/tifm_core.c
drivers/mmc/host/Kconfig
drivers/mmc/host/at91_mci.c
drivers/mmc/host/ricoh_mmc.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/nand/cs553x_nand.c
drivers/net/bnx2.c
drivers/net/bnx2x.c
drivers/net/natsemi.c
drivers/net/pppol2tp.c
drivers/net/starfire.c
drivers/net/typhoon.c
drivers/net/via-velocity.c
drivers/net/wan/x25_asy.c
drivers/pcmcia/Kconfig
drivers/rtc/rtc-r9701.c
drivers/s390/char/sclp_vt220.c
drivers/s390/cio/qdio.c
drivers/s390/crypto/ap_bus.c
drivers/scsi/aic7xxx/Makefile
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/migrate.c
fs/ext4/namei.c
fs/ext4/super.c
fs/hostfs/hostfs_kern.c
fs/ioctl.c
fs/jbd/commit.c
fs/jbd2/commit.c
fs/jbd2/recovery.c
fs/splice.c
include/asm-blackfin/page.h
include/asm-h8300/page.h
include/asm-m68knommu/page.h
include/asm-s390/a.out.h [deleted file]
include/asm-s390/bitops.h
include/asm-s390/elf.h
include/asm-s390/mmu.h
include/asm-s390/mmu_context.h
include/asm-s390/page.h
include/asm-s390/pgalloc.h
include/asm-s390/pgtable.h
include/asm-s390/processor.h
include/asm-s390/tlb.h
include/asm-s390/tlbflush.h
include/asm-s390/unistd.h
include/asm-sparc/a.out.h
include/asm-sparc/bpp.h
include/asm-sparc/bsderrno.h [deleted file]
include/asm-sparc/bug.h
include/asm-sparc/bugs.h
include/asm-sparc/byteorder.h
include/asm-sparc/cache.h
include/asm-sparc/current.h
include/asm-sparc/device.h
include/asm-sparc/errno.h
include/asm-sparc/fb.h
include/asm-sparc/of_platform.h
include/asm-sparc/prom.h
include/asm-sparc64/a.out.h
include/asm-sparc64/auxvec.h
include/asm-sparc64/bpp.h
include/asm-sparc64/bsderrno.h [deleted file]
include/asm-sparc64/bug.h
include/asm-sparc64/bugs.h
include/asm-sparc64/byteorder.h
include/asm-sparc64/cache.h
include/asm-sparc64/cputime.h
include/asm-sparc64/current.h
include/asm-sparc64/device.h
include/asm-sparc64/div64.h
include/asm-sparc64/emergency-restart.h
include/asm-sparc64/errno.h
include/asm-sparc64/fb.h
include/asm-sparc64/io.h
include/asm-sparc64/iommu.h
include/asm-sparc64/kprobes.h
include/asm-sparc64/of_device.h
include/asm-sparc64/of_platform.h
include/asm-sparc64/prom.h
include/asm-v850/page.h
include/asm-x86/acpi.h
include/asm-x86/cacheflush.h
include/asm-x86/geode.h
include/asm-x86/page_32.h
include/asm-x86/pgtable.h
include/asm-x86/pgtable_32.h
include/linux/compiler-gcc4.h
include/linux/ext4_fs.h
include/linux/hrtimer.h
include/linux/memcontrol.h
include/linux/memstick.h [new file with mode: 0644]
include/linux/pci.h
include/linux/sctp.h
include/linux/swapops.h
include/linux/thermal.h
include/linux/tifm.h
include/linux/timex.h
include/net/sctp/auth.h
include/net/sctp/command.h
include/net/sctp/constants.h
include/net/sctp/sctp.h
include/net/sctp/sm.h
include/net/sctp/structs.h
include/net/sctp/tsnmap.h
include/net/sctp/ulpevent.h
include/net/sctp/ulpqueue.h
include/net/sctp/user.h
init/Kconfig
init/Makefile
init/main.c
kernel/.gitignore
kernel/compat.c
kernel/hrtimer.c
kernel/posix-timers.c
kernel/time/ntp.c
lib/Kconfig.debug
lib/vsprintf.c
mm/memcontrol.c
mm/rmap.c
net/ipv4/igmp.c
net/ipv6/route.c
net/key/af_key.c
net/sched/em_meta.c
net/sched/ematch.c
net/sched/sch_htb.c
net/sctp/associola.c
net/sctp/auth.c
net/sctp/bind_addr.c
net/sctp/chunk.c
net/sctp/command.c
net/sctp/debug.c
net/sctp/endpointola.c
net/sctp/input.c
net/sctp/inqueue.c
net/sctp/ipv6.c
net/sctp/objcnt.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/primitive.c
net/sctp/proc.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/sm_statetable.c
net/sctp/socket.c
net/sctp/ssnmap.c
net/sctp/sysctl.c
net/sctp/transport.c
net/sctp/tsnmap.c
net/sctp/ulpevent.c
net/sctp/ulpqueue.c
scripts/.gitignore
scripts/Kbuild.include
scripts/mod/modpost.c
scripts/package/builddeb

index 6e9c4050a41baedb072d0d0ba60d2391c7fd4e88..8d556707bb68e9ca8357143f0c318027b16319bc 100644 (file)
@@ -227,6 +227,8 @@ kref.txt
        - docs on adding reference counters (krefs) to kernel objects.
 laptop-mode.txt
        - how to conserve battery power using laptop-mode.
+laptops/
+       - directory with laptop related info and laptop driver documentation.
 ldm.txt
        - a brief description of LDM (Windows Dynamic Disks).
 leds-class.txt
@@ -351,10 +353,6 @@ sh/
        - directory with info on porting Linux to a new architecture.
 smart-config.txt
        - description of the Smart Config makefile feature.
-sony-laptop.txt
-       - Sony Notebook Control Driver (SNC) Readme.
-sonypi.txt
-       - info on Linux Sony Programmable I/O Device support.
 sound/
        - directory with info on sound card support.
 sparc/
@@ -385,8 +383,6 @@ sysrq.txt
        - info on the magic SysRq key.
 telephony/
        - directory with info on telephony (e.g. voice over IP) support.
-thinkpad-acpi.txt
-       - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver.
 time_interpolators.txt
        - info on time interpolators.
 tipar.txt
index ce9503c892b525ea69ff41a5aec2f9c16cd65c71..4d3aa519eadfc5cebea01e5244f0435702264319 100644 (file)
@@ -111,15 +111,6 @@ Who:       Christoph Hellwig <hch@lst.de>
 
 ---------------------------
 
-What:  CONFIG_FORCED_INLINING
-When:  June 2006
-Why:   Config option is there to see if gcc is good enough. (in january
-        2006). If it is, the behavior should just be the default. If it's not,
-       the option should just go away entirely.
-Who:    Arjan van de Ven
-
----------------------------
-
 What:   eepro100 network driver
 When:   January 2007
 Why:    replaced by the e100 driver
@@ -304,3 +295,14 @@ Why:       The support code for the old firmware hurts code readability/maintainabilit
        and slightly hurts runtime performance. Bugfixes for the old firmware
        are not provided by Broadcom anymore.
 Who:   Michael Buesch <mb@bu3sch.de>
+
+---------------------------
+
+What:  Solaris/SunOS syscall and binary support on Sparc
+When:  2.6.26
+Why:   Largely unmaintained and almost entirely unused.  File system
+       layering used to divert library and dynamic linker searches to
+       /usr/gnemul is extremely buggy and unfixable.  Making it work
+       is largely pointless as without a lot of work only the most
+       trivial of Solaris binaries can work with the emulation code.
+Who:   David S. Miller <davem@davemloft.net>
diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX
new file mode 100644 (file)
index 0000000..729c2c0
--- /dev/null
@@ -0,0 +1,10 @@
+00-INDEX
+       - This file
+acer-wmi.txt
+       - information on the Acer Laptop WMI Extras driver.
+sony-laptop.txt
+       - Sony Notebook Control Driver (SNC) Readme.
+sonypi.txt
+       - info on Linux Sony Programmable I/O Device support.
+thinkpad-acpi.txt
+       - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver.
diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt
new file mode 100644 (file)
index 0000000..b066963
--- /dev/null
@@ -0,0 +1,202 @@
+Acer Laptop WMI Extras Driver
+http://code.google.com/p/aceracpi
+Version 0.1
+9th February 2008
+
+Copyright 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
+
+acer-wmi is a driver to allow you to control various parts of your Acer laptop
+hardware under Linux which are exposed via ACPI-WMI.
+
+This driver completely replaces the old out-of-tree acer_acpi, which I am
+currently maintaining for bug fixes only on pre-2.6.25 kernels. All development
+work is now focused solely on acer-wmi.
+
+Disclaimer
+**********
+
+Acer and Wistron have provided nothing towards the development acer_acpi or
+acer-wmi. All information we have has been through the efforts of the developers
+and the users to discover as much as possible about the hardware.
+
+As such, I do warn that this could break your hardware - this is extremely
+unlikely of course, but please bear this in mind.
+
+Background
+**********
+
+acer-wmi is derived from acer_acpi, originally developed by Mark
+Smith in 2005, then taken over by Carlos Corbacho in 2007, in order to activate
+the wireless LAN card under a 64-bit version of Linux, as acerhk[1] (the
+previous solution to the problem) relied on making 32 bit BIOS calls which are
+not possible in kernel space from a 64 bit OS.
+
+[1] acerhk: http://www.cakey.de/acerhk/
+
+Supported Hardware
+******************
+
+Please see the website for the current list of known working hardare:
+
+http://code.google.com/p/aceracpi/wiki/SupportedHardware
+
+If your laptop is not listed, or listed as unknown, and works with acer-wmi,
+please contact me with a copy of the DSDT.
+
+If your Acer laptop doesn't work with acer-wmi, I would also like to see the
+DSDT.
+
+To send me the DSDT, as root/sudo:
+
+cat /sys/firmware/acpi/DSDT > dsdt
+
+And send me the resulting 'dsdt' file.
+
+Usage
+*****
+
+On Acer laptops, acer-wmi should already be autoloaded based on DMI matching.
+For non-Acer laptops, until WMI based autoloading support is added, you will
+need to manually load acer-wmi.
+
+acer-wmi creates /sys/devices/platform/acer-wmi, and fills it with various
+files whose usage is detailed below, which enables you to control some of the
+following (varies between models):
+
+* the wireless LAN card radio
+* inbuilt Bluetooth adapter
+* inbuilt 3G card
+* mail LED of your laptop
+* brightness of the LCD panel
+
+Wireless
+********
+
+With regards to wireless, all acer-wmi does is enable the radio on the card. It
+is not responsible for the wireless LED - once the radio is enabled, this is
+down to the wireless driver for your card. So the behaviour of the wireless LED,
+once you enable the radio, will depend on your hardware and driver combination.
+
+e.g. With the BCM4318 on the Acer Aspire 5020 series:
+
+ndiswrapper: Light blinks on when transmitting
+bcm43xx/b43: Solid light, blinks off when transmitting
+
+Wireless radio control is unconditionally enabled - all Acer laptops that support
+acer-wmi come with built-in wireless. However, should you feel so inclined to
+ever wish to remove the card, or swap it out at some point, please get in touch
+with me, as we may well be able to gain some data on wireless card detection.
+
+To read the status of the wireless radio (0=off, 1=on):
+cat /sys/devices/platform/acer-wmi/wireless
+
+To enable the wireless radio:
+echo 1 > /sys/devices/platform/acer-wmi/wireless
+
+To disable the wireless radio:
+echo 0 > /sys/devices/platform/acer-wmi/wireless
+
+To set the state of the wireless radio when loading acer-wmi, pass:
+wireless=X (where X is 0 or 1)
+
+Bluetooth
+*********
+
+For bluetooth, this is an internal USB dongle, so once enabled, you will get
+a USB device connection event, and a new USB device appears. When you disable
+bluetooth, you get the reverse - a USB device disconnect event, followed by the
+device disappearing again.
+
+Bluetooth is autodetected by acer-wmi, so if you do not have a bluetooth module
+installed in your laptop, this file won't exist (please be aware that it is
+quite common for Acer not to fit bluetooth to their laptops - so just because
+you have a bluetooth button on the laptop, doesn't mean that bluetooth is
+installed).
+
+For the adventurously minded - if you want to buy an internal bluetooth
+module off the internet that is compatible with your laptop and fit it, then
+it will work just fine with acer-wmi.
+
+To read the status of the bluetooth module (0=off, 1=on):
+cat /sys/devices/platform/acer-wmi/wireless
+
+To enable the bluetooth module:
+echo 1 > /sys/devices/platform/acer-wmi/bluetooth
+
+To disable the bluetooth module:
+echo 0 > /sys/devices/platform/acer-wmi/bluetooth
+
+To set the state of the bluetooth module when loading acer-wmi, pass:
+bluetooth=X (where X is 0 or 1)
+
+3G
+**
+
+3G is currently not autodetected, so the 'threeg' file is always created under
+sysfs. So far, no-one in possession of an Acer laptop with 3G built-in appears to
+have tried Linux, or reported back, so we don't have any information on this.
+
+If you have an Acer laptop that does have a 3G card in, please contact me so we
+can properly detect these, and find out a bit more about them.
+
+To read the status of the 3G card (0=off, 1=on):
+cat /sys/devices/platform/acer-wmi/threeg
+
+To enable the 3G card:
+echo 1 > /sys/devices/platform/acer-wmi/threeg
+
+To disable the 3G card:
+echo 0 > /sys/devices/platform/acer-wmi/threeg
+
+To set the state of the 3G card when loading acer-wmi, pass:
+threeg=X (where X is 0 or 1)
+
+Mail LED
+********
+
+This can be found in most older Acer laptops supported by acer-wmi, and many
+newer ones - it is built into the 'mail' button, and blinks when active.
+
+On newer (WMID) laptops though, we have no way of detecting the mail LED. If
+your laptop identifies itself in dmesg as a WMID model, then please try loading
+acer_acpi with:
+
+force_series=2490
+
+This will use a known alternative method of reading/ writing the mail LED. If
+it works, please report back to me with the DMI data from your laptop so this
+can be added to acer-wmi.
+
+The LED is exposed through the LED subsystem, and can be found in:
+
+/sys/devices/platform/acer-wmi/leds/acer-mail:green/
+
+The mail LED is autodetected, so if you don't have one, the LED device won't
+be registered.
+
+If you have a mail LED that is not green, please report this to me.
+
+Backlight
+*********
+
+The backlight brightness control is available on all acer-wmi supported
+hardware. The maximum brightness level is usually 15, but on some newer laptops
+it's 10 (this is again autodetected).
+
+The backlight is exposed through the backlight subsystem, and can be found in:
+
+/sys/devices/platform/acer-wmi/backlight/acer-wmi/
+
+Credits
+*******
+
+Olaf Tauber, who did the real hard work when he developed acerhk
+http://www.informatik.hu-berlin.de/~tauber/acerhk
+All the authors of laptop ACPI modules in the kernel, whose work
+was an inspiration in the early days of acer_acpi
+Mathieu Segaud, who solved the problem with having to modprobe the driver
+twice in acer_acpi 0.2.
+Jim Ramsay, who added support for the WMID interface
+Mark Smith, who started the original acer_acpi
+
+And the many people who have used both acer_acpi and acer-wmi.
similarity index 99%
rename from Documentation/sony-laptop.txt
rename to Documentation/laptops/sony-laptop.txt
index 7a5c1a81905c66940fe2c3a2d516b237f957b970..8b2bc1572d98eae5fe8e2c78dd0be77bee1d9326 100644 (file)
@@ -114,4 +114,3 @@ Bugs/Limitations:
   sonypi driver (through /dev/sonypi) does not try to use the
   sony-laptop driver. In the future, spicctrl could try sonypi first,
   and if it isn't present, try sony-laptop instead.
-
index 8984a53962716f3f528964d6c318a9e7dcdf8a47..dc8801d4e9445d749eb6f3e52e1b33b61950c82c 100644 (file)
@@ -41,6 +41,7 @@ show up in /proc/sys/kernel:
 - pid_max
 - powersave-nap               [ PPC only ]
 - printk
+- randomize_va_space
 - real-root-dev               ==> Documentation/initrd.txt
 - reboot-cmd                  [ SPARC only ]
 - rtsig-max
@@ -280,6 +281,34 @@ send before ratelimiting kicks in.
 
 ==============================================================
 
+randomize-va-space:
+
+This option can be used to select the type of process address
+space randomization that is used in the system, for architectures
+that support this feature.
+
+0 - Turn the process address space randomization off by default.
+
+1 - Make the addresses of mmap base, stack and VDSO page randomized.
+    This, among other things, implies that shared libraries will be
+    loaded to random addresses. Also for PIE-linked binaries, the location
+    of code start is randomized.
+
+    With heap randomization, the situation is a little bit more
+    complicated.
+    There a few legacy applications out there (such as some ancient
+    versions of libc.so.5 from 1996) that assume that brk area starts
+    just after the end of the code+bss. These applications break when
+    start of the brk area is randomized. There are however no known
+    non-legacy applications that would be broken this way, so for most
+    systems it is safe to choose full randomization. However there is
+    a CONFIG_COMPAT_BRK option for systems with ancient and/or broken
+    binaries, that makes heap non-randomized, but keeps all other
+    parts of process address space randomized if randomize_va_space
+    sysctl is turned on.
+
+==============================================================
+
 reboot-cmd: (Sparc only)
 
 ??? This seems to be a way to give an argument to the Sparc
index 0d6f5119a6da08e49ab50e316a606c4acaf9a9a6..c40f0ae965523a04ef327be9c13c97923e67fb6c 100644 (file)
@@ -2682,7 +2682,6 @@ MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
 P:     Pavel Pisa
 M:     ppisa@pikron.com
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
-W:     http://mmc.drzeus.cx/wiki/Controllers/Freescale/SDHC
 S:     Maintained
 
 MOUSE AND MISC DEVICES [GENERAL]
@@ -3627,6 +3626,13 @@ L:       linux-acpi@vger.kernel.org
 W:     http://www.linux.it/~malattia/wiki/index.php/Sony_drivers
 S:     Maintained
 
+SONY MEMORYSTICK CARD SUPPORT
+P:     Alex Dubov
+M:     oakad@yahoo.com
+L:     linux-kernel@vger.kernel.org
+W:     http://tifmxx.berlios.de/
+S:     Maintained
+
 SOUND
 P:     Jaroslav Kysela
 M:     perex@perex.cz
@@ -3709,7 +3715,6 @@ SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER
 P:     Pierre Ossman
 M:     drzeus-sdhci@drzeus.cx
 L:     sdhci-devel@list.drzeus.cx
-W:     http://mmc.drzeus.cx/wiki/Linux/Drivers/sdhci
 S:     Maintained
 
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
@@ -4279,7 +4284,6 @@ W83L51xD SD/MMC CARD INTERFACE DRIVER
 P:     Pierre Ossman
 M:     drzeus-wbsd@drzeus.cx
 L:     linux-kernel@vger.kernel.org
-W:     http://projects.drzeus.cx/wbsd
 S:     Maintained
 
 WATCHDOG DEVICE DRIVERS
index 5b7dcd5a0e75b663e709b093bc2f4f21fb3d49b8..002703b8c0b033d72eea6297b869796f772c2c6e 100644 (file)
@@ -5,6 +5,7 @@
 config ALPHA
        bool
        default y
+       select HAVE_IDE
        select HAVE_OPROFILE
        help
          The Alpha is a 64-bit general-purpose processor designed and
index 4127af93c5f373fdf31e81f4d748bf60decc514a..9619c43783ffd333ad8346aa6e9b85f0de750d7e 100644 (file)
@@ -222,6 +222,7 @@ config ARCH_CLPS7500
        select TIMER_ACORN
        select ISA
        select NO_IOPORT
+       select HAVE_IDE
        help
          Support for the Cirrus Logic PS7500FE system-on-a-chip.
 
@@ -234,6 +235,7 @@ config ARCH_CO285
        bool "Co-EBSA285"
        select FOOTBRIDGE
        select FOOTBRIDGE_ADDIN
+       select HAVE_IDE
        help
          Support for Intel's EBSA285 companion chip.
 
@@ -258,6 +260,7 @@ config ARCH_EP93XX
 config ARCH_FOOTBRIDGE
        bool "FootBridge"
        select FOOTBRIDGE
+       select HAVE_IDE
        help
          Support for systems based on the DC21285 companion chip
          ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@@ -296,6 +299,7 @@ config ARCH_IOP32X
        depends on MMU
        select PLAT_IOP
        select PCI
+       select HAVE_IDE
        help
          Support for Intel's 80219 and IOP32X (XScale) family of
          processors.
@@ -305,12 +309,14 @@ config ARCH_IOP33X
        depends on MMU
        select PLAT_IOP
        select PCI
+       select HAVE_IDE
        help
          Support for Intel's IOP33X (XScale) family of processors.
 
 config ARCH_IXP23XX
        bool "IXP23XX-based"
        depends on MMU
+       select HAVE_IDE
        select PCI
        help
          Support for Intel's IXP23xx (XScale) family of processors.
@@ -328,12 +334,14 @@ config ARCH_IXP4XX
        select GENERIC_GPIO
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
+       select HAVE_IDE
        help
          Support for Intel's IXP4XX (XScale) family of processors.
 
 config ARCH_L7200
        bool "LinkUp-L7200"
        select FIQ
+       select HAVE_IDE
        help
          Say Y here if you intend to run this kernel on a LinkUp Systems
          L7200 Software Development Board which uses an ARM720T processor.
@@ -388,6 +396,7 @@ config ARCH_PXA
        depends on MMU
        select ARCH_MTD_XIP
        select GENERIC_GPIO
+       select HAVE_IDE
        select HAVE_GPIO_LIB
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
@@ -403,6 +412,7 @@ config ARCH_RPC
        select ARCH_MAY_HAVE_PC_FDC
        select ISA_DMA_API
        select NO_IOPORT
+       select HAVE_IDE
        help
          On the Acorn Risc-PC, Linux can support the internal IDE disk and
          CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -414,12 +424,14 @@ config ARCH_SA1100
        select ARCH_MTD_XIP
        select GENERIC_GPIO
        select GENERIC_TIME
+       select HAVE_IDE
        help
          Support for StrongARM 11x0 based boards.
 
 config ARCH_S3C2410
        bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
        select GENERIC_GPIO
+       select HAVE_IDE
        help
          Samsung S3C2410X CPU based systems, such as the Simtec Electronics
          BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -427,6 +439,7 @@ config ARCH_S3C2410
 
 config ARCH_SHARK
        bool "Shark"
+       select HAVE_IDE
        select ISA
        select ISA_DMA
        select PCI
@@ -436,6 +449,7 @@ config ARCH_SHARK
 
 config ARCH_LH7A40X
        bool "Sharp LH7A40X"
+       select HAVE_IDE
        help
          Say Y here for systems based on one of the Sharp LH7A40X
          System on a Chip processors.  These CPUs include an ARM922T
@@ -1093,12 +1107,7 @@ source "drivers/block/Kconfig"
 
 source "drivers/misc/Kconfig"
 
-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
-       || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
-       || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
-       || ARCH_IXP23XX
 source "drivers/ide/Kconfig"
-endif
 
 source "drivers/scsi/Kconfig"
 
index 28e0caf4156ca68bb066d8300fd1947264e28037..c75d7089f982bba957ced3680d4d2bf9b52f56d3 100644 (file)
@@ -10,6 +10,7 @@ config AVR32
        # With EMBEDDED=n, we get lots of stuff automatically selected
        # that we usually don't need on AVR32.
        select EMBEDDED
+       select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_KPROBES
        help
index 368bc7fe167e70c1400b38e30188dda6b87baa00..589c6aca4803c83c1ac02f9d08735ca15510baca 100644 (file)
@@ -24,6 +24,7 @@ config RWSEM_XCHGADD_ALGORITHM
 config BLACKFIN
        bool
        default y
+       select HAVE_IDE
        select HAVE_OPROFILE
 
 config ZONE_DMA
index 8456bc8efb7c6b2ce3fa1107189b8e4ff92923fd..9389d38f222f2f749497b106872278a7da5bdd0b 100644 (file)
@@ -54,6 +54,7 @@ config FORCE_MAX_ZONEORDER
 config CRIS
        bool
        default y
+       select HAVE_IDE
 
 config HZ
        int
index 9e561ede0925b6928bb44907c1bcde6ee4139d43..a5aac1b075628b8a30004d52bb73d2e1ce7d978f 100644 (file)
@@ -5,6 +5,7 @@
 config FRV
        bool
        default y
+       select HAVE_IDE
 
 config ZONE_DMA
        bool
index f69e5ea385588d0c554fe5f0d3ca2ff82f8c2138..085dc6ec152b057b6da23c2742a39d0a0012c327 100644 (file)
@@ -8,6 +8,7 @@ mainmenu "uClinux/h8300 (w/o MMU) Kernel Configuration"
 config H8300
        bool
        default y
+       select HAVE_IDE
 
 config MMU
        bool
index b0de1132dfc02e0537c381b66be30d507daee2f5..2d4fcd01bc913a1103431516e3204827b331e886 100644 (file)
@@ -15,6 +15,7 @@ config IA64
        select ACPI if (!IA64_HP_SIM)
        select PM if (!IA64_HP_SIM)
        select ARCH_SUPPORTS_MSI
+       select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_KPROBES
        default y
index 488e48a5deeaefd75d390df505a59288ccb828f4..8fd7e825192b60160bf82215ed3004d22da075eb 100644 (file)
@@ -43,8 +43,7 @@
 #define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg)      \
        (((u64) seg << 28) | (bus << 20) | (devfn << 12) | (reg))
 
-static int
-pci_sal_read (unsigned int seg, unsigned int bus, unsigned int devfn,
+int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn,
              int reg, int len, u32 *value)
 {
        u64 addr, data = 0;
@@ -68,8 +67,7 @@ pci_sal_read (unsigned int seg, unsigned int bus, unsigned int devfn,
        return 0;
 }
 
-static int
-pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
+int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn,
               int reg, int len, u32 value)
 {
        u64 addr;
@@ -91,24 +89,17 @@ pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
        return 0;
 }
 
-static struct pci_raw_ops pci_sal_ops = {
-       .read =         pci_sal_read,
-       .write =        pci_sal_write
-};
-
-struct pci_raw_ops *raw_pci_ops = &pci_sal_ops;
-
-static int
-pci_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
+static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+                                                       int size, u32 *value)
 {
-       return raw_pci_ops->read(pci_domain_nr(bus), bus->number,
+       return raw_pci_read(pci_domain_nr(bus), bus->number,
                                 devfn, where, size, value);
 }
 
-static int
-pci_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
+static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+                                                       int size, u32 value)
 {
-       return raw_pci_ops->write(pci_domain_nr(bus), bus->number,
+       return raw_pci_write(pci_domain_nr(bus), bus->number,
                                  devfn, where, size, value);
 }
 
index e1a3e19d3d9c9c8a0e55852e9df3f3011e06416a..999f14f986e2cc99c8f6204d598092e2e942d4ea 100644 (file)
@@ -752,13 +752,13 @@ tioce_kern_init(struct tioce_common *tioce_common)
         * Determine the secondary bus number of the port2 logical PPB.
         * This is used to decide whether a given pci device resides on
         * port1 or port2.  Note:  We don't have enough plumbing set up
-        * here to use pci_read_config_xxx() so use the raw_pci_ops vector.
+        * here to use pci_read_config_xxx() so use raw_pci_read().
         */
 
        seg = tioce_common->ce_pcibus.bs_persist_segment;
        bus = tioce_common->ce_pcibus.bs_persist_busnum;
 
-       raw_pci_ops->read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp);
+       raw_pci_read(seg, bus, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1,&tmp);
        tioce_kern->ce_port1_secondary = (u8) tmp;
 
        /*
@@ -799,11 +799,11 @@ tioce_kern_init(struct tioce_common *tioce_common)
 
                /* mem base/limit */
 
-               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+               raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
                                  PCI_MEMORY_BASE, 2, &tmp);
                base = (u64)tmp << 16;
 
-               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+               raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
                                  PCI_MEMORY_LIMIT, 2, &tmp);
                limit = (u64)tmp << 16;
                limit |= 0xfffffUL;
@@ -817,21 +817,21 @@ tioce_kern_init(struct tioce_common *tioce_common)
                 * attributes.
                 */
 
-               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+               raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
                                  PCI_PREF_MEMORY_BASE, 2, &tmp);
                base = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
 
-               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+               raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
                                  PCI_PREF_BASE_UPPER32, 4, &tmp);
                base |= (u64)tmp << 32;
 
-               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+               raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
                                  PCI_PREF_MEMORY_LIMIT, 2, &tmp);
 
                limit = ((u64)tmp & PCI_PREF_RANGE_MASK) << 16;
                limit |= 0xfffffUL;
 
-               raw_pci_ops->read(seg, bus, PCI_DEVFN(dev, 0),
+               raw_pci_read(seg, bus, PCI_DEVFN(dev, 0),
                                  PCI_PREF_LIMIT_UPPER32, 4, &tmp);
                limit |= (u64)tmp << 32;
 
index d4679ab55b969c3fe8bfc4f88dfef02d618e1877..de153de2ea9f34df702bcbd7c915ee119e9bac53 100644 (file)
@@ -8,6 +8,7 @@ mainmenu "Linux/M32R Kernel Configuration"
 config M32R
        bool
        default y
+       select HAVE_IDE
        select HAVE_OPROFILE
 
 config SBUS
index 2b0ed89cd173728ddda8ad3ea201977c5ee0484c..65db2261b9ea5baa94d87a2042d690200cdcb874 100644 (file)
@@ -5,6 +5,7 @@
 config M68K
        bool
        default y
+       select HAVE_IDE
 
 config MMU
        bool
index 548a7b321633c670b358f190e2a92a54a694ba45..07eb4c4bab8243723ead643a13d6f5611a42d032 100644 (file)
@@ -8,6 +8,7 @@ mainmenu "uClinux/68k (w/o MMU) Kernel Configuration"
 config M68K
        bool
        default y
+       select HAVE_IDE
 
 config MMU
        bool
index ec78a5762e9ec3be6a23630413c4f81a5f6b0fe9..ade230d445d9fd1ed952bc191720e60c679d9073 100644 (file)
@@ -1,6 +1,7 @@
 config MIPS
        bool
        default y
+       select HAVE_IDE
        select HAVE_OPROFILE
        # Horrible source of confusion.  Die, die, die ...
        select EMBEDDED
index d929ac84f25a1fcd5a636249d24c5921508d483d..bc7a19da6245d89349cf4c532cc8233623a217de 100644 (file)
@@ -7,6 +7,7 @@ mainmenu "Linux/PA-RISC Kernel Configuration"
 
 config PARISC
        def_bool y
+       select HAVE_IDE
        select HAVE_OPROFILE
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
index 26b963c33c88d0e9dd64e336a5c72336e8195c73..485513c9f1af4c4f4f0aa91ad6d29f0ccb363c1c 100644 (file)
@@ -87,6 +87,7 @@ config ARCH_NO_VIRT_TO_BUS
 config PPC
        bool
        default y
+       select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_KPROBES
 
index 531156f8919ca5e4877f1835a14a303a232496ae..abc877faf1232eb73cc284d6737e8ef356bef308 100644 (file)
@@ -42,6 +42,7 @@ config GENERIC_CALIBRATE_DELAY
 config PPC
        bool
        default y
+       select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_KPROBES
 
index ece7b99da8955c8e31ae82a7726e3ea5c76e7c83..39921f3a9685a74247c9c2b8fbee8ad48bf1142c 100644 (file)
@@ -1,12 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.23
-# Mon Oct 22 12:10:44 2007
+# Linux kernel version: 2.6.24
+# Sat Feb  9 12:13:01 2008
 #
 CONFIG_MMU=y
 CONFIG_ZONE_DMA=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -15,6 +16,7 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_BUG=y
 CONFIG_NO_IOMEM=y
 CONFIG_NO_DMA=y
+CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_S390=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -32,7 +34,6 @@ CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_USER_NS is not set
 CONFIG_AUDIT=y
 # CONFIG_AUDITSYSCALL is not set
 CONFIG_IKCONFIG=y
@@ -41,13 +42,19 @@ CONFIG_LOG_BUF_SHIFT=17
 CONFIG_CGROUPS=y
 # CONFIG_CGROUP_DEBUG is not set
 CONFIG_CGROUP_NS=y
-CONFIG_CGROUP_CPUACCT=y
 # CONFIG_CPUSETS is not set
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_FAIR_USER_SCHED=y
 # CONFIG_FAIR_CGROUP_SCHED is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -61,17 +68,26 @@ CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
+# CONFIG_COMPAT_BRK is not set
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -99,6 +115,8 @@ CONFIG_DEFAULT_DEADLINE=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
 
 #
 # Base setup
@@ -137,7 +155,7 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
-CONFIG_PREEMPT_BKL=y
+# CONFIG_RCU_TRACE is not set
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -151,7 +169,6 @@ CONFIG_RESOURCES_64BIT=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_HOLES_IN_ZONE=y
 
 #
 # I/O subsystem configuration
@@ -180,6 +197,7 @@ CONFIG_HZ_100=y
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
 CONFIG_NO_IDLE_HZ=y
 CONFIG_NO_IDLE_HZ_INIT=y
 CONFIG_S390_HYPFS_FS=y
@@ -201,6 +219,7 @@ CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
 CONFIG_NET_KEY=y
 # CONFIG_NET_KEY_MIGRATE is not set
 CONFIG_IUCV=m
@@ -251,6 +270,7 @@ CONFIG_IPV6_SIT=y
 # CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
 
 #
 # Core Netfilter Configuration
@@ -258,7 +278,6 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK=m
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
 CONFIG_NF_CONNTRACK=m
 # CONFIG_NF_CT_ACCT is not set
 # CONFIG_NF_CONNTRACK_MARK is not set
@@ -286,7 +305,7 @@ CONFIG_NF_CONNTRACK=m
 # CONFIG_IP_NF_ARPTABLES is not set
 
 #
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# IPv6: Netfilter Configuration
 #
 # CONFIG_NF_CONNTRACK_IPV6 is not set
 # CONFIG_IP6_NF_QUEUE is not set
@@ -343,6 +362,7 @@ CONFIG_NET_CLS_U32=m
 CONFIG_CLS_U32_MARK=y
 CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
 # CONFIG_NET_EMATCH is not set
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
@@ -351,7 +371,6 @@ CONFIG_NET_ACT_POLICE=y
 CONFIG_NET_ACT_NAT=m
 # CONFIG_NET_ACT_PEDIT is not set
 # CONFIG_NET_ACT_SIMP is not set
-CONFIG_NET_CLS_POLICE=y
 # CONFIG_NET_CLS_IND is not set
 CONFIG_NET_SCH_FIFO=y
 
@@ -360,6 +379,15 @@ CONFIG_NET_SCH_FIFO=y
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_NET_TCPPROBE is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
 # CONFIG_AF_RXRPC is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -389,7 +417,7 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_XIP=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -406,6 +434,7 @@ CONFIG_DASD_DIAG=y
 CONFIG_DASD_EER=y
 CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
 
 #
 # SCSI device support
@@ -487,6 +516,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_TAH is not set
 # CONFIG_IBM_NEW_EMAC_EMAC4 is not set
 CONFIG_NETDEV_1000=y
+# CONFIG_E1000E_ENABLED is not set
 CONFIG_NETDEV_10000=y
 # CONFIG_TR is not set
 # CONFIG_WAN is not set
@@ -508,7 +538,6 @@ CONFIG_QETH=y
 CONFIG_CCWGROUP=y
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -558,6 +587,7 @@ CONFIG_S390_TAPE_34XX=m
 CONFIG_MONWRITER=m
 CONFIG_S390_VMUR=m
 # CONFIG_POWER_SUPPLY is not set
+# CONFIG_THERMAL is not set
 # CONFIG_WATCHDOG is not set
 
 #
@@ -584,12 +614,10 @@ CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
+CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
@@ -632,8 +660,10 @@ CONFIG_CONFIGFS_FS=m
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
@@ -686,16 +716,13 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_NLS is not set
 CONFIG_DLM=m
 # CONFIG_DLM_DEBUG is not set
-CONFIG_INSTRUMENTATION=y
-# CONFIG_PROFILING is not set
-CONFIG_KPROBES=y
-# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
 #
 CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -721,12 +748,18 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
 # CONFIG_FRAME_POINTER is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
 CONFIG_SAMPLES=y
+# CONFIG_SAMPLE_KOBJECT is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 
 #
 # Security options
@@ -738,6 +771,7 @@ CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_AEAD=m
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_SEQIV=m
 CONFIG_CRYPTO_HASH=m
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=m
@@ -745,17 +779,20 @@ CONFIG_CRYPTO_HMAC=m
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=m
-# CONFIG_CRYPTO_SHA1 is not set
+CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
 # CONFIG_CRYPTO_XTS is not set
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CCM=m
 # CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_DES is not set
 CONFIG_CRYPTO_FCRYPT=m
@@ -770,20 +807,22 @@ CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_ANUBIS is not set
 CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SALSA20=m
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
 CONFIG_CRYPTO_CAMELLIA=m
 # CONFIG_CRYPTO_TEST is not set
 CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_HW=y
+CONFIG_ZCRYPT=m
+# CONFIG_ZCRYPT_MONOLITHIC is not set
 # CONFIG_CRYPTO_SHA1_S390 is not set
 # CONFIG_CRYPTO_SHA256_S390 is not set
 # CONFIG_CRYPTO_DES_S390 is not set
 # CONFIG_CRYPTO_AES_S390 is not set
 CONFIG_S390_PRNG=m
-CONFIG_ZCRYPT=m
-# CONFIG_ZCRYPT_MONOLITHIC is not set
 
 #
 # Library routines
@@ -794,5 +833,7 @@ CONFIG_BITREVERSE=m
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=m
 CONFIG_CRC7=m
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
+CONFIG_LZO_COMPRESS=m
+CONFIG_LZO_DECOMPRESS=m
 CONFIG_PLIST=y
index f1e40ca00d8d97c93ff630010f0a69becd9af815..3e1c315b736d70a8ab030fdf82b08a0915a4769c 100644 (file)
@@ -134,6 +134,7 @@ static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
 }
 
 #include <asm/processor.h>
+#include <asm/pgalloc.h>
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/binfmts.h>
@@ -183,6 +184,16 @@ struct elf_prpsinfo32
 #undef start_thread
 #define start_thread                    start_thread31 
 
+static inline void start_thread31(struct pt_regs *regs, unsigned long new_psw,
+                                 unsigned long new_stackp)
+{
+       set_fs(USER_DS);
+       regs->psw.mask  = psw_user32_bits;
+       regs->psw.addr  = new_psw;
+       regs->gprs[15]  = new_stackp;
+       crst_table_downgrade(current->mm, 1UL << 31);
+}
+
 MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries,"
                    " Copyright 2000 IBM Corporation"); 
 MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>");
index 062c3d4c0394b48f4e8bbea8306bc538a03c2758..743d54f0b8dbb01e93c17f51be274bece0005f48 100644 (file)
@@ -1712,3 +1712,23 @@ sys_fallocate_wrapper:
        sllg    %r5,%r6,32              # get high word of 64bit loff_t
        l       %r5,164(%r15)           # get low word of 64bit loff_t
        jg      sys_fallocate
+
+       .globl  sys_timerfd_create_wrapper
+sys_timerfd_create_wrapper:
+       lgfr    %r2,%r2                 # int
+       lgfr    %r3,%r3                 # int
+       jg      sys_timerfd_create
+
+       .globl  compat_sys_timerfd_settime_wrapper
+compat_sys_timerfd_settime_wrapper:
+       lgfr    %r2,%r2                 # int
+       lgfr    %r3,%r3                 # int
+       llgtr   %r4,%r4                 # struct compat_itimerspec *
+       llgtr   %r5,%r5                 # struct compat_itimerspec *
+       jg      compat_sys_timerfd_settime
+
+       .globl  compat_sys_timerfd_gettime_wrapper
+compat_sys_timerfd_gettime_wrapper:
+       lgfr    %r2,%r2                 # int
+       llgtr   %r3,%r3                 # struct compat_itimerspec *
+       jg      compat_sys_timerfd_gettime
index 0e7aca0393070d3ca19538c130b1b5491bdb4681..a6a4729e0e942bcc23a49ad3c7a17f2ac56bbfd8 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
index f9f8779022a0dc5c218b56628b00bd1c49d33c34..290e504061a350502d5e7662d357e02365d19740 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
index 25eac7802fc4dba21980e643fc6fc2f0b76081bf..c87ec687d4c6ab5c68fdb4c803df24c724cdadb8 100644 (file)
@@ -327,3 +327,6 @@ SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper)   /* 315 */
 SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
 NI_SYSCALL                                             /* 317 old sys_timer_fd */
 SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
+SYSCALL(sys_timerfd_create,sys_timerfd_create,sys_timerfd_create_wrapper)
+SYSCALL(sys_timerfd_settime,sys_timerfd_settime,compat_sys_timerfd_settime_wrapper) /* 320 */
+SYSCALL(sys_timerfd_gettime,sys_timerfd_gettime,compat_sys_timerfd_gettime_wrapper)
index a4d29025ddbd9b178197495d955877486b0101f3..60f728aeaf12986ceebbf52c2303805bed0ef378 100644 (file)
@@ -60,6 +60,7 @@ int sysctl_userprocess_debug = 0;
 extern pgm_check_handler_t do_protection_exception;
 extern pgm_check_handler_t do_dat_exception;
 extern pgm_check_handler_t do_monitor_call;
+extern pgm_check_handler_t do_asce_exception;
 
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
 
@@ -730,7 +731,7 @@ void __init trap_init(void)
         pgm_check_table[0x12] = &translation_exception;
         pgm_check_table[0x13] = &special_op_exception;
 #ifdef CONFIG_64BIT
-        pgm_check_table[0x38] = &do_dat_exception;
+       pgm_check_table[0x38] = &do_asce_exception;
        pgm_check_table[0x39] = &do_dat_exception;
        pgm_check_table[0x3A] = &do_dat_exception;
         pgm_check_table[0x3B] = &do_dat_exception;
index 2456b52ed0687e4ac588fa47ae860cc0973636fa..ed13d429a487d01c4cf927b6d7cfc4a7e519faf9 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/s390_ext.h>
+#include <asm/mmu_context.h>
 
 #ifndef CONFIG_64BIT
 #define __FAIL_ADDR_MASK 0x7ffff000
@@ -444,6 +445,45 @@ void __kprobes do_dat_exception(struct pt_regs *regs, unsigned long error_code)
        do_exception(regs, error_code & 0xff, 0);
 }
 
+#ifdef CONFIG_64BIT
+void __kprobes do_asce_exception(struct pt_regs *regs, unsigned long error_code)
+{
+       struct mm_struct *mm;
+       struct vm_area_struct *vma;
+       unsigned long address;
+       int space;
+
+       mm = current->mm;
+       address = S390_lowcore.trans_exc_code & __FAIL_ADDR_MASK;
+       space = check_space(current);
+
+       if (unlikely(space == 0 || in_atomic() || !mm))
+               goto no_context;
+
+       local_irq_enable();
+
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, address);
+       up_read(&mm->mmap_sem);
+
+       if (vma) {
+               update_mm(mm, current);
+               return;
+       }
+
+       /* User mode accesses just cause a SIGSEGV */
+       if (regs->psw.mask & PSW_MASK_PSTATE) {
+               current->thread.prot_addr = address;
+               current->thread.trap_no = error_code;
+               do_sigsegv(regs, error_code, SEGV_MAPERR, address);
+               return;
+       }
+
+no_context:
+       do_no_context(regs, error_code, address);
+}
+#endif
+
 #ifdef CONFIG_PFAULT 
 /*
  * 'pfault' pseudo page faults routines.
index 983ec6ec0e7cc6c85800eea42068196a5fbdbc28..8053245fe259212bedd8075a6560164c5ec977ae 100644 (file)
@@ -112,6 +112,7 @@ void __init paging_init(void)
        init_mm.pgd = swapper_pg_dir;
        S390_lowcore.kernel_asce = __pa(init_mm.pgd) & PAGE_MASK;
 #ifdef CONFIG_64BIT
+       /* A three level page table (4TB) is enough for the kernel space. */
        S390_lowcore.kernel_asce |= _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
        pgd_type = _REGION3_ENTRY_EMPTY;
 #else
@@ -184,7 +185,7 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
                pmd = pmd_offset(pud, address);
                pte = pte_offset_kernel(pmd, address);
                if (!enable) {
-                       ptep_invalidate(address, pte);
+                       ptep_invalidate(&init_mm, address, pte);
                        continue;
                }
                *pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
index 356257c171de77ef60aba46f0af097b39fc97591..5932a824547a51c370e28f05583a5eef12d9931e 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/personality.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <asm/pgalloc.h>
 
 /*
  * Top of mmap area (just below the process stack).
@@ -62,6 +63,8 @@ static inline int mmap_is_legacy(void)
            current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY;
 }
 
+#ifndef CONFIG_64BIT
+
 /*
  * This function, called very early during the creation of a new
  * process VM image, sets up which VM layout function to use:
@@ -84,3 +87,65 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 }
 EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
 
+#else
+
+static unsigned long
+s390_get_unmapped_area(struct file *filp, unsigned long addr,
+               unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+       struct mm_struct *mm = current->mm;
+       int rc;
+
+       addr = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
+       if (addr & ~PAGE_MASK)
+               return addr;
+       if (unlikely(mm->context.asce_limit < addr + len)) {
+               rc = crst_table_upgrade(mm, addr + len);
+               if (rc)
+                       return (unsigned long) rc;
+       }
+       return addr;
+}
+
+static unsigned long
+s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+                         const unsigned long len, const unsigned long pgoff,
+                         const unsigned long flags)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long addr = addr0;
+       int rc;
+
+       addr = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
+       if (addr & ~PAGE_MASK)
+               return addr;
+       if (unlikely(mm->context.asce_limit < addr + len)) {
+               rc = crst_table_upgrade(mm, addr + len);
+               if (rc)
+                       return (unsigned long) rc;
+       }
+       return addr;
+}
+/*
+ * This function, called very early during the creation of a new
+ * process VM image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+       /*
+        * Fall back to the standard layout if the personality
+        * bit is set, or if the expected stack growth is unlimited:
+        */
+       if (mmap_is_legacy()) {
+               mm->mmap_base = TASK_UNMAPPED_BASE;
+               mm->get_unmapped_area = s390_get_unmapped_area;
+               mm->unmap_area = arch_unmap_area;
+       } else {
+               mm->mmap_base = mmap_base();
+               mm->get_unmapped_area = s390_get_unmapped_area_topdown;
+               mm->unmap_area = arch_unmap_area_topdown;
+       }
+}
+EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
+
+#endif
index 019f518cd5a0c014c2e12db2e96274c5f65066d2..fd072013f88ce11658adab8b7db4818a6479f50b 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 
 #ifndef CONFIG_64BIT
 #define ALLOC_ORDER    1
+#define TABLES_PER_PAGE        4
+#define FRAG_MASK      15UL
+#define SECOND_HALVES  10UL
 #else
 #define ALLOC_ORDER    2
+#define TABLES_PER_PAGE        2
+#define FRAG_MASK      3UL
+#define SECOND_HALVES  2UL
 #endif
 
 unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
@@ -45,52 +52,179 @@ unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec)
                }
                page->index = page_to_phys(shadow);
        }
+       spin_lock(&mm->page_table_lock);
+       list_add(&page->lru, &mm->context.crst_list);
+       spin_unlock(&mm->page_table_lock);
        return (unsigned long *) page_to_phys(page);
 }
 
-void crst_table_free(unsigned long *table)
+void crst_table_free(struct mm_struct *mm, unsigned long *table)
 {
        unsigned long *shadow = get_shadow_table(table);
+       struct page *page = virt_to_page(table);
 
+       spin_lock(&mm->page_table_lock);
+       list_del(&page->lru);
+       spin_unlock(&mm->page_table_lock);
        if (shadow)
                free_pages((unsigned long) shadow, ALLOC_ORDER);
        free_pages((unsigned long) table, ALLOC_ORDER);
 }
 
+#ifdef CONFIG_64BIT
+int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
+{
+       unsigned long *table, *pgd;
+       unsigned long entry;
+
+       BUG_ON(limit > (1UL << 53));
+repeat:
+       table = crst_table_alloc(mm, mm->context.noexec);
+       if (!table)
+               return -ENOMEM;
+       spin_lock(&mm->page_table_lock);
+       if (mm->context.asce_limit < limit) {
+               pgd = (unsigned long *) mm->pgd;
+               if (mm->context.asce_limit <= (1UL << 31)) {
+                       entry = _REGION3_ENTRY_EMPTY;
+                       mm->context.asce_limit = 1UL << 42;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_REGION3;
+               } else {
+                       entry = _REGION2_ENTRY_EMPTY;
+                       mm->context.asce_limit = 1UL << 53;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_REGION2;
+               }
+               crst_table_init(table, entry);
+               pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd);
+               mm->pgd = (pgd_t *) table;
+               table = NULL;
+       }
+       spin_unlock(&mm->page_table_lock);
+       if (table)
+               crst_table_free(mm, table);
+       if (mm->context.asce_limit < limit)
+               goto repeat;
+       update_mm(mm, current);
+       return 0;
+}
+
+void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
+{
+       pgd_t *pgd;
+
+       if (mm->context.asce_limit <= limit)
+               return;
+       __tlb_flush_mm(mm);
+       while (mm->context.asce_limit > limit) {
+               pgd = mm->pgd;
+               switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
+               case _REGION_ENTRY_TYPE_R2:
+                       mm->context.asce_limit = 1UL << 42;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_REGION3;
+                       break;
+               case _REGION_ENTRY_TYPE_R3:
+                       mm->context.asce_limit = 1UL << 31;
+                       mm->context.asce_bits = _ASCE_TABLE_LENGTH |
+                                               _ASCE_USER_BITS |
+                                               _ASCE_TYPE_SEGMENT;
+                       break;
+               default:
+                       BUG();
+               }
+               mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
+               crst_table_free(mm, (unsigned long *) pgd);
+       }
+       update_mm(mm, current);
+}
+#endif
+
 /*
  * page table entry allocation/free routines.
  */
-unsigned long *page_table_alloc(int noexec)
+unsigned long *page_table_alloc(struct mm_struct *mm)
 {
-       struct page *page = alloc_page(GFP_KERNEL);
+       struct page *page;
        unsigned long *table;
+       unsigned long bits;
 
-       if (!page)
-               return NULL;
-       page->index = 0;
-       if (noexec) {
-               struct page *shadow = alloc_page(GFP_KERNEL);
-               if (!shadow) {
-                       __free_page(page);
+       bits = mm->context.noexec ? 3UL : 1UL;
+       spin_lock(&mm->page_table_lock);
+       page = NULL;
+       if (!list_empty(&mm->context.pgtable_list)) {
+               page = list_first_entry(&mm->context.pgtable_list,
+                                       struct page, lru);
+               if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
+                       page = NULL;
+       }
+       if (!page) {
+               spin_unlock(&mm->page_table_lock);
+               page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
+               if (!page)
                        return NULL;
-               }
-               table = (unsigned long *) page_to_phys(shadow);
+               pgtable_page_ctor(page);
+               page->flags &= ~FRAG_MASK;
+               table = (unsigned long *) page_to_phys(page);
                clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
-               page->index = (addr_t) table;
+               spin_lock(&mm->page_table_lock);
+               list_add(&page->lru, &mm->context.pgtable_list);
        }
-       pgtable_page_ctor(page);
        table = (unsigned long *) page_to_phys(page);
-       clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+       while (page->flags & bits) {
+               table += 256;
+               bits <<= 1;
+       }
+       page->flags |= bits;
+       if ((page->flags & FRAG_MASK) == ((1UL << TABLES_PER_PAGE) - 1))
+               list_move_tail(&page->lru, &mm->context.pgtable_list);
+       spin_unlock(&mm->page_table_lock);
        return table;
 }
 
-void page_table_free(unsigned long *table)
+void page_table_free(struct mm_struct *mm, unsigned long *table)
 {
-       unsigned long *shadow = get_shadow_pte(table);
+       struct page *page;
+       unsigned long bits;
 
-       pgtable_page_dtor(virt_to_page(table));
-       if (shadow)
-               free_page((unsigned long) shadow);
-       free_page((unsigned long) table);
+       bits = mm->context.noexec ? 3UL : 1UL;
+       bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long);
+       page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+       spin_lock(&mm->page_table_lock);
+       page->flags ^= bits;
+       if (page->flags & FRAG_MASK) {
+               /* Page now has some free pgtable fragments. */
+               list_move(&page->lru, &mm->context.pgtable_list);
+               page = NULL;
+       } else
+               /* All fragments of the 4K page have been freed. */
+               list_del(&page->lru);
+       spin_unlock(&mm->page_table_lock);
+       if (page) {
+               pgtable_page_dtor(page);
+               __free_page(page);
+       }
+}
 
+void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
+{
+       struct page *page;
+
+       spin_lock(&mm->page_table_lock);
+       /* Free shadow region and segment tables. */
+       list_for_each_entry(page, &mm->context.crst_list, lru)
+               if (page->index) {
+                       free_pages((unsigned long) page->index, ALLOC_ORDER);
+                       page->index = 0;
+               }
+       /* "Free" second halves of page tables. */
+       list_for_each_entry(page, &mm->context.pgtable_list, lru)
+               page->flags &= ~SECOND_HALVES;
+       spin_unlock(&mm->page_table_lock);
+       mm->context.noexec = 0;
+       update_mm(mm, tsk);
 }
index 7c1287ccf78864fee054865ef9afd97193497d93..35d90a4720fdcc7570a0dd1d09c231c85c1ab097 100644 (file)
@@ -69,7 +69,19 @@ static void __ref *vmem_alloc_pages(unsigned int order)
        return alloc_bootmem_pages((1 << order) * PAGE_SIZE);
 }
 
-#define vmem_pud_alloc()       ({ BUG(); ((pud_t *) NULL); })
+static inline pud_t *vmem_pud_alloc(void)
+{
+       pud_t *pud = NULL;
+
+#ifdef CONFIG_64BIT
+       pud = vmem_alloc_pages(2);
+       if (!pud)
+               return NULL;
+       pud_val(*pud) = _REGION3_ENTRY_EMPTY;
+       memcpy(pud + 1, pud, (PTRS_PER_PUD - 1)*sizeof(pud_t));
+#endif
+       return pud;
+}
 
 static inline pmd_t *vmem_pmd_alloc(void)
 {
@@ -84,13 +96,18 @@ static inline pmd_t *vmem_pmd_alloc(void)
        return pmd;
 }
 
-static inline pte_t *vmem_pte_alloc(void)
+static pte_t __init_refok *vmem_pte_alloc(void)
 {
-       pte_t *pte = vmem_alloc_pages(0);
+       pte_t *pte;
 
+       if (slab_is_available())
+               pte = (pte_t *) page_table_alloc(&init_mm);
+       else
+               pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t));
        if (!pte)
                return NULL;
-       clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, PAGE_SIZE);
+       clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY,
+                   PTRS_PER_PTE * sizeof(pte_t));
        return pte;
 }
 
@@ -360,6 +377,9 @@ void __init vmem_map_init(void)
 {
        int i;
 
+       INIT_LIST_HEAD(&init_mm.context.crst_list);
+       INIT_LIST_HEAD(&init_mm.context.pgtable_list);
+       init_mm.context.noexec = 0;
        NODE_DATA(0)->node_mem_map = VMEM_MAP;
        for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
                vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
index 6e035d1cf7895663f5c51eed1b4167f16dd1d759..d87d4bf88803815ffcb812afe36edcc258cc8cb4 100644 (file)
@@ -8,6 +8,7 @@ mainmenu "Linux/SuperH Kernel Configuration"
 config SUPERH
        def_bool y
        select EMBEDDED
+       select HAVE_IDE
        select HAVE_OPROFILE
        help
          The SuperH is a RISC processor targeted for use in embedded systems
index 7c674a3503b66c8aa2ced1896bc3df6e2a6e7999..c40343c5492085c203bbb553d113a970ec65c918 100644 (file)
@@ -69,6 +69,7 @@ config NR_CPUS
 config SPARC
        bool
        default y
+       select HAVE_IDE
        select HAVE_OPROFILE
 
 # Identify this as a Sparc32 build
index bb36f6eadfeeec9c7e96ff13c9e1f4ada9b6dd3d..ed14df7116e969bc9755d083fad646f508feaf2f 100644 (file)
@@ -1,21 +1,18 @@
-/* $Id: errtbls.c,v 1.2 1995/11/25 00:57:55 davem Exp $
- * errtbls.c: Error number conversion tables between various syscall
- *            OS semantics.
+/* errtbls.c: Error number conversion tables.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
  *
  * Based upon preliminary work which is:
  *
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
-#include <asm/bsderrno.h>        /* NetBSD (bsd4.4) errnos */
 #include <asm/solerrno.h>        /* Solaris errnos */
 
-/* Here are tables which convert between Linux/SunOS error number
- * values to the equivalent in other OSs.  Note that since the Linux
- * ones have been set up to match exactly those of SunOS, no
- * translation table is needed for that OS.
+/* Here is the table which converts between Linux error number values
+ * to the equivalent under Solaris.  Note that since the Linux ones
+ * have been set up to match exactly those of SunOS, no translation
+ * table is needed for that OS.
  */
 
 int solaris_errno[] = {
@@ -145,132 +142,3 @@ int solaris_errno[] = {
        SOL_ELIBMAX,
        SOL_ELIBSCN,
 };
-
-int netbsd_errno[] = {
-       0,
-       BSD_EPERM,
-       BSD_ENOENT,
-       BSD_ESRCH,
-       BSD_EINTR,
-       BSD_EIO,
-       BSD_ENXIO,
-       BSD_E2BIG,
-       BSD_ENOEXEC,
-       BSD_EBADF,
-       BSD_ECHILD,
-       BSD_EAGAIN,
-       BSD_ENOMEM,
-       BSD_EACCES,
-       BSD_EFAULT,
-       BSD_NOTBLK,
-       BSD_EBUSY,
-       BSD_EEXIST,
-       BSD_EXDEV,
-       BSD_ENODEV,
-       BSD_ENOTDIR,
-       BSD_EISDIR,
-       BSD_EINVAL,
-       BSD_ENFILE,
-       BSD_EMFILE,
-       BSD_ENOTTY,
-       BSD_ETXTBSY,
-       BSD_EFBIG,
-       BSD_ENOSPC,
-       BSD_ESPIPE,
-       BSD_EROFS,
-       BSD_EMLINK,
-       BSD_EPIPE,
-       BSD_EDOM,
-       BSD_ERANGE,
-       BSD_EWOULDBLOCK,
-       BSD_EINPROGRESS,
-       BSD_EALREADY,
-       BSD_ENOTSOCK,
-       BSD_EDESTADDRREQ,
-       BSD_EMSGSIZE,
-       BSD_EPROTOTYPE,
-       BSD_ENOPROTOOPT,
-       BSD_EPROTONOSUPPORT,
-       BSD_ESOCKTNOSUPPORT,
-       BSD_EOPNOTSUPP,
-       BSD_EPFNOSUPPORT,
-       BSD_EAFNOSUPPORT,
-       BSD_EADDRINUSE,
-       BSD_EADDRNOTAVAIL,
-       BSD_ENETDOWN,
-       BSD_ENETUNREACH,
-       BSD_ENETRESET,
-       BSD_ECONNABORTED,
-       BSD_ECONNRESET,
-       BSD_ENOBUFS,
-       BSD_EISCONN,
-       BSD_ENOTONN,
-       BSD_ESHUTDOWN,
-       BSD_ETOOMANYREFS,
-       BSD_ETIMEDOUT,
-       BSD_ECONNREFUSED,
-       BSD_ELOOP,
-       BSD_ENAMETOOLONG,
-       BSD_EHOSTDOWN,
-       BSD_EHOSTUNREACH,
-       BSD_ENOTEMPTY,
-       BSD_EPROCLIM,
-       BSD_EUSERS,
-       BSD_EDQUOT,
-       BSD_ESTALE,
-       BSD_EREMOTE,
-       BSD_ENOSTR,
-       BSD_ETIME,
-       BSD_ENOSR,
-       BSD_ENOMSG,
-       BSD_EBADMSG,
-       BSD_IDRM,
-       BSD_EDEADLK,
-       BSD_ENOLCK,
-       BSD_ENONET,
-       BSD_ERREMOTE,
-       BSD_ENOLINK,
-       BSD_EADV,
-       BSD_ESRMNT,
-       BSD_ECOMM,
-       BSD_EPROTO,
-       BSD_EMULTIHOP,
-       BSD_EINVAL,    /* EDOTDOT XXX??? */
-       BSD_REMCHG,
-       BSD_NOSYS,
-       BSD_STRPIPE,
-       BSD_EOVERFLOW,
-       BSD_EBADFD,
-       BSD_ECHRNG,
-       BSD_EL2NSYNC,
-       BSD_EL3HLT,
-       BSD_EL3RST,
-       BSD_NRNG,
-       BSD_EUNATCH,
-       BSD_ENOCSI,
-       BSD_EL2HLT,
-       BSD_EBADE,
-       BSD_EBADR,
-       BSD_EXFULL,
-       BSD_ENOANO,
-       BSD_EBADRQC,
-       BSD_EBADSLT,
-       BSD_EDEADLOCK,
-       BSD_EBFONT,
-       BSD_ELIBEXEC,
-       BSD_ENODATA,
-       BSD_ELIBBAD,
-       BSD_ENOPKG,
-       BSD_ELIBACC,
-       BSD_ENOTUNIQ,
-       BSD_ERESTART,
-       BSD_EUCLEAN,
-       BSD_ENOTNAM,
-       BSD_ENAVAIL,
-       BSD_EISNAM,
-       BSD_EREMOTEIO,
-       BSD_EILSEQ,
-       BSD_ELIBMAX,
-       BSD_ELIBSCN,
-};
-
index 3ea000d15e3a29b8d7273e7aad0e53667356e5df..cc4c235c4f592e5e193429bfb346656287c8092f 100644 (file)
@@ -584,30 +584,3 @@ static int __init of_debug(char *str)
 }
 
 __setup("of_debug=", of_debug);
-
-struct of_device* of_platform_device_create(struct device_node *np,
-                                           const char *bus_id,
-                                           struct device *parent,
-                                           struct bus_type *bus)
-{
-       struct of_device *dev;
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return NULL;
-
-       dev->dev.parent = parent;
-       dev->dev.bus = bus;
-       dev->dev.release = of_release_dev;
-
-       strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-
-       if (of_device_register(dev) != 0) {
-               kfree(dev);
-               return NULL;
-       }
-
-       return dev;
-}
-
-EXPORT_SYMBOL(of_platform_device_create);
index 216147d6e61f6882d8050c161d356c4bd6f15bec..b1002c60719615bca22b0c4161e0d60afb959d58 100644 (file)
@@ -89,6 +89,10 @@ SECTIONS
        .data.cacheline_aligned : {
                *(.data.cacheline_aligned)
        }
+       . = ALIGN(32);
+       .data.read_mostly : {
+               *(.data.read_mostly)
+       }
 
        __bss_start = .;
        .sbss : {
index b810f2b7526a605b1f783c021190bc8304c7ac0f..3af378ddb6ae8008db5619074414b489165370a6 100644 (file)
@@ -14,6 +14,7 @@ config SPARC
 config SPARC64
        bool
        default y
+       select HAVE_IDE
        help
          SPARC is a family of RISC microprocessors designed and marketed by
          Sun Microsystems, incorporated.  This port covers the newer 64-bit
@@ -40,6 +41,10 @@ config MMU
        bool
        default y
 
+config IOMMU_HELPER
+       bool
+       default y
+
 config QUICKLIST
        bool
        default y
index 5623a4d59dff0a642ca0e468527214d9b456384a..d3276ebcfb4715a118268a8cb6c92640a33afcca 100644 (file)
@@ -1,6 +1,6 @@
 /* iommu.c: Generic sparc64 IOMMU support.
  *
- * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
  */
 
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
+#include <linux/iommu-helper.h>
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
@@ -41,7 +42,7 @@
                               "i" (ASI_PHYS_BYPASS_EC_E))
 
 /* Must be invoked under the IOMMU lock. */
-static void __iommu_flushall(struct iommu *iommu)
+static void iommu_flushall(struct iommu *iommu)
 {
        if (iommu->iommu_flushinv) {
                iommu_write(iommu->iommu_flushinv, ~(u64)0);
@@ -83,54 +84,91 @@ static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte)
        iopte_val(*iopte) = val;
 }
 
-/* Based largely upon the ppc64 iommu allocator.  */
-static long arena_alloc(struct iommu *iommu, unsigned long npages)
+/* Based almost entirely upon the ppc64 iommu allocator.  If you use the 'handle'
+ * facility it must all be done in one pass while under the iommu lock.
+ *
+ * On sun4u platforms, we only flush the IOMMU once every time we've passed
+ * over the entire page table doing allocations.  Therefore we only ever advance
+ * the hint and cannot backtrack it.
+ */
+unsigned long iommu_range_alloc(struct device *dev,
+                               struct iommu *iommu,
+                               unsigned long npages,
+                               unsigned long *handle)
 {
+       unsigned long n, end, start, limit, boundary_size;
        struct iommu_arena *arena = &iommu->arena;
-       unsigned long n, i, start, end, limit;
-       int pass;
+       int pass = 0;
+
+       /* This allocator was derived from x86_64's bit string search */
+
+       /* Sanity check */
+       if (unlikely(npages == 0)) {
+               if (printk_ratelimit())
+                       WARN_ON(1);
+               return DMA_ERROR_CODE;
+       }
+
+       if (handle && *handle)
+               start = *handle;
+       else
+               start = arena->hint;
 
        limit = arena->limit;
-       start = arena->hint;
-       pass = 0;
 
-again:
-       n = find_next_zero_bit(arena->map, limit, start);
-       end = n + npages;
-       if (unlikely(end >= limit)) {
+       /* The case below can happen if we have a small segment appended
+        * to a large, or when the previous alloc was at the very end of
+        * the available space. If so, go back to the beginning and flush.
+        */
+       if (start >= limit) {
+               start = 0;
+               if (iommu->flush_all)
+                       iommu->flush_all(iommu);
+       }
+
+ again:
+
+       if (dev)
+               boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+                                     1 << IO_PAGE_SHIFT);
+       else
+               boundary_size = ALIGN(1UL << 32, 1 << IO_PAGE_SHIFT);
+
+       n = iommu_area_alloc(arena->map, limit, start, npages, 0,
+                            boundary_size >> IO_PAGE_SHIFT, 0);
+       if (n == -1) {
                if (likely(pass < 1)) {
-                       limit = start;
+                       /* First failure, rescan from the beginning.  */
                        start = 0;
-                       __iommu_flushall(iommu);
+                       if (iommu->flush_all)
+                               iommu->flush_all(iommu);
                        pass++;
                        goto again;
                } else {
-                       /* Scanned the whole thing, give up. */
-                       return -1;
-               }
-       }
-
-       for (i = n; i < end; i++) {
-               if (test_bit(i, arena->map)) {
-                       start = i + 1;
-                       goto again;
+                       /* Second failure, give up */
+                       return DMA_ERROR_CODE;
                }
        }
 
-       for (i = n; i < end; i++)
-               __set_bit(i, arena->map);
+       end = n + npages;
 
        arena->hint = end;
 
+       /* Update handle for SG allocations */
+       if (handle)
+               *handle = end;
+
        return n;
 }
 
-static void arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
+void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long npages)
 {
-       unsigned long i;
+       struct iommu_arena *arena = &iommu->arena;
+       unsigned long entry;
 
-       for (i = base; i < (base + npages); i++)
-               __clear_bit(i, arena->map);
+       entry = (dma_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
+
+       iommu_area_free(arena->map, entry, npages);
 }
 
 int iommu_table_init(struct iommu *iommu, int tsbsize,
@@ -156,6 +194,9 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
        }
        iommu->arena.limit = num_tsb_entries;
 
+       if (tlb_type != hypervisor)
+               iommu->flush_all = iommu_flushall;
+
        /* Allocate and initialize the dummy page which we
         * set inactive IO PTEs to point to.
         */
@@ -192,22 +233,18 @@ out_free_map:
        return -ENOMEM;
 }
 
-static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
+static inline iopte_t *alloc_npages(struct device *dev, struct iommu *iommu,
+                                   unsigned long npages)
 {
-       long entry;
+       unsigned long entry;
 
-       entry = arena_alloc(iommu, npages);
-       if (unlikely(entry < 0))
+       entry = iommu_range_alloc(dev, iommu, npages, NULL);
+       if (unlikely(entry == DMA_ERROR_CODE))
                return NULL;
 
        return iommu->page_table + entry;
 }
 
-static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
-{
-       arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
-}
-
 static int iommu_alloc_ctx(struct iommu *iommu)
 {
        int lowest = iommu->ctx_lowest_free;
@@ -258,7 +295,7 @@ static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
        iommu = dev->archdata.iommu;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
+       iopte = alloc_npages(dev, iommu, size >> IO_PAGE_SHIFT);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        if (unlikely(iopte == NULL)) {
@@ -296,7 +333,7 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,
 
        spin_lock_irqsave(&iommu->lock, flags);
 
-       free_npages(iommu, dvma - iommu->page_table_map_base, npages);
+       iommu_range_free(iommu, dvma, npages);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 
@@ -327,7 +364,7 @@ static dma_addr_t dma_4u_map_single(struct device *dev, void *ptr, size_t sz,
        npages >>= IO_PAGE_SHIFT;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       base = alloc_npages(iommu, npages);
+       base = alloc_npages(dev, iommu, npages);
        ctx = 0;
        if (iommu->iommu_ctxflush)
                ctx = iommu_alloc_ctx(iommu);
@@ -465,7 +502,7 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
        for (i = 0; i < npages; i++)
                iopte_make_dummy(iommu, base + i);
 
-       free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
+       iommu_range_free(iommu, bus_addr, npages);
 
        iommu_free_ctx(iommu, ctx);
 
@@ -475,124 +512,209 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
 static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
                         int nelems, enum dma_data_direction direction)
 {
-       unsigned long flags, ctx, i, npages, iopte_protection;
-       struct scatterlist *sg;
+       struct scatterlist *s, *outs, *segstart;
+       unsigned long flags, handle, prot, ctx;
+       dma_addr_t dma_next = 0, dma_addr;
+       unsigned int max_seg_size;
+       int outcount, incount, i;
        struct strbuf *strbuf;
        struct iommu *iommu;
-       iopte_t *base;
-       u32 dma_base;
-
-       /* Fast path single entry scatterlists. */
-       if (nelems == 1) {
-               sglist->dma_address =
-                       dma_4u_map_single(dev, sg_virt(sglist),
-                                         sglist->length, direction);
-               if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
-                       return 0;
-               sglist->dma_length = sglist->length;
-               return 1;
-       }
+
+       BUG_ON(direction == DMA_NONE);
 
        iommu = dev->archdata.iommu;
        strbuf = dev->archdata.stc;
-
-       if (unlikely(direction == DMA_NONE))
-               goto bad_no_ctx;
-
-       npages = calc_npages(sglist, nelems);
+       if (nelems == 0 || !iommu)
+               return 0;
 
        spin_lock_irqsave(&iommu->lock, flags);
 
-       base = alloc_npages(iommu, npages);
        ctx = 0;
        if (iommu->iommu_ctxflush)
                ctx = iommu_alloc_ctx(iommu);
 
-       spin_unlock_irqrestore(&iommu->lock, flags);
-
-       if (base == NULL)
-               goto bad;
-
-       dma_base = iommu->page_table_map_base +
-               ((base - iommu->page_table) << IO_PAGE_SHIFT);
-
        if (strbuf->strbuf_enabled)
-               iopte_protection = IOPTE_STREAMING(ctx);
+               prot = IOPTE_STREAMING(ctx);
        else
-               iopte_protection = IOPTE_CONSISTENT(ctx);
+               prot = IOPTE_CONSISTENT(ctx);
        if (direction != DMA_TO_DEVICE)
-               iopte_protection |= IOPTE_WRITE;
-
-       for_each_sg(sglist, sg, nelems, i) {
-               unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
-               unsigned long slen = sg->length;
-               unsigned long this_npages;
+               prot |= IOPTE_WRITE;
+
+       outs = s = segstart = &sglist[0];
+       outcount = 1;
+       incount = nelems;
+       handle = 0;
+
+       /* Init first segment length for backout at failure */
+       outs->dma_length = 0;
+
+       max_seg_size = dma_get_max_seg_size(dev);
+       for_each_sg(sglist, s, nelems, i) {
+               unsigned long paddr, npages, entry, slen;
+               iopte_t *base;
+
+               slen = s->length;
+               /* Sanity check */
+               if (slen == 0) {
+                       dma_next = 0;
+                       continue;
+               }
+               /* Allocate iommu entries for that segment */
+               paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+               npages = iommu_num_pages(paddr, slen);
+               entry = iommu_range_alloc(dev, iommu, npages, &handle);
+
+               /* Handle failure */
+               if (unlikely(entry == DMA_ERROR_CODE)) {
+                       if (printk_ratelimit())
+                               printk(KERN_INFO "iommu_alloc failed, iommu %p paddr %lx"
+                                      " npages %lx\n", iommu, paddr, npages);
+                       goto iommu_map_failed;
+               }
 
-               this_npages = iommu_num_pages(paddr, slen);
+               base = iommu->page_table + entry;
 
-               sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
-               sg->dma_length = slen;
+               /* Convert entry to a dma_addr_t */
+               dma_addr = iommu->page_table_map_base +
+                       (entry << IO_PAGE_SHIFT);
+               dma_addr |= (s->offset & ~IO_PAGE_MASK);
 
+               /* Insert into HW table */
                paddr &= IO_PAGE_MASK;
-               while (this_npages--) {
-                       iopte_val(*base) = iopte_protection | paddr;
-
+               while (npages--) {
+                       iopte_val(*base) = prot | paddr;
                        base++;
                        paddr += IO_PAGE_SIZE;
-                       dma_base += IO_PAGE_SIZE;
                }
+
+               /* If we are in an open segment, try merging */
+               if (segstart != s) {
+                       /* We cannot merge if:
+                        * - allocated dma_addr isn't contiguous to previous allocation
+                        */
+                       if ((dma_addr != dma_next) ||
+                           (outs->dma_length + s->length > max_seg_size)) {
+                               /* Can't merge: create a new segment */
+                               segstart = s;
+                               outcount++;
+                               outs = sg_next(outs);
+                       } else {
+                               outs->dma_length += s->length;
+                       }
+               }
+
+               if (segstart == s) {
+                       /* This is a new segment, fill entries */
+                       outs->dma_address = dma_addr;
+                       outs->dma_length = slen;
+               }
+
+               /* Calculate next page pointer for contiguous check */
+               dma_next = dma_addr + slen;
        }
 
-       return nelems;
+       spin_unlock_irqrestore(&iommu->lock, flags);
+
+       if (outcount < incount) {
+               outs = sg_next(outs);
+               outs->dma_address = DMA_ERROR_CODE;
+               outs->dma_length = 0;
+       }
+
+       return outcount;
+
+iommu_map_failed:
+       for_each_sg(sglist, s, nelems, i) {
+               if (s->dma_length != 0) {
+                       unsigned long vaddr, npages, entry, i;
+                       iopte_t *base;
+
+                       vaddr = s->dma_address & IO_PAGE_MASK;
+                       npages = iommu_num_pages(s->dma_address, s->dma_length);
+                       iommu_range_free(iommu, vaddr, npages);
+
+                       entry = (vaddr - iommu->page_table_map_base)
+                               >> IO_PAGE_SHIFT;
+                       base = iommu->page_table + entry;
+
+                       for (i = 0; i < npages; i++)
+                               iopte_make_dummy(iommu, base + i);
+
+                       s->dma_address = DMA_ERROR_CODE;
+                       s->dma_length = 0;
+               }
+               if (s == outs)
+                       break;
+       }
+       spin_unlock_irqrestore(&iommu->lock, flags);
 
-bad:
-       iommu_free_ctx(iommu, ctx);
-bad_no_ctx:
-       if (printk_ratelimit())
-               WARN_ON(1);
        return 0;
 }
 
+/* If contexts are being used, they are the same in all of the mappings
+ * we make for a particular SG.
+ */
+static unsigned long fetch_sg_ctx(struct iommu *iommu, struct scatterlist *sg)
+{
+       unsigned long ctx = 0;
+
+       if (iommu->iommu_ctxflush) {
+               iopte_t *base;
+               u32 bus_addr;
+
+               bus_addr = sg->dma_address & IO_PAGE_MASK;
+               base = iommu->page_table +
+                       ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+
+               ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+       }
+       return ctx;
+}
+
 static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
                            int nelems, enum dma_data_direction direction)
 {
-       unsigned long flags, ctx, i, npages;
+       unsigned long flags, ctx;
+       struct scatterlist *sg;
        struct strbuf *strbuf;
        struct iommu *iommu;
-       iopte_t *base;
-       u32 bus_addr;
 
-       if (unlikely(direction == DMA_NONE)) {
-               if (printk_ratelimit())
-                       WARN_ON(1);
-       }
+       BUG_ON(direction == DMA_NONE);
 
        iommu = dev->archdata.iommu;
        strbuf = dev->archdata.stc;
 
-       bus_addr = sglist->dma_address & IO_PAGE_MASK;
+       ctx = fetch_sg_ctx(iommu, sglist);
 
-       npages = calc_npages(sglist, nelems);
+       spin_lock_irqsave(&iommu->lock, flags);
 
-       base = iommu->page_table +
-               ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+       sg = sglist;
+       while (nelems--) {
+               dma_addr_t dma_handle = sg->dma_address;
+               unsigned int len = sg->dma_length;
+               unsigned long npages, entry;
+               iopte_t *base;
+               int i;
 
-       spin_lock_irqsave(&iommu->lock, flags);
+               if (!len)
+                       break;
+               npages = iommu_num_pages(dma_handle, len);
+               iommu_range_free(iommu, dma_handle, npages);
 
-       /* Record the context, if any. */
-       ctx = 0;
-       if (iommu->iommu_ctxflush)
-               ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+               entry = ((dma_handle - iommu->page_table_map_base)
+                        >> IO_PAGE_SHIFT);
+               base = iommu->page_table + entry;
 
-       /* Step 1: Kick data out of streaming buffers if necessary. */
-       if (strbuf->strbuf_enabled)
-               strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+               dma_handle &= IO_PAGE_MASK;
+               if (strbuf->strbuf_enabled)
+                       strbuf_flush(strbuf, iommu, dma_handle, ctx,
+                                    npages, direction);
 
-       /* Step 2: Clear out the TSB entries. */
-       for (i = 0; i < npages; i++)
-               iopte_make_dummy(iommu, base + i);
+               for (i = 0; i < npages; i++)
+                       iopte_make_dummy(iommu, base + i);
 
-       free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
+               sg = sg_next(sg);
+       }
 
        iommu_free_ctx(iommu, ctx);
 
index 4b5cafa2877a4330b6f3f23d46be309009f2a2cc..0713bd58499c1de49d2650877c60f59437b66fd3 100644 (file)
@@ -1,9 +1,11 @@
-/* $Id: iommu_common.h,v 1.5 2001/12/11 09:41:01 davem Exp $
- * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
+/* iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
  *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2008 David S. Miller (davem@davemloft.net)
  */
 
+#ifndef _IOMMU_COMMON_H
+#define _IOMMU_COMMON_H
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/sched.h>
@@ -56,21 +58,12 @@ static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems)
        return npages;
 }
 
-/* You are _strongly_ advised to enable the following debugging code
- * any time you make changes to the sg code below, run it for a while
- * with filesystems mounted read-only before buying the farm... -DaveM
- */
-#undef VERIFY_SG
-
-#ifdef VERIFY_SG
-extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages);
-#endif
-
-/* Two addresses are "virtually contiguous" if and only if:
- * 1) They are equal, or...
- * 2) They are both on a page boundary
- */
-#define VCONTIG(__X, __Y)      (((__X) == (__Y)) || \
-                                (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
+extern unsigned long iommu_range_alloc(struct device *dev,
+                                      struct iommu *iommu,
+                                      unsigned long npages,
+                                      unsigned long *handle);
+extern void iommu_range_free(struct iommu *iommu,
+                            dma_addr_t dma_addr,
+                            unsigned long npages);
 
-extern unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents);
+#endif /* _IOMMU_COMMON_H */
index d94f901d321e91423e25f26fee5ccf3f57907c8f..34fc3ddd50026dbbc802ded84b7329382f76c17f 100644 (file)
@@ -480,8 +480,117 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
        return 0;
 }
 
-/* architecture specific initialization */
-int arch_init_kprobes(void)
+/* Called with kretprobe_lock held.  The value stored in the return
+ * address register is actually 2 instructions before where the
+ * callee will return to.  Sequences usually look something like this
+ *
+ *             call    some_function   <--- return register points here
+ *              nop                    <--- call delay slot
+ *             whatever                <--- where callee returns to
+ *
+ * To keep trampoline_probe_handler logic simpler, we normalize the
+ * value kept in ri->ret_addr so we don't need to keep adjusting it
+ * back and forth.
+ */
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+                                     struct pt_regs *regs)
+{
+       ri->ret_addr = (kprobe_opcode_t *)(regs->u_regs[UREG_RETPC] + 8);
+
+       /* Replace the return addr with trampoline addr */
+       regs->u_regs[UREG_RETPC] =
+               ((unsigned long)kretprobe_trampoline) - 8;
+}
+
+/*
+ * Called when the probe at kretprobe trampoline is hit
+ */
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct kretprobe_instance *ri = NULL;
+       struct hlist_head *head, empty_rp;
+       struct hlist_node *node, *tmp;
+       unsigned long flags, orig_ret_address = 0;
+       unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+
+       INIT_HLIST_HEAD(&empty_rp);
+       spin_lock_irqsave(&kretprobe_lock, flags);
+       head = kretprobe_inst_table_head(current);
+
+       /*
+        * It is possible to have multiple instances associated with a given
+        * task either because an multiple functions in the call path
+        * have a return probe installed on them, and/or more then one return
+        * return probe was registered for a target function.
+        *
+        * We can handle this because:
+        *     - instances are always inserted at the head of the list
+        *     - when multiple return probes are registered for the same
+        *       function, the first instance's ret_addr will point to the
+        *       real return address, and all the rest will point to
+        *       kretprobe_trampoline
+        */
+       hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+               if (ri->task != current)
+                       /* another task is sharing our hash bucket */
+                       continue;
+
+               if (ri->rp && ri->rp->handler)
+                       ri->rp->handler(ri, regs);
+
+               orig_ret_address = (unsigned long)ri->ret_addr;
+               recycle_rp_inst(ri, &empty_rp);
+
+               if (orig_ret_address != trampoline_address)
+                       /*
+                        * This is the real return address. Any other
+                        * instances associated with this task are for
+                        * other calls deeper on the call stack
+                        */
+                       break;
+       }
+
+       kretprobe_assert(ri, orig_ret_address, trampoline_address);
+       regs->tpc = orig_ret_address;
+       regs->tnpc = orig_ret_address + 4;
+
+       reset_current_kprobe();
+       spin_unlock_irqrestore(&kretprobe_lock, flags);
+       preempt_enable_no_resched();
+
+       hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
+               hlist_del(&ri->hlist);
+               kfree(ri);
+       }
+       /*
+        * By returning a non-zero value, we are telling
+        * kprobe_handler() that we don't want the post_handler
+        * to run (and have re-enabled preemption)
+        */
+       return 1;
+}
+
+void kretprobe_trampoline_holder(void)
+{
+       asm volatile(".global kretprobe_trampoline\n"
+                    "kretprobe_trampoline:\n"
+                    "\tnop\n"
+                    "\tnop\n");
+}
+static struct kprobe trampoline_p = {
+       .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+       .pre_handler = trampoline_probe_handler
+};
+
+int __init arch_init_kprobes(void)
 {
+       return register_kprobe(&trampoline_p);
+}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline)
+               return 1;
+
        return 0;
 }
index fc5c0cc793b8f3a403307c9366b3be0a4fdc84da..0fd9db95b896415773e0208f390457b4c263b19d 100644 (file)
@@ -868,29 +868,3 @@ static int __init of_debug(char *str)
 }
 
 __setup("of_debug=", of_debug);
-
-struct of_device* of_platform_device_create(struct device_node *np,
-                                           const char *bus_id,
-                                           struct device *parent,
-                                           struct bus_type *bus)
-{
-       struct of_device *dev;
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return NULL;
-
-       dev->dev.parent = parent;
-       dev->dev.bus = bus;
-       dev->dev.release = of_release_dev;
-
-       strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-
-       if (of_device_register(dev) != 0) {
-               kfree(dev);
-               return NULL;
-       }
-
-       return dev;
-}
-EXPORT_SYMBOL(of_platform_device_create);
index 61baf8dc095e2d2631e7958b4473d419524e47d9..ddca6c6c0b492709193e1a3c8a86dcb30f884fbf 100644 (file)
@@ -1,6 +1,6 @@
 /* pci_sun4v.c: SUN4V specific PCI controller support.
  *
- * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2006, 2007, 2008 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/kernel.h>
@@ -89,6 +89,17 @@ static long iommu_batch_flush(struct iommu_batch *p)
        return 0;
 }
 
+static inline void iommu_batch_new_entry(unsigned long entry)
+{
+       struct iommu_batch *p = &__get_cpu_var(iommu_batch);
+
+       if (p->entry + p->npages == entry)
+               return;
+       if (p->entry != ~0UL)
+               iommu_batch_flush(p);
+       p->entry = entry;
+}
+
 /* Interrupts must be disabled.  */
 static inline long iommu_batch_add(u64 phys_page)
 {
@@ -113,54 +124,6 @@ static inline long iommu_batch_end(void)
        return iommu_batch_flush(p);
 }
 
-static long arena_alloc(struct iommu_arena *arena, unsigned long npages)
-{
-       unsigned long n, i, start, end, limit;
-       int pass;
-
-       limit = arena->limit;
-       start = arena->hint;
-       pass = 0;
-
-again:
-       n = find_next_zero_bit(arena->map, limit, start);
-       end = n + npages;
-       if (unlikely(end >= limit)) {
-               if (likely(pass < 1)) {
-                       limit = start;
-                       start = 0;
-                       pass++;
-                       goto again;
-               } else {
-                       /* Scanned the whole thing, give up. */
-                       return -1;
-               }
-       }
-
-       for (i = n; i < end; i++) {
-               if (test_bit(i, arena->map)) {
-                       start = i + 1;
-                       goto again;
-               }
-       }
-
-       for (i = n; i < end; i++)
-               __set_bit(i, arena->map);
-
-       arena->hint = end;
-
-       return n;
-}
-
-static void arena_free(struct iommu_arena *arena, unsigned long base,
-                      unsigned long npages)
-{
-       unsigned long i;
-
-       for (i = base; i < (base + npages); i++)
-               __clear_bit(i, arena->map);
-}
-
 static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
                                   dma_addr_t *dma_addrp, gfp_t gfp)
 {
@@ -185,11 +148,11 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
        iommu = dev->archdata.iommu;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       entry = arena_alloc(&iommu->arena, npages);
+       entry = iommu_range_alloc(dev, iommu, npages, NULL);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
-       if (unlikely(entry < 0L))
-               goto arena_alloc_fail;
+       if (unlikely(entry == DMA_ERROR_CODE))
+               goto range_alloc_fail;
 
        *dma_addrp = (iommu->page_table_map_base +
                      (entry << IO_PAGE_SHIFT));
@@ -219,10 +182,10 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 iommu_map_fail:
        /* Interrupts are disabled.  */
        spin_lock(&iommu->lock);
-       arena_free(&iommu->arena, entry, npages);
+       iommu_range_free(iommu, *dma_addrp, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
-arena_alloc_fail:
+range_alloc_fail:
        free_pages(first_page, order);
        return NULL;
 }
@@ -243,7 +206,7 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
 
        spin_lock_irqsave(&iommu->lock, flags);
 
-       arena_free(&iommu->arena, entry, npages);
+       iommu_range_free(iommu, dvma, npages);
 
        do {
                unsigned long num;
@@ -281,10 +244,10 @@ static dma_addr_t dma_4v_map_single(struct device *dev, void *ptr, size_t sz,
        npages >>= IO_PAGE_SHIFT;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       entry = arena_alloc(&iommu->arena, npages);
+       entry = iommu_range_alloc(dev, iommu, npages, NULL);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
-       if (unlikely(entry < 0L))
+       if (unlikely(entry == DMA_ERROR_CODE))
                goto bad;
 
        bus_addr = (iommu->page_table_map_base +
@@ -319,7 +282,7 @@ bad:
 iommu_map_fail:
        /* Interrupts are disabled.  */
        spin_lock(&iommu->lock);
-       arena_free(&iommu->arena, entry, npages);
+       iommu_range_free(iommu, bus_addr, npages);
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        return DMA_ERROR_CODE;
@@ -350,9 +313,9 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
 
        spin_lock_irqsave(&iommu->lock, flags);
 
-       entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
-       arena_free(&iommu->arena, entry, npages);
+       iommu_range_free(iommu, bus_addr, npages);
 
+       entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
        do {
                unsigned long num;
 
@@ -368,88 +331,131 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
 static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
                         int nelems, enum dma_data_direction direction)
 {
-       unsigned long flags, npages, i, prot;
-       struct scatterlist *sg;
+       struct scatterlist *s, *outs, *segstart;
+       unsigned long flags, handle, prot;
+       dma_addr_t dma_next = 0, dma_addr;
+       unsigned int max_seg_size;
+       int outcount, incount, i;
        struct iommu *iommu;
-       long entry, err;
-       u32 dma_base;
-
-       /* Fast path single entry scatterlists. */
-       if (nelems == 1) {
-               sglist->dma_address =
-                       dma_4v_map_single(dev, sg_virt(sglist),
-                                         sglist->length, direction);
-               if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
-                       return 0;
-               sglist->dma_length = sglist->length;
-               return 1;
-       }
+       long err;
+
+       BUG_ON(direction == DMA_NONE);
 
        iommu = dev->archdata.iommu;
+       if (nelems == 0 || !iommu)
+               return 0;
        
-       if (unlikely(direction == DMA_NONE))
-               goto bad;
-
-       npages = calc_npages(sglist, nelems);
+       prot = HV_PCI_MAP_ATTR_READ;
+       if (direction != DMA_TO_DEVICE)
+               prot |= HV_PCI_MAP_ATTR_WRITE;
 
-       spin_lock_irqsave(&iommu->lock, flags);
-       entry = arena_alloc(&iommu->arena, npages);
-       spin_unlock_irqrestore(&iommu->lock, flags);
+       outs = s = segstart = &sglist[0];
+       outcount = 1;
+       incount = nelems;
+       handle = 0;
 
-       if (unlikely(entry < 0L))
-               goto bad;
+       /* Init first segment length for backout at failure */
+       outs->dma_length = 0;
 
-       dma_base = iommu->page_table_map_base +
-               (entry << IO_PAGE_SHIFT);
+       spin_lock_irqsave(&iommu->lock, flags);
 
-       prot = HV_PCI_MAP_ATTR_READ;
-       if (direction != DMA_TO_DEVICE)
-               prot |= HV_PCI_MAP_ATTR_WRITE;
+       iommu_batch_start(dev, prot, ~0UL);
 
-       local_irq_save(flags);
+       max_seg_size = dma_get_max_seg_size(dev);
+       for_each_sg(sglist, s, nelems, i) {
+               unsigned long paddr, npages, entry, slen;
 
-       iommu_batch_start(dev, prot, entry);
+               slen = s->length;
+               /* Sanity check */
+               if (slen == 0) {
+                       dma_next = 0;
+                       continue;
+               }
+               /* Allocate iommu entries for that segment */
+               paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+               npages = iommu_num_pages(paddr, slen);
+               entry = iommu_range_alloc(dev, iommu, npages, &handle);
 
-       for_each_sg(sglist, sg, nelems, i) {
-               unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
-               unsigned long slen = sg->length;
-               unsigned long this_npages;
+               /* Handle failure */
+               if (unlikely(entry == DMA_ERROR_CODE)) {
+                       if (printk_ratelimit())
+                               printk(KERN_INFO "iommu_alloc failed, iommu %p paddr %lx"
+                                      " npages %lx\n", iommu, paddr, npages);
+                       goto iommu_map_failed;
+               }
 
-               this_npages = iommu_num_pages(paddr, slen);
+               iommu_batch_new_entry(entry);
 
-               sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
-               sg->dma_length = slen;
+               /* Convert entry to a dma_addr_t */
+               dma_addr = iommu->page_table_map_base +
+                       (entry << IO_PAGE_SHIFT);
+               dma_addr |= (s->offset & ~IO_PAGE_MASK);
 
+               /* Insert into HW table */
                paddr &= IO_PAGE_MASK;
-               while (this_npages--) {
+               while (npages--) {
                        err = iommu_batch_add(paddr);
-                       if (unlikely(err < 0L)) {
-                               local_irq_restore(flags);
+                       if (unlikely(err < 0L))
                                goto iommu_map_failed;
+                       paddr += IO_PAGE_SIZE;
+               }
+
+               /* If we are in an open segment, try merging */
+               if (segstart != s) {
+                       /* We cannot merge if:
+                        * - allocated dma_addr isn't contiguous to previous allocation
+                        */
+                       if ((dma_addr != dma_next) ||
+                           (outs->dma_length + s->length > max_seg_size)) {
+                               /* Can't merge: create a new segment */
+                               segstart = s;
+                               outcount++;
+                               outs = sg_next(outs);
+                       } else {
+                               outs->dma_length += s->length;
                        }
+               }
 
-                       paddr += IO_PAGE_SIZE;
-                       dma_base += IO_PAGE_SIZE;
+               if (segstart == s) {
+                       /* This is a new segment, fill entries */
+                       outs->dma_address = dma_addr;
+                       outs->dma_length = slen;
                }
+
+               /* Calculate next page pointer for contiguous check */
+               dma_next = dma_addr + slen;
        }
 
        err = iommu_batch_end();
 
-       local_irq_restore(flags);
-
        if (unlikely(err < 0L))
                goto iommu_map_failed;
 
-       return nelems;
+       spin_unlock_irqrestore(&iommu->lock, flags);
 
-bad:
-       if (printk_ratelimit())
-               WARN_ON(1);
-       return 0;
+       if (outcount < incount) {
+               outs = sg_next(outs);
+               outs->dma_address = DMA_ERROR_CODE;
+               outs->dma_length = 0;
+       }
+
+       return outcount;
 
 iommu_map_failed:
-       spin_lock_irqsave(&iommu->lock, flags);
-       arena_free(&iommu->arena, entry, npages);
+       for_each_sg(sglist, s, nelems, i) {
+               if (s->dma_length != 0) {
+                       unsigned long vaddr, npages;
+
+                       vaddr = s->dma_address & IO_PAGE_MASK;
+                       npages = iommu_num_pages(s->dma_address, s->dma_length);
+                       iommu_range_free(iommu, vaddr, npages);
+                       /* XXX demap? XXX */
+                       s->dma_address = DMA_ERROR_CODE;
+                       s->dma_length = 0;
+               }
+               if (s == outs)
+                       break;
+       }
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        return 0;
@@ -458,39 +464,43 @@ iommu_map_failed:
 static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
                            int nelems, enum dma_data_direction direction)
 {
-       unsigned long flags, npages;
        struct pci_pbm_info *pbm;
-       u32 devhandle, bus_addr;
+       struct scatterlist *sg;
        struct iommu *iommu;
-       long entry;
+       unsigned long flags;
+       u32 devhandle;
 
-       if (unlikely(direction == DMA_NONE)) {
-               if (printk_ratelimit())
-                       WARN_ON(1);
-       }
+       BUG_ON(direction == DMA_NONE);
 
        iommu = dev->archdata.iommu;
        pbm = dev->archdata.host_controller;
        devhandle = pbm->devhandle;
        
-       bus_addr = sglist->dma_address & IO_PAGE_MASK;
-
-       npages = calc_npages(sglist, nelems);
-
-       entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
-
        spin_lock_irqsave(&iommu->lock, flags);
 
-       arena_free(&iommu->arena, entry, npages);
-
-       do {
-               unsigned long num;
+       sg = sglist;
+       while (nelems--) {
+               dma_addr_t dma_handle = sg->dma_address;
+               unsigned int len = sg->dma_length;
+               unsigned long npages, entry;
+
+               if (!len)
+                       break;
+               npages = iommu_num_pages(dma_handle, len);
+               iommu_range_free(iommu, dma_handle, npages);
+
+               entry = ((dma_handle - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+               while (npages) {
+                       unsigned long num;
+
+                       num = pci_sun4v_iommu_demap(devhandle, HV_PCI_TSBID(0, entry),
+                                                   npages);
+                       entry += num;
+                       npages -= num;
+               }
 
-               num = pci_sun4v_iommu_demap(devhandle, HV_PCI_TSBID(0, entry),
-                                           npages);
-               entry += num;
-               npages -= num;
-       } while (npages != 0);
+               sg = sg_next(sg);
+       }
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
index 7b6d3716efca4a0f370ef848ac8cecbfa0e39eb6..4379f43505efafe27f1c50dca47b970f3fdad3df 100644 (file)
@@ -78,6 +78,7 @@ config MCA
 config V850
        bool
        default y
+       select HAVE_IDE
 
 menu "Processor type and features"
 
index 65a70b777c12e149d14c95a9775896abbe720964..aaed1a3b92d65bfab4804aec952256c9dc25ef72 100644 (file)
@@ -18,6 +18,7 @@ config X86_64
 ### Arch settings
 config X86
        def_bool y
+       select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_KPROBES
 
@@ -102,6 +103,9 @@ config ARCH_HAS_ILOG2_U32
 config ARCH_HAS_ILOG2_U64
        def_bool n
 
+config ARCH_HAS_CPU_IDLE_WAIT
+       def_bool y
+
 config GENERIC_CALIBRATE_DELAY
        def_bool y
 
index fa555148823de98079ced8464fb31a28c25c4063..864affc9a7b07ec67870e1fe2f0dcbc0159cc721 100644 (file)
@@ -34,13 +34,9 @@ config DEBUG_STACK_USAGE
 
          This option will slow down process creation somewhat.
 
-comment "Page alloc debug is incompatible with Software Suspend on i386"
-       depends on DEBUG_KERNEL && HIBERNATION
-       depends on X86_32
-
 config DEBUG_PAGEALLOC
        bool "Debug page memory allocations"
-       depends on DEBUG_KERNEL && X86_32
+       depends on DEBUG_KERNEL
        help
          Unmap pages from the kernel linear mapping after free_pages().
          This results in a large slowdown, but helps to find certain types
index 364865b1b08de8b54625efbf3acb4bb9dbe8089d..204af43535c512556985a9c70d5b5c1b1355b485 100644 (file)
@@ -191,8 +191,10 @@ drivers-$(CONFIG_PCI)            += arch/x86/pci/
 # must be linked after kernel/
 drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/
 
-ifeq ($(CONFIG_X86_32),y)
+# suspend and hibernation support
 drivers-$(CONFIG_PM) += arch/x86/power/
+
+ifeq ($(CONFIG_X86_32),y)
 drivers-$(CONFIG_FB) += arch/x86/video/
 endif
 
index 18465143cfa28b6dbed71a3991f6a1eeee56984a..b1bdc4c6f9f29c8de2ad322980f5d1f28c0c9a8e 100644 (file)
@@ -3,3 +3,5 @@ bzImage
 setup
 setup.bin
 setup.elf
+cpustr.h
+mkcpustr
index 1a09f9309d3c017f846bfd70aaddc5097557bfd8..7e7e890699be9acf34756c7179e1b928db3c0bb8 100644 (file)
@@ -33,8 +33,8 @@ static int skip_atoi(const char **s)
 #define PLUS   4               /* show plus */
 #define SPACE  8               /* space if plus */
 #define LEFT   16              /* left justified */
-#define SPECIAL        32              /* 0x */
-#define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
+#define SMALL  32              /* Must be 32 == 0x20 */
+#define SPECIAL        64              /* 0x */
 
 #define do_div(n,base) ({ \
 int __res; \
@@ -45,12 +45,16 @@ __res; })
 static char *number(char *str, long num, int base, int size, int precision,
                    int type)
 {
-       char c, sign, tmp[66];
-       const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+       /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
+       static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+
+       char tmp[66];
+       char c, sign, locase;
        int i;
 
-       if (type & LARGE)
-               digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       /* locase = 0 or 0x20. ORing digits or letters with 'locase'
+        * produces same digits or (maybe lowercased) letters */
+       locase = (type & SMALL);
        if (type & LEFT)
                type &= ~ZEROPAD;
        if (base < 2 || base > 36)
@@ -81,7 +85,7 @@ static char *number(char *str, long num, int base, int size, int precision,
                tmp[i++] = '0';
        else
                while (num != 0)
-                       tmp[i++] = digits[do_div(num, base)];
+                       tmp[i++] = (digits[do_div(num, base)] | locase);
        if (i > precision)
                precision = i;
        size -= precision;
@@ -95,7 +99,7 @@ static char *number(char *str, long num, int base, int size, int precision,
                        *str++ = '0';
                else if (base == 16) {
                        *str++ = '0';
-                       *str++ = digits[33];
+                       *str++ = ('X' | locase);
                }
        }
        if (!(type & LEFT))
@@ -244,9 +248,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                        base = 8;
                        break;
 
-               case 'X':
-                       flags |= LARGE;
                case 'x':
+                       flags |= SMALL;
+               case 'X':
                        base = 16;
                        break;
 
index 77562e7cdab67a9044347214adcfd285a44233c2..3df340b54e57e93ab09dc6430184f38a2e4b49f3 100644 (file)
@@ -1421,7 +1421,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
-# CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
index 9e2b0ef851dee9ef62ed6494abcafb389921e10e..eef98cb00c629f118ae3982c4f654290de6c2102 100644 (file)
@@ -1346,7 +1346,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FRAME_POINTER is not set
-# CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
index 21dc1a061bf1b13c653b6ba7c8f54e31941f80ff..76ec0f8f138a71cc6014b0f4cc27f3f49b28485f 100644 (file)
@@ -84,8 +84,6 @@ ifeq ($(CONFIG_X86_64),y)
         obj-y                          += genapic_64.o genapic_flat_64.o
         obj-$(CONFIG_X86_PM_TIMER)     += pmtimer_64.o
         obj-$(CONFIG_AUDIT)            += audit_64.o
-        obj-$(CONFIG_PM)               += suspend_64.o
-        obj-$(CONFIG_HIBERNATION)      += suspend_asm_64.o
 
         obj-$(CONFIG_GART_IOMMU)       += pci-gart_64.o aperture_64.o
         obj-$(CONFIG_CALGARY_IOMMU)    += pci-calgary_64.o tce_64.o
index 24885be5c48ca5004a899506ad8fda31edf8a7a3..9b7e01daa1ca22c70830add7e46e68247f903899 100644 (file)
@@ -118,7 +118,7 @@ static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev)
 
 static __cpuinit void thermal_throttle_remove_dev(struct sys_device *sys_dev)
 {
-       return sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
+       sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
 }
 
 /* Mutex protecting device creation against CPU hotplug */
index be5c31d048847e0ba2ae2f76eb5a136e9ee96cb7..824e21b80aadf8c3ff35f30424265f1e87879c35 100644 (file)
@@ -409,7 +409,8 @@ restore_nocheck_notrace:
        RESTORE_REGS
        addl $4, %esp                   # skip orig_eax/error_code
        CFI_ADJUST_CFA_OFFSET -4
-1:     INTERRUPT_RETURN
+ENTRY(irq_return)
+       INTERRUPT_RETURN
 .section .fixup,"ax"
 iret_exc:
        pushl $0                        # no error code
@@ -418,7 +419,7 @@ iret_exc:
 .previous
 .section __ex_table,"a"
        .align 4
-       .long 1b,iret_exc
+       .long irq_return,iret_exc
 .previous
 
        CFI_RESTORE_STATE
@@ -865,20 +866,16 @@ nmi_espfix_stack:
        RESTORE_REGS
        lss 12+4(%esp), %esp            # back to espfix stack
        CFI_ADJUST_CFA_OFFSET -24
-1:     INTERRUPT_RETURN
+       jmp irq_return
        CFI_ENDPROC
-.section __ex_table,"a"
-       .align 4
-       .long 1b,iret_exc
-.previous
 KPROBE_END(nmi)
 
 #ifdef CONFIG_PARAVIRT
 ENTRY(native_iret)
-1:     iret
+       iret
 .section __ex_table,"a"
        .align 4
-       .long 1b,iret_exc
+       .long native_iret, iret_exc
 .previous
 END(native_iret)
 
index c7341e81941cc0e7d6863e317953316c2f045392..6be39a387c5ae66780b0b5f946a71c336980fea8 100644 (file)
@@ -581,16 +581,24 @@ retint_restore_args:      /* return to kernel space */
         */
        TRACE_IRQS_IRETQ
 restore_args:
-       RESTORE_ARGS 0,8,0                                              
-#ifdef CONFIG_PARAVIRT
+       RESTORE_ARGS 0,8,0
+
+ENTRY(irq_return)
        INTERRUPT_RETURN
-#endif
+
+       .section __ex_table, "a"
+       .quad irq_return, bad_iret
+       .previous
+
+#ifdef CONFIG_PARAVIRT
 ENTRY(native_iret)
        iretq
 
        .section __ex_table,"a"
        .quad native_iret, bad_iret
        .previous
+#endif
+
        .section .fixup,"ax"
 bad_iret:
        /*
@@ -804,7 +812,7 @@ paranoid_swapgs\trace:
        SWAPGS_UNSAFE_STACK
 paranoid_restore\trace:
        RESTORE_ALL 8
-       INTERRUPT_RETURN
+       jmp irq_return
 paranoid_userspace\trace:
        GET_THREAD_INFO(%rcx)
        movl threadinfo_flags(%rcx),%ebx
@@ -919,7 +927,7 @@ error_kernelspace:
           iret run with kernel gs again, so don't set the user space flag.
           B stepping K8s sometimes report an truncated RIP for IRET 
           exceptions returning to compat mode. Check for these here too. */
-       leaq native_iret(%rip),%rbp
+       leaq irq_return(%rip),%rbp
        cmpq %rbp,RIP(%rsp) 
        je   error_swapgs
        movl %ebp,%ebp  /* zero extend */
index 9c7f7d3959689af664bd7060b8f5c918a495dd14..9dad6ca6cd70d2812426d7da93224aeaa2d69e33 100644 (file)
@@ -163,14 +163,11 @@ EXPORT_SYMBOL_GPL(geode_gpio_setup_event);
 
 static int __init geode_southbridge_init(void)
 {
-       int timers;
-
        if (!is_geode())
                return -ENODEV;
 
        init_lbars();
-       timers = geode_mfgpt_detect();
-       printk(KERN_INFO "geode:  %d MFGPT timers available.\n", timers);
+       (void) mfgpt_timer_setup();
        return 0;
 }
 
index 5d8c5730686b1e12eab12798d0ed07ae0f4aafa0..74ef4a41f22404a1ff86eb6a7865c83e0ab7d555 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
 #include <asm/setup.h>
+#include <asm/processor-flags.h>
+
+/* Physical address */
+#define pa(X) ((X) - __PAGE_OFFSET)
 
 /*
  * References to members of the new_cpu_data structure.
@@ -80,10 +84,6 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_
  */
 .section .text.head,"ax",@progbits
 ENTRY(startup_32)
-       /* check to see if KEEP_SEGMENTS flag is meaningful */
-       cmpw $0x207, BP_version(%esi)
-       jb 1f
-
        /* test KEEP_SEGMENTS flag to see if the bootloader is asking
                us to not reload segments */
        testb $(1<<6), BP_loadflags(%esi)
@@ -92,7 +92,7 @@ ENTRY(startup_32)
 /*
  * Set segments to known values.
  */
-1:     lgdt boot_gdt_descr - __PAGE_OFFSET
+       lgdt pa(boot_gdt_descr)
        movl $(__BOOT_DS),%eax
        movl %eax,%ds
        movl %eax,%es
@@ -105,8 +105,8 @@ ENTRY(startup_32)
  */
        cld
        xorl %eax,%eax
-       movl $__bss_start - __PAGE_OFFSET,%edi
-       movl $__bss_stop - __PAGE_OFFSET,%ecx
+       movl $pa(__bss_start),%edi
+       movl $pa(__bss_stop),%ecx
        subl %edi,%ecx
        shrl $2,%ecx
        rep ; stosl
@@ -118,31 +118,32 @@ ENTRY(startup_32)
  * (kexec on panic case). Hence copy out the parameters before initializing
  * page tables.
  */
-       movl $(boot_params - __PAGE_OFFSET),%edi
+       movl $pa(boot_params),%edi
        movl $(PARAM_SIZE/4),%ecx
        cld
        rep
        movsl
-       movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi
+       movl pa(boot_params) + NEW_CL_POINTER,%esi
        andl %esi,%esi
        jz 1f                   # No comand line
-       movl $(boot_command_line - __PAGE_OFFSET),%edi
+       movl $pa(boot_command_line),%edi
        movl $(COMMAND_LINE_SIZE/4),%ecx
        rep
        movsl
 1:
 
 #ifdef CONFIG_PARAVIRT
-       cmpw $0x207, (boot_params + BP_version - __PAGE_OFFSET)
+       /* This is can only trip for a broken bootloader... */
+       cmpw $0x207, pa(boot_params + BP_version)
        jb default_entry
 
        /* Paravirt-compatible boot parameters.  Look to see what architecture
                we're booting under. */
-       movl (boot_params + BP_hardware_subarch - __PAGE_OFFSET), %eax
+       movl pa(boot_params + BP_hardware_subarch), %eax
        cmpl $num_subarch_entries, %eax
        jae bad_subarch
 
-       movl subarch_entries - __PAGE_OFFSET(,%eax,4), %eax
+       movl pa(subarch_entries)(,%eax,4), %eax
        subl $__PAGE_OFFSET, %eax
        jmp *%eax
 
@@ -170,17 +171,68 @@ num_subarch_entries = (. - subarch_entries) / 4
  * Mappings are created both at virtual address 0 (identity mapping)
  * and PAGE_OFFSET for up to _end+sizeof(page tables)+INIT_MAP_BEYOND_END.
  *
- * Warning: don't use %esi or the stack in this code.  However, %esp
- * can be used as a GPR if you really need it...
+ * Note that the stack is not yet set up!
  */
-page_pde_offset = (__PAGE_OFFSET >> 20);
+#define PTE_ATTR       0x007           /* PRESENT+RW+USER */
+#define PDE_ATTR       0x067           /* PRESENT+RW+USER+DIRTY+ACCESSED */
+#define PGD_ATTR       0x001           /* PRESENT (no other attributes) */
 
 default_entry:
-       movl $(pg0 - __PAGE_OFFSET), %edi
-       movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
-       movl $0x007, %eax                       /* 0x007 = PRESENT+RW+USER */
+#ifdef CONFIG_X86_PAE
+
+       /*
+        * In PAE mode swapper_pg_dir is statically defined to contain enough
+        * entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+        * entries). The identity mapping is handled by pointing two PGD
+        * entries to the first kernel PMD.
+        *
+        * Note the upper half of each PMD or PTE are always zero at
+        * this stage.
+        */
+
+#define KPMDS ((0x100000000-__PAGE_OFFSET) >> 30) /* Number of kernel PMDs */
+
+       xorl %ebx,%ebx                          /* %ebx is kept at zero */
+
+       movl $pa(pg0), %edi
+       movl $pa(swapper_pg_pmd), %edx
+       movl $PTE_ATTR, %eax
+10:
+       leal PDE_ATTR(%edi),%ecx                /* Create PMD entry */
+       movl %ecx,(%edx)                        /* Store PMD entry */
+                                               /* Upper half already zero */
+       addl $8,%edx
+       movl $512,%ecx
+11:
+       stosl
+       xchgl %eax,%ebx
+       stosl
+       xchgl %eax,%ebx
+       addl $0x1000,%eax
+       loop 11b
+
+       /*
+        * End condition: we must map up to and including INIT_MAP_BEYOND_END
+        * bytes beyond the end of our own page tables.
+        */
+       leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp
+       cmpl %ebp,%eax
+       jb 10b
+1:
+       movl %edi,pa(init_pg_tables_end)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax
+       movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8)
+#else  /* Not PAE */
+
+page_pde_offset = (__PAGE_OFFSET >> 20);
+
+       movl $pa(pg0), %edi
+       movl $pa(swapper_pg_dir), %edx
+       movl $PTE_ATTR, %eax
 10:
-       leal 0x007(%edi),%ecx                   /* Create PDE entry */
+       leal PDE_ATTR(%edi),%ecx                /* Create PDE entry */
        movl %ecx,(%edx)                        /* Store identity PDE entry */
        movl %ecx,page_pde_offset(%edx)         /* Store kernel PDE entry */
        addl $4,%edx
@@ -189,19 +241,20 @@ default_entry:
        stosl
        addl $0x1000,%eax
        loop 11b
-       /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
-       /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
-       leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
+       /*
+        * End condition: we must map up to and including INIT_MAP_BEYOND_END
+        * bytes beyond the end of our own page tables; the +0x007 is
+        * the attribute bits
+        */
+       leal (INIT_MAP_BEYOND_END+PTE_ATTR)(%edi),%ebp
        cmpl %ebp,%eax
        jb 10b
-       movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
-
-       /* Do an early initialization of the fixmap area */
-       movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
-       movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax
-       addl $0x67, %eax                        /* 0x67 == _PAGE_TABLE */
-       movl %eax, 4092(%edx)
+       movl %edi,pa(init_pg_tables_end)
 
+       /* Do early initialization of the fixmap area */
+       movl $pa(swapper_pg_fixmap)+PDE_ATTR,%eax
+       movl %eax,pa(swapper_pg_dir+0xffc)
+#endif
        jmp 3f
 /*
  * Non-boot CPU entry point; entered from trampoline.S
@@ -241,7 +294,7 @@ ENTRY(startup_32_smp)
  *     NOTE! We have to correct for the fact that we're
  *     not yet offset PAGE_OFFSET..
  */
-#define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+#define cr4_bits pa(mmu_cr4_features)
        movl cr4_bits,%edx
        andl %edx,%edx
        jz 6f
@@ -276,10 +329,10 @@ ENTRY(startup_32_smp)
 /*
  * Enable paging
  */
-       movl $swapper_pg_dir-__PAGE_OFFSET,%eax
+       movl $pa(swapper_pg_dir),%eax
        movl %eax,%cr3          /* set the page table pointer.. */
        movl %cr0,%eax
-       orl $0x80000000,%eax
+       orl  $X86_CR0_PG,%eax
        movl %eax,%cr0          /* ..and set paging (PG) bit */
        ljmp $__BOOT_CS,$1f     /* Clear prefetch and normalize %eip */
 1:
@@ -552,16 +605,44 @@ ENTRY(_stext)
  */
 .section ".bss.page_aligned","wa"
        .align PAGE_SIZE_asm
+#ifdef CONFIG_X86_PAE
+ENTRY(swapper_pg_pmd)
+       .fill 1024*KPMDS,4,0
+#else
 ENTRY(swapper_pg_dir)
        .fill 1024,4,0
-ENTRY(swapper_pg_pmd)
+#endif
+ENTRY(swapper_pg_fixmap)
        .fill 1024,4,0
 ENTRY(empty_zero_page)
        .fill 4096,1,0
-
 /*
  * This starts the data section.
  */
+#ifdef CONFIG_X86_PAE
+.section ".data.page_aligned","wa"
+       /* Page-aligned for the benefit of paravirt? */
+       .align PAGE_SIZE_asm
+ENTRY(swapper_pg_dir)
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0           /* low identity map */
+# if KPMDS == 3
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0
+       .long   pa(swapper_pg_pmd+PGD_ATTR+0x1000),0
+       .long   pa(swapper_pg_pmd+PGD_ATTR+0x2000),0
+# elif KPMDS == 2
+       .long   0,0
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0
+       .long   pa(swapper_pg_pmd+PGD_ATTR+0x1000),0
+# elif KPMDS == 1
+       .long   0,0
+       .long   0,0
+       .long   pa(swapper_pg_pmd+PGD_ATTR),0
+# else
+#  error "Kernel PMDs should be 1, 2 or 3"
+# endif
+       .align PAGE_SIZE_asm            /* needs to be page-sized too */
+#endif
+
 .data
 ENTRY(stack_start)
        .long init_thread_union+THREAD_SIZE
index 219f86eb612301766771651eb56cb1e8f98189ac..027fc067b3995153164c799fbe63502baf7706fd 100644 (file)
  */
 
 /*
- * We are using the 32Khz input clock - its the only one that has the
+ * We are using the 32.768kHz input clock - it's the only one that has the
  * ranges we find desirable.  The following table lists the suitable
- * divisors and the associated hz, minimum interval
- * and the maximum interval:
+ * divisors and the associated Hz, minimum interval and the maximum interval:
  *
- *  Divisor   Hz      Min Delta (S) Max Delta (S)
- *   1        32000     .0005          2.048
- *   2        16000      .001          4.096
- *   4         8000      .002          8.192
- *   8         4000      .004         16.384
- *   16        2000      .008         32.768
- *   32        1000      .016         65.536
- *   64         500      .032        131.072
- *  128         250      .064        262.144
- *  256         125      .128        524.288
+ *  Divisor   Hz      Min Delta (s)  Max Delta (s)
+ *   1        32768   .00048828125      2.000
+ *   2        16384   .0009765625       4.000
+ *   4         8192   .001953125        8.000
+ *   8         4096   .00390625        16.000
+ *   16        2048   .0078125         32.000
+ *   32        1024   .015625          64.000
+ *   64         512   .03125          128.000
+ *  128         256   .0625           256.000
+ *  256         128   .125            512.000
  */
 
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
-#include <linux/module.h>
 #include <asm/geode.h>
 
-#define F_AVAIL    0x01
-
 static struct mfgpt_timer_t {
-       int flags;
-       struct module *owner;
+       unsigned int avail:1;
 } mfgpt_timers[MFGPT_MAX_TIMERS];
 
 /* Selected from the table above */
 
 #define MFGPT_DIVISOR 16
 #define MFGPT_SCALE  4     /* divisor = 2^(scale) */
-#define MFGPT_HZ  (32000 / MFGPT_DIVISOR)
+#define MFGPT_HZ  (32768 / MFGPT_DIVISOR)
 #define MFGPT_PERIODIC (MFGPT_HZ / HZ)
 
-#ifdef CONFIG_GEODE_MFGPT_TIMER
-static int __init mfgpt_timer_setup(void);
-#else
-#define mfgpt_timer_setup() (0)
-#endif
-
 /* Allow for disabling of MFGPTs */
 static int disable;
 static int __init mfgpt_disable(char *s)
@@ -85,28 +74,37 @@ __setup("mfgptfix", mfgpt_fix);
  * In other cases (such as with VSAless OpenFirmware), the system firmware
  * leaves timers available for us to use.
  */
-int __init geode_mfgpt_detect(void)
+
+
+static int timers = -1;
+
+static void geode_mfgpt_detect(void)
 {
-       int count = 0, i;
+       int i;
        u16 val;
 
+       timers = 0;
+
        if (disable) {
-               printk(KERN_INFO "geode-mfgpt:  Skipping MFGPT setup\n");
-               return 0;
+               printk(KERN_INFO "geode-mfgpt:  MFGPT support is disabled\n");
+               goto done;
+       }
+
+       if (!geode_get_dev_base(GEODE_DEV_MFGPT)) {
+               printk(KERN_INFO "geode-mfgpt:  MFGPT LBAR is not set up\n");
+               goto done;
        }
 
        for (i = 0; i < MFGPT_MAX_TIMERS; i++) {
                val = geode_mfgpt_read(i, MFGPT_REG_SETUP);
                if (!(val & MFGPT_SETUP_SETUP)) {
-                       mfgpt_timers[i].flags = F_AVAIL;
-                       count++;
+                       mfgpt_timers[i].avail = 1;
+                       timers++;
                }
        }
 
-       /* set up clock event device, if desired */
-       i = mfgpt_timer_setup();
-
-       return count;
+done:
+       printk(KERN_INFO "geode-mfgpt:  %d MFGPT timers available.\n", timers);
 }
 
 int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable)
@@ -183,36 +181,41 @@ int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable)
        return 0;
 }
 
-static int mfgpt_get(int timer, struct module *owner)
+static int mfgpt_get(int timer)
 {
-       mfgpt_timers[timer].flags &= ~F_AVAIL;
-       mfgpt_timers[timer].owner = owner;
+       mfgpt_timers[timer].avail = 0;
        printk(KERN_INFO "geode-mfgpt:  Registered timer %d\n", timer);
        return timer;
 }
 
-int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner)
+int geode_mfgpt_alloc_timer(int timer, int domain)
 {
        int i;
 
-       if (!geode_get_dev_base(GEODE_DEV_MFGPT))
-               return -ENODEV;
+       if (timers == -1) {
+               /* timers haven't been detected yet */
+               geode_mfgpt_detect();
+       }
+
+       if (!timers)
+               return -1;
+
        if (timer >= MFGPT_MAX_TIMERS)
-               return -EIO;
+               return -1;
 
        if (timer < 0) {
                /* Try to find an available timer */
                for (i = 0; i < MFGPT_MAX_TIMERS; i++) {
-                       if (mfgpt_timers[i].flags & F_AVAIL)
-                               return mfgpt_get(i, owner);
+                       if (mfgpt_timers[i].avail)
+                               return mfgpt_get(i);
 
                        if (i == 5 && domain == MFGPT_DOMAIN_WORKING)
                                break;
                }
        } else {
                /* If they requested a specific timer, try to honor that */
-               if (mfgpt_timers[timer].flags & F_AVAIL)
-                       return mfgpt_get(timer, owner);
+               if (mfgpt_timers[timer].avail)
+                       return mfgpt_get(timer);
        }
 
        /* No timers available - too bad */
@@ -244,10 +247,11 @@ static int __init mfgpt_setup(char *str)
 }
 __setup("mfgpt_irq=", mfgpt_setup);
 
-static inline void mfgpt_disable_timer(u16 clock)
+static void mfgpt_disable_timer(u16 clock)
 {
-       u16 val = geode_mfgpt_read(clock, MFGPT_REG_SETUP);
-       geode_mfgpt_write(clock, MFGPT_REG_SETUP, val & ~MFGPT_SETUP_CNTEN);
+       /* avoid races by clearing CMP1 and CMP2 unconditionally */
+       geode_mfgpt_write(clock, MFGPT_REG_SETUP, (u16) ~MFGPT_SETUP_CNTEN |
+                       MFGPT_SETUP_CMP1 | MFGPT_SETUP_CMP2);
 }
 
 static int mfgpt_next_event(unsigned long, struct clock_event_device *);
@@ -263,7 +267,7 @@ static struct clock_event_device mfgpt_clockevent = {
        .shift = 32
 };
 
-static inline void mfgpt_start_timer(u16 clock, u16 delta)
+static void mfgpt_start_timer(u16 delta)
 {
        geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_CMP2, (u16) delta);
        geode_mfgpt_write(mfgpt_event_clock, MFGPT_REG_COUNTER, 0);
@@ -278,21 +282,25 @@ static void mfgpt_set_mode(enum clock_event_mode mode,
        mfgpt_disable_timer(mfgpt_event_clock);
 
        if (mode == CLOCK_EVT_MODE_PERIODIC)
-               mfgpt_start_timer(mfgpt_event_clock, MFGPT_PERIODIC);
+               mfgpt_start_timer(MFGPT_PERIODIC);
 
        mfgpt_tick_mode = mode;
 }
 
 static int mfgpt_next_event(unsigned long delta, struct clock_event_device *evt)
 {
-       mfgpt_start_timer(mfgpt_event_clock, delta);
+       mfgpt_start_timer(delta);
        return 0;
 }
 
-/* Assume (foolishly?), that this interrupt was due to our tick */
-
 static irqreturn_t mfgpt_tick(int irq, void *dev_id)
 {
+       u16 val = geode_mfgpt_read(mfgpt_event_clock, MFGPT_REG_SETUP);
+
+       /* See if the interrupt was for us */
+       if (!(val & (MFGPT_SETUP_SETUP  | MFGPT_SETUP_CMP2 | MFGPT_SETUP_CMP1)))
+               return IRQ_NONE;
+
        /* Turn off the clock (and clear the event) */
        mfgpt_disable_timer(mfgpt_event_clock);
 
@@ -320,13 +328,12 @@ static struct irqaction mfgptirq  = {
        .name = "mfgpt-timer"
 };
 
-static int __init mfgpt_timer_setup(void)
+int __init mfgpt_timer_setup(void)
 {
        int timer, ret;
        u16 val;
 
-       timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING,
-                       THIS_MODULE);
+       timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, MFGPT_DOMAIN_WORKING);
        if (timer < 0) {
                printk(KERN_ERR
                       "mfgpt-timer:  Could not allocate a MFPGT timer\n");
@@ -363,7 +370,7 @@ static int __init mfgpt_timer_setup(void)
                        &mfgpt_clockevent);
 
        printk(KERN_INFO
-              "mfgpt-timer:  registering the MFGT timer as a clock event.\n");
+              "mfgpt-timer:  registering the MFGPT timer as a clock event.\n");
        clockevents_register_device(&mfgpt_clockevent);
 
        return 0;
index 6ba33ca8715abc3e925debf55797b0834aee1a38..1941482d4ca317d52ddbd9af51a7142a96a452ba 100644 (file)
@@ -27,7 +27,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
        pci_write_config_byte(dev, 0xf4, config|0x2);
 
        /* read xTPR register */
-       raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
+       raw_pci_read(0, 0, 0x40, 0x4c, 2, &word);
 
        if (!(word & (1 << 13))) {
                dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
index d1d8c347cc0b77a05f2c7d90ca1ddaa1d5420e99..691ab4cb167be129fda7ac8bf1d5d14da92017d4 100644 (file)
@@ -154,7 +154,11 @@ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 EXPORT_SYMBOL(boot_cpu_data);
 
+#ifndef CONFIG_X86_PAE
 unsigned long mmu_cr4_features;
+#else
+unsigned long mmu_cr4_features = X86_CR4_PAE;
+#endif
 
 /* for MCA, but anyone else can use it if they want */
 unsigned int machine_id;
index e6757aaa202bda9c7dfc1992d3e148fa55541f45..a40051b71d9b79cb2906b296aa5fc882dbe7dc53 100644 (file)
@@ -53,7 +53,7 @@ EXPORT_SYMBOL(arch_register_cpu);
 
 void arch_unregister_cpu(int num)
 {
-       return unregister_cpu(&per_cpu(cpu_devices, num).cpu);
+       unregister_cpu(&per_cpu(cpu_devices, num).cpu);
 }
 EXPORT_SYMBOL(arch_unregister_cpu);
 #else
index d1bc04006d16e12fc706fe10b942e01cde3bb2d5..8106bba41ecb4b7ce5b87a58545c50102cc562b7 100644 (file)
@@ -46,6 +46,7 @@
 #include <asm/pgalloc.h>
 #include <asm/sections.h>
 #include <asm/paravirt.h>
+#include <asm/setup.h>
 
 unsigned int __VMALLOC_RESERVE = 128 << 20;
 
@@ -328,44 +329,38 @@ pteval_t __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
 
 void __init native_pagetable_setup_start(pgd_t *base)
 {
-#ifdef CONFIG_X86_PAE
-       int i;
+       unsigned long pfn, va;
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
 
        /*
-        * Init entries of the first-level page table to the
-        * zero page, if they haven't already been set up.
-        *
-        * In a normal native boot, we'll be running on a
-        * pagetable rooted in swapper_pg_dir, but not in PAE
-        * mode, so this will end up clobbering the mappings
-        * for the lower 24Mbytes of the address space,
-        * without affecting the kernel address space.
+        * Remove any mappings which extend past the end of physical
+        * memory from the boot time page table:
         */
-       for (i = 0; i < USER_PTRS_PER_PGD; i++)
-               set_pgd(&base[i],
-                       __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
-
-       /* Make sure kernel address space is empty so that a pagetable
-          will be allocated for it. */
-       memset(&base[USER_PTRS_PER_PGD], 0,
-              KERNEL_PGD_PTRS * sizeof(pgd_t));
-#else
+       for (pfn = max_low_pfn + 1; pfn < 1<<(32-PAGE_SHIFT); pfn++) {
+               va = PAGE_OFFSET + (pfn<<PAGE_SHIFT);
+               pgd = base + pgd_index(va);
+               if (!pgd_present(*pgd))
+                       break;
+
+               pud = pud_offset(pgd, va);
+               pmd = pmd_offset(pud, va);
+               if (!pmd_present(*pmd))
+                       break;
+
+               pte = pte_offset_kernel(pmd, va);
+               if (!pte_present(*pte))
+                       break;
+
+               pte_clear(NULL, va, pte);
+       }
        paravirt_alloc_pd(&init_mm, __pa(base) >> PAGE_SHIFT);
-#endif
 }
 
 void __init native_pagetable_setup_done(pgd_t *base)
 {
-#ifdef CONFIG_X86_PAE
-       /*
-        * Add low memory identity-mappings - SMP needs it when
-        * starting up on an AP from real-mode. In the non-PAE
-        * case we already have these mappings through head.S.
-        * All user-space mappings are explicitly cleared after
-        * SMP startup.
-        */
-       set_pgd(&base[0], base[USER_PTRS_PER_PGD]);
-#endif
 }
 
 /*
@@ -374,9 +369,8 @@ void __init native_pagetable_setup_done(pgd_t *base)
  * the boot process.
  *
  * If we're booting on native hardware, this will be a pagetable
- * constructed in arch/i386/kernel/head.S, and not running in PAE mode
- * (even if we'll end up running in PAE).  The root of the pagetable
- * will be swapper_pg_dir.
+ * constructed in arch/x86/kernel/head_32.S.  The root of the
+ * pagetable will be swapper_pg_dir.
  *
  * If we're booting paravirtualized under a hypervisor, then there are
  * more options: we may already be running PAE, and the pagetable may
@@ -537,14 +531,6 @@ void __init paging_init(void)
 
        load_cr3(swapper_pg_dir);
 
-#ifdef CONFIG_X86_PAE
-       /*
-        * We will bail out later - printk doesn't work right now so
-        * the user would just see a hanging kernel.
-        */
-       if (cpu_has_pae)
-               set_in_cr4(X86_CR4_PAE);
-#endif
        __flush_tlb_all();
 
        kmap_init();
@@ -675,13 +661,11 @@ void __init mem_init(void)
        BUG_ON((unsigned long)high_memory               > VMALLOC_START);
 #endif /* double-sanity-check paranoia */
 
-#ifdef CONFIG_X86_PAE
-       if (!cpu_has_pae)
-               panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
-#endif
        if (boot_cpu_data.wp_works_ok < 0)
                test_wp_bit();
 
+       cpa_init();
+
        /*
         * Subtle. SMP is doing it's boot stuff late (because it has to
         * fork idle threads) - but it also needs low mappings for the
index 5fe880fc305d03c90131948bab8c4cd16096e9f9..b59fc238151fb58650f64c411c961511e725ee81 100644 (file)
@@ -528,13 +528,15 @@ void __init mem_init(void)
                reservedpages << (PAGE_SHIFT-10),
                datasize >> 10,
                initsize >> 10);
+
+       cpa_init();
 }
 
 void free_init_pages(char *what, unsigned long begin, unsigned long end)
 {
-       unsigned long addr;
+       unsigned long addr = begin;
 
-       if (begin >= end)
+       if (addr >= end)
                return;
 
        /*
@@ -549,7 +551,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
 #else
        printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
 
-       for (addr = begin; addr < end; addr += PAGE_SIZE) {
+       for (; addr < end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
                memset((void *)(addr & ~(PAGE_SIZE-1)),
index ee6648fe6b15de75a4e0fe53a90f6311fa8b917a..a4897a85268a5274d76145783a240426e6d456b7 100644 (file)
@@ -260,41 +260,46 @@ static int __init early_ioremap_debug_setup(char *str)
 early_param("early_ioremap_debug", early_ioremap_debug_setup);
 
 static __initdata int after_paging_init;
-static __initdata unsigned long bm_pte[1024]
+static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)]
                                __attribute__((aligned(PAGE_SIZE)));
 
-static inline unsigned long * __init early_ioremap_pgd(unsigned long addr)
+static inline pmd_t * __init early_ioremap_pmd(unsigned long addr)
 {
-       return (unsigned long *)swapper_pg_dir + ((addr >> 22) & 1023);
+       pgd_t *pgd = &swapper_pg_dir[pgd_index(addr)];
+       pud_t *pud = pud_offset(pgd, addr);
+       pmd_t *pmd = pmd_offset(pud, addr);
+
+       return pmd;
 }
 
-static inline unsigned long * __init early_ioremap_pte(unsigned long addr)
+static inline pte_t * __init early_ioremap_pte(unsigned long addr)
 {
-       return bm_pte + ((addr >> PAGE_SHIFT) & 1023);
+       return &bm_pte[pte_index(addr)];
 }
 
 void __init early_ioremap_init(void)
 {
-       unsigned long *pgd;
+       pmd_t *pmd;
 
        if (early_ioremap_debug)
                printk(KERN_INFO "early_ioremap_init()\n");
 
-       pgd = early_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
-       *pgd = __pa(bm_pte) | _PAGE_TABLE;
+       pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
        memset(bm_pte, 0, sizeof(bm_pte));
+       pmd_populate_kernel(&init_mm, pmd, bm_pte);
+
        /*
-        * The boot-ioremap range spans multiple pgds, for which
+        * The boot-ioremap range spans multiple pmds, for which
         * we are not prepared:
         */
-       if (pgd != early_ioremap_pgd(fix_to_virt(FIX_BTMAP_END))) {
+       if (pmd != early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END))) {
                WARN_ON(1);
-               printk(KERN_WARNING "pgd %p != %p\n",
-                      pgd, early_ioremap_pgd(fix_to_virt(FIX_BTMAP_END)));
+               printk(KERN_WARNING "pmd %p != %p\n",
+                      pmd, early_ioremap_pmd(fix_to_virt(FIX_BTMAP_END)));
                printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
-                      fix_to_virt(FIX_BTMAP_BEGIN));
+                       fix_to_virt(FIX_BTMAP_BEGIN));
                printk(KERN_WARNING "fix_to_virt(FIX_BTMAP_END):   %08lx\n",
-                      fix_to_virt(FIX_BTMAP_END));
+                       fix_to_virt(FIX_BTMAP_END));
 
                printk(KERN_WARNING "FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
                printk(KERN_WARNING "FIX_BTMAP_BEGIN:     %d\n",
@@ -304,28 +309,29 @@ void __init early_ioremap_init(void)
 
 void __init early_ioremap_clear(void)
 {
-       unsigned long *pgd;
+       pmd_t *pmd;
 
        if (early_ioremap_debug)
                printk(KERN_INFO "early_ioremap_clear()\n");
 
-       pgd = early_ioremap_pgd(fix_to_virt(FIX_BTMAP_BEGIN));
-       *pgd = 0;
-       paravirt_release_pt(__pa(pgd) >> PAGE_SHIFT);
+       pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN));
+       pmd_clear(pmd);
+       paravirt_release_pt(__pa(bm_pte) >> PAGE_SHIFT);
        __flush_tlb_all();
 }
 
 void __init early_ioremap_reset(void)
 {
        enum fixed_addresses idx;
-       unsigned long *pte, phys, addr;
+       unsigned long addr, phys;
+       pte_t *pte;
 
        after_paging_init = 1;
        for (idx = FIX_BTMAP_BEGIN; idx >= FIX_BTMAP_END; idx--) {
                addr = fix_to_virt(idx);
                pte = early_ioremap_pte(addr);
-               if (*pte & _PAGE_PRESENT) {
-                       phys = *pte & PAGE_MASK;
+               if (pte_present(*pte)) {
+                       phys = pte_val(*pte) & PAGE_MASK;
                        set_fixmap(idx, phys);
                }
        }
@@ -334,7 +340,8 @@ void __init early_ioremap_reset(void)
 static void __init __early_set_fixmap(enum fixed_addresses idx,
                                   unsigned long phys, pgprot_t flags)
 {
-       unsigned long *pte, addr = __fix_to_virt(idx);
+       unsigned long addr = __fix_to_virt(idx);
+       pte_t *pte;
 
        if (idx >= __end_of_fixed_addresses) {
                BUG();
@@ -342,9 +349,9 @@ static void __init __early_set_fixmap(enum fixed_addresses idx,
        }
        pte = early_ioremap_pte(addr);
        if (pgprot_val(flags))
-               *pte = (phys & PAGE_MASK) | pgprot_val(flags);
+               set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, flags));
        else
-               *pte = 0;
+               pte_clear(NULL, addr, pte);
        __flush_tlb_one(addr);
 }
 
index 8493c855582bf56a5a36d2e6e64266332c9d26c0..440210a2277d3d6a710dcb713792e377f8306d89 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/interrupt.h>
 
 #include <asm/e820.h>
 #include <asm/processor.h>
@@ -191,7 +192,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
  * or when the present bit is not set. Otherwise we would return a
  * pointer to a nonexisting mapping.
  */
-pte_t *lookup_address(unsigned long address, int *level)
+pte_t *lookup_address(unsigned long address, unsigned int *level)
 {
        pgd_t *pgd = pgd_offset_k(address);
        pud_t *pud;
@@ -252,10 +253,11 @@ static int
 try_preserve_large_page(pte_t *kpte, unsigned long address,
                        struct cpa_data *cpa)
 {
-       unsigned long nextpage_addr, numpages, pmask, psize, flags;
+       unsigned long nextpage_addr, numpages, pmask, psize, flags, addr;
        pte_t new_pte, old_pte, *tmp;
        pgprot_t old_prot, new_prot;
-       int level, do_split = 1;
+       int i, do_split = 1;
+       unsigned int level;
 
        spin_lock_irqsave(&pgd_lock, flags);
        /*
@@ -301,6 +303,19 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
        pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
        new_prot = static_protections(new_prot, address);
 
+       /*
+        * We need to check the full range, whether
+        * static_protection() requires a different pgprot for one of
+        * the pages in the range we try to preserve:
+        */
+       addr = address + PAGE_SIZE;
+       for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE) {
+               pgprot_t chk_prot = static_protections(new_prot, addr);
+
+               if (pgprot_val(chk_prot) != pgprot_val(new_prot))
+                       goto out_unlock;
+       }
+
        /*
         * If there are no changes, return. maxpages has been updated
         * above:
@@ -335,23 +350,103 @@ out_unlock:
        return do_split;
 }
 
+static LIST_HEAD(page_pool);
+static unsigned long pool_size, pool_pages, pool_low;
+static unsigned long pool_used, pool_failed, pool_refill;
+
+static void cpa_fill_pool(void)
+{
+       struct page *p;
+       gfp_t gfp = GFP_KERNEL;
+
+       /* Do not allocate from interrupt context */
+       if (in_irq() || irqs_disabled())
+               return;
+       /*
+        * Check unlocked. I does not matter when we have one more
+        * page in the pool. The bit lock avoids recursive pool
+        * allocations:
+        */
+       if (pool_pages >= pool_size || test_and_set_bit_lock(0, &pool_refill))
+               return;
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+       /*
+        * We could do:
+        * gfp = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
+        * but this fails on !PREEMPT kernels
+        */
+       gfp =  GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
+#endif
+
+       while (pool_pages < pool_size) {
+               p = alloc_pages(gfp, 0);
+               if (!p) {
+                       pool_failed++;
+                       break;
+               }
+               spin_lock_irq(&pgd_lock);
+               list_add(&p->lru, &page_pool);
+               pool_pages++;
+               spin_unlock_irq(&pgd_lock);
+       }
+       clear_bit_unlock(0, &pool_refill);
+}
+
+#define SHIFT_MB               (20 - PAGE_SHIFT)
+#define ROUND_MB_GB            ((1 << 10) - 1)
+#define SHIFT_MB_GB            10
+#define POOL_PAGES_PER_GB      16
+
+void __init cpa_init(void)
+{
+       struct sysinfo si;
+       unsigned long gb;
+
+       si_meminfo(&si);
+       /*
+        * Calculate the number of pool pages:
+        *
+        * Convert totalram (nr of pages) to MiB and round to the next
+        * GiB. Shift MiB to Gib and multiply the result by
+        * POOL_PAGES_PER_GB:
+        */
+       gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB;
+       pool_size = POOL_PAGES_PER_GB * gb;
+       pool_low = pool_size;
+
+       cpa_fill_pool();
+       printk(KERN_DEBUG
+              "CPA: page pool initialized %lu of %lu pages preallocated\n",
+              pool_pages, pool_size);
+}
+
 static int split_large_page(pte_t *kpte, unsigned long address)
 {
        unsigned long flags, pfn, pfninc = 1;
-       gfp_t gfp_flags = GFP_KERNEL;
        unsigned int i, level;
        pte_t *pbase, *tmp;
        pgprot_t ref_prot;
        struct page *base;
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
-#endif
-       base = alloc_pages(gfp_flags, 0);
-       if (!base)
+       /*
+        * Get a page from the pool. The pool list is protected by the
+        * pgd_lock, which we have to take anyway for the split
+        * operation:
+        */
+       spin_lock_irqsave(&pgd_lock, flags);
+       if (list_empty(&page_pool)) {
+               spin_unlock_irqrestore(&pgd_lock, flags);
                return -ENOMEM;
+       }
+
+       base = list_first_entry(&page_pool, struct page, lru);
+       list_del(&base->lru);
+       pool_pages--;
+
+       if (pool_pages < pool_low)
+               pool_low = pool_pages;
 
-       spin_lock_irqsave(&pgd_lock, flags);
        /*
         * Check for races, another CPU might have split this page
         * up for us already:
@@ -396,17 +491,24 @@ static int split_large_page(pte_t *kpte, unsigned long address)
        base = NULL;
 
 out_unlock:
+       /*
+        * If we dropped out via the lookup_address check under
+        * pgd_lock then stick the page back into the pool:
+        */
+       if (base) {
+               list_add(&base->lru, &page_pool);
+               pool_pages++;
+       } else
+               pool_used++;
        spin_unlock_irqrestore(&pgd_lock, flags);
 
-       if (base)
-               __free_pages(base, 0);
-
        return 0;
 }
 
 static int __change_page_attr(unsigned long address, struct cpa_data *cpa)
 {
-       int level, do_split, err;
+       int do_split, err;
+       unsigned int level;
        struct page *kpte_page;
        pte_t *kpte;
 
@@ -598,7 +700,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
         * Check whether we really changed something:
         */
        if (!cpa.flushtlb)
-               return ret;
+               goto out;
 
        /*
         * No need to flush, when we did not set any of the caching
@@ -617,6 +719,8 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
        else
                cpa_flush_all(cache);
 
+out:
+       cpa_fill_pool();
        return ret;
 }
 
@@ -770,6 +874,12 @@ void kernel_map_pages(struct page *page, int numpages, int enable)
         * but that can deadlock->flush only current cpu:
         */
        __flush_tlb_all();
+
+       /*
+        * Try to refill the page pool here. We can do this only after
+        * the tlb flush.
+        */
+       cpa_fill_pool();
 }
 #endif
 
index 52deabc72a6facaf7975436a7bba1cf5c99d403f..b7c67a187b6bd3417c6bf7528e466e24660255a7 100644 (file)
@@ -26,16 +26,37 @@ int pcibios_last_bus = -1;
 unsigned long pirq_table_addr;
 struct pci_bus *pci_root_bus;
 struct pci_raw_ops *raw_pci_ops;
+struct pci_raw_ops *raw_pci_ext_ops;
+
+int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
+                                               int reg, int len, u32 *val)
+{
+       if (reg < 256 && raw_pci_ops)
+               return raw_pci_ops->read(domain, bus, devfn, reg, len, val);
+       if (raw_pci_ext_ops)
+               return raw_pci_ext_ops->read(domain, bus, devfn, reg, len, val);
+       return -EINVAL;
+}
+
+int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
+                                               int reg, int len, u32 val)
+{
+       if (reg < 256 && raw_pci_ops)
+               return raw_pci_ops->write(domain, bus, devfn, reg, len, val);
+       if (raw_pci_ext_ops)
+               return raw_pci_ext_ops->write(domain, bus, devfn, reg, len, val);
+       return -EINVAL;
+}
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
 {
-       return raw_pci_ops->read(pci_domain_nr(bus), bus->number,
+       return raw_pci_read(pci_domain_nr(bus), bus->number,
                                 devfn, where, size, value);
 }
 
 static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
 {
-       return raw_pci_ops->write(pci_domain_nr(bus), bus->number,
+       return raw_pci_write(pci_domain_nr(bus), bus->number,
                                  devfn, where, size, value);
 }
 
index 431c9a51b1578bbaf39de3bcefc95d2087a73a38..42f3e4cad179754c1dfc2594e4f759695eca1089 100644 (file)
@@ -14,7 +14,7 @@
 #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
        (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
 
-int pci_conf1_read(unsigned int seg, unsigned int bus,
+static int pci_conf1_read(unsigned int seg, unsigned int bus,
                          unsigned int devfn, int reg, int len, u32 *value)
 {
        unsigned long flags;
@@ -45,7 +45,7 @@ int pci_conf1_read(unsigned int seg, unsigned int bus,
        return 0;
 }
 
-int pci_conf1_write(unsigned int seg, unsigned int bus,
+static int pci_conf1_write(unsigned int seg, unsigned int bus,
                           unsigned int devfn, int reg, int len, u32 value)
 {
        unsigned long flags;
index 74d30ff33c495319e6f45da8097f7fefc5f4f606..a5ef5f55137313fcb1faec0145200beac774d4f8 100644 (file)
@@ -215,7 +215,8 @@ static int quirk_aspm_offset[MAX_PCIEROOT << 3];
 
 static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
 {
-       return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
+       return raw_pci_read(pci_domain_nr(bus), bus->number,
+                                               devfn, where, size, value);
 }
 
 /*
@@ -231,7 +232,8 @@ static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int wh
        if ((offset) && (where == offset))
                value = value & 0xfffffffc;
 
-       return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
+       return raw_pci_write(pci_domain_nr(bus), bus->number,
+                                               devfn, where, size, value);
 }
 
 static struct pci_ops quirk_pcie_aspm_ops = {
index 5565d7016b754d340c4f82aceec44f781b964d63..e041ced0ce138714a93147f9cc5015e0f7f51d3e 100644 (file)
@@ -22,7 +22,7 @@ static void __devinit pcibios_fixup_peer_bridges(void)
                if (pci_find_bus(0, n))
                        continue;
                for (devfn = 0; devfn < 256; devfn += 8) {
-                       if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
+                       if (!raw_pci_read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
                            l != 0x0000 && l != 0xffff) {
                                DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
                                printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
index 4df637e34f813da1e47839c75d9cd3fc502bc560..8d54df4dfaad551518bcbf77cbe0be20d0f36562 100644 (file)
 #define MMCONFIG_APER_MIN      (2 * 1024*1024)
 #define MMCONFIG_APER_MAX      (256 * 1024*1024)
 
-DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
 /* Indicate if the mmcfg resources have been placed into the resource table. */
 static int __initdata pci_mmcfg_resources_inserted;
 
-/* K8 systems have some devices (typically in the builtin northbridge)
-   that are only accessible using type1
-   Normally this can be expressed in the MCFG by not listing them
-   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
-   Instead try to discover all devices on bus 0 that are unreachable using MM
-   and fallback for them. */
-static void __init unreachable_devices(void)
-{
-       int i, bus;
-       /* Use the max bus number from ACPI here? */
-       for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
-               for (i = 0; i < 32; i++) {
-                       unsigned int devfn = PCI_DEVFN(i, 0);
-                       u32 val1, val2;
-
-                       pci_conf1_read(0, bus, devfn, 0, 4, &val1);
-                       if (val1 == 0xffffffff)
-                               continue;
-
-                       if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
-                               raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
-                               if (val1 == val2)
-                                       continue;
-                       }
-                       set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
-                       printk(KERN_NOTICE "PCI: No mmconfig possible on device"
-                              " %02x:%02x\n", bus, i);
-               }
-       }
-}
-
 static const char __init *pci_mmcfg_e7520(void)
 {
        u32 win;
-       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
+       pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win);
 
        win = win & 0xf000;
        if(win == 0x0000 || win == 0xf000)
@@ -86,7 +53,7 @@ static const char __init *pci_mmcfg_intel_945(void)
 
        pci_mmcfg_config_num = 1;
 
-       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
+       pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar);
 
        /* Enable bit */
        if (!(pciexbar & 1))
@@ -151,7 +118,7 @@ static int __init pci_mmcfg_check_hostbridge(void)
        int i;
        const char *name;
 
-       pci_conf1_read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
+       pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0, 4, &l);
        vendor = l & 0xffff;
        device = (l >> 16) & 0xffff;
 
@@ -270,8 +237,6 @@ void __init pci_mmcfg_init(int type)
                return;
 
        if (pci_mmcfg_arch_init()) {
-               if (type == 1)
-                       unreachable_devices();
                if (known_bridge)
                        pci_mmcfg_insert_resources(IORESOURCE_BUSY);
                pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
index 1bf5816d34c85e294717fecf082bdd90baf26f38..081816ada05792dc87d670db497a7ecf500534ba 100644 (file)
@@ -30,10 +30,6 @@ static u32 get_base_addr(unsigned int seg, int bus, unsigned devfn)
        struct acpi_mcfg_allocation *cfg;
        int cfg_num;
 
-       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
-           test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
-               return 0;
-
        for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
                cfg = &pci_mmcfg_config[cfg_num];
                if (cfg->pci_segment == seg &&
@@ -68,13 +64,13 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
        u32 base;
 
        if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
-               *value = -1;
+err:           *value = -1;
                return -EINVAL;
        }
 
        base = get_base_addr(seg, bus, devfn);
        if (!base)
-               return pci_conf1_read(seg,bus,devfn,reg,len,value);
+               goto err;
 
        spin_lock_irqsave(&pci_config_lock, flags);
 
@@ -107,7 +103,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 
        base = get_base_addr(seg, bus, devfn);
        if (!base)
-               return pci_conf1_write(seg,bus,devfn,reg,len,value);
+               return -EINVAL;
 
        spin_lock_irqsave(&pci_config_lock, flags);
 
@@ -134,15 +130,9 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
-int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                   unsigned int devfn)
-{
-       return get_base_addr(seg, bus, devfn) != 0;
-}
-
 int __init pci_mmcfg_arch_init(void)
 {
-       printk(KERN_INFO "PCI: Using MMCONFIG\n");
-       raw_pci_ops = &pci_mmcfg;
+       printk(KERN_INFO "PCI: Using MMCONFIG for extended config space\n");
+       raw_pci_ext_ops = &pci_mmcfg;
        return 1;
 }
index 4095e4d66a1d9345b236ee514260db23cf94c64b..9207fd49233c1f120f6bbbd3e4b7c87f77c671b3 100644 (file)
@@ -40,9 +40,7 @@ static char __iomem *get_virt(unsigned int seg, unsigned bus)
 static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
 {
        char __iomem *addr;
-       if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
-               test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots))
-               return NULL;
+
        addr = get_virt(seg, bus);
        if (!addr)
                return NULL;
@@ -56,13 +54,13 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
 
        /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
        if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
-               *value = -1;
+err:           *value = -1;
                return -EINVAL;
        }
 
        addr = pci_dev_base(seg, bus, devfn);
        if (!addr)
-               return pci_conf1_read(seg,bus,devfn,reg,len,value);
+               goto err;
 
        switch (len) {
        case 1:
@@ -90,7 +88,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 
        addr = pci_dev_base(seg, bus, devfn);
        if (!addr)
-               return pci_conf1_write(seg,bus,devfn,reg,len,value);
+               return -EINVAL;
 
        switch (len) {
        case 1:
@@ -126,12 +124,6 @@ static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
        return addr;
 }
 
-int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                   unsigned int devfn)
-{
-       return pci_dev_base(seg, bus, devfn) != NULL;
-}
-
 int __init pci_mmcfg_arch_init(void)
 {
        int i;
@@ -152,6 +144,6 @@ int __init pci_mmcfg_arch_init(void)
                        return 0;
                }
        }
-       raw_pci_ops = &pci_mmcfg;
+       raw_pci_ext_ops = &pci_mmcfg;
        return 1;
 }
index ac56d3916c50e3491ff6ca0421950a3f3a3efc39..3431518d921ac3cb79f1dece168e272f5539da4b 100644 (file)
@@ -85,10 +85,17 @@ extern spinlock_t pci_config_lock;
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
 extern void (*pcibios_disable_irq)(struct pci_dev *dev);
 
-extern int pci_conf1_write(unsigned int seg, unsigned int bus,
-                          unsigned int devfn, int reg, int len, u32 value);
-extern int pci_conf1_read(unsigned int seg, unsigned int bus,
-                         unsigned int devfn, int reg, int len, u32 *value);
+struct pci_raw_ops {
+       int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
+                                               int reg, int len, u32 *val);
+       int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
+                                               int reg, int len, u32 val);
+};
+
+extern struct pci_raw_ops *raw_pci_ops;
+extern struct pci_raw_ops *raw_pci_ext_ops;
+
+extern struct pci_raw_ops pci_direct_conf1;
 
 extern int pci_direct_probe(void);
 extern void pci_direct_init(int type);
@@ -98,13 +105,6 @@ extern void pcibios_sort(void);
 
 /* pci-mmconfig.c */
 
-/* Verify the first 16 busses. We assume that systems with more busses
-   get MCFG right. */
-#define PCI_MMCFG_MAX_CHECK_BUS 16
-extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
-
-extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
-                                          unsigned int devfn);
 extern int __init pci_mmcfg_arch_init(void);
 
 /*
index 8ecb1c72259497348be3c5c899655516a255697c..c2df4e97eed6ea4d66a971811471e03a3c3ddaa9 100644 (file)
@@ -13,9 +13,6 @@
 
 #include "pci.h"
 
-
-extern struct pci_raw_ops pci_direct_conf1;
-
 static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
 static void pci_visws_disable_irq(struct pci_dev *dev) { }
 
index d764ec950065686d96bbd92e49440de08e538270..9ff4d5b55ad182852ef5c4fd2dbb11a372525275 100644 (file)
@@ -1,2 +1,2 @@
-obj-$(CONFIG_PM)               += cpu.o
-obj-$(CONFIG_HIBERNATION)      += swsusp.o suspend.o
+obj-$(CONFIG_PM_SLEEP)         += cpu_$(BITS).o
+obj-$(CONFIG_HIBERNATION)      += hibernate_$(BITS).o hibernate_asm_$(BITS).o
similarity index 99%
rename from arch/x86/power/cpu.c
rename to arch/x86/power/cpu_32.c
index efcf620d1439490b7311fe4aa05f6d3ce4f7df75..7f9c6da04a4c143a01f9529125b775052cfb35d1 100644 (file)
@@ -40,7 +40,7 @@ static void __save_processor_state(struct saved_context *ctxt)
        savesegment(ss, ctxt->ss);
 
        /*
-        * control registers 
+        * control registers
         */
        ctxt->cr0 = read_cr0();
        ctxt->cr2 = read_cr2();
similarity index 53%
rename from arch/x86/kernel/suspend_64.c
rename to arch/x86/power/cpu_64.c
index 7ac7130022f1a73926a392ee2a83d1c366d29164..66bdfb591fd8b0adcc1d8181d3d1fcfb14f71808 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * Suspend support specific for i386.
+ * Suspend and hibernation support for x86-64
  *
  * Distribute under GPLv2
  *
+ * Copyright (c) 2007 Rafael J. Wysocki <rjw@sisk.pl>
  * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
  * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
  */
@@ -14,9 +15,6 @@
 #include <asm/pgtable.h>
 #include <asm/mtrr.h>
 
-/* References to section boundaries */
-extern const void __nosave_begin, __nosave_end;
-
 static void fix_processor_context(void);
 
 struct saved_context saved_context;
@@ -63,7 +61,7 @@ static void __save_processor_state(struct saved_context *ctxt)
        mtrr_save_fixed_ranges(NULL);
 
        /*
-        * control registers 
+        * control registers
         */
        rdmsrl(MSR_EFER, ctxt->efer);
        ctxt->cr0 = read_cr0();
@@ -166,155 +164,3 @@ static void fix_processor_context(void)
                 loaddebug(&current->thread, 7);
        }
 }
-
-#ifdef CONFIG_HIBERNATION
-/* Defined in arch/x86_64/kernel/suspend_asm.S */
-extern int restore_image(void);
-
-/*
- * Address to jump to in the last phase of restore in order to get to the image
- * kernel's text (this value is passed in the image header).
- */
-unsigned long restore_jump_address;
-
-/*
- * Value of the cr3 register from before the hibernation (this value is passed
- * in the image header).
- */
-unsigned long restore_cr3;
-
-pgd_t *temp_level4_pgt;
-
-void *relocated_restore_code;
-
-static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
-{
-       long i, j;
-
-       i = pud_index(address);
-       pud = pud + i;
-       for (; i < PTRS_PER_PUD; pud++, i++) {
-               unsigned long paddr;
-               pmd_t *pmd;
-
-               paddr = address + i*PUD_SIZE;
-               if (paddr >= end)
-                       break;
-
-               pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
-               if (!pmd)
-                       return -ENOMEM;
-               set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
-               for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
-                       unsigned long pe;
-
-                       if (paddr >= end)
-                               break;
-                       pe = __PAGE_KERNEL_LARGE_EXEC | paddr;
-                       pe &= __supported_pte_mask;
-                       set_pmd(pmd, __pmd(pe));
-               }
-       }
-       return 0;
-}
-
-static int set_up_temporary_mappings(void)
-{
-       unsigned long start, end, next;
-       int error;
-
-       temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
-       if (!temp_level4_pgt)
-               return -ENOMEM;
-
-       /* It is safe to reuse the original kernel mapping */
-       set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
-               init_level4_pgt[pgd_index(__START_KERNEL_map)]);
-
-       /* Set up the direct mapping from scratch */
-       start = (unsigned long)pfn_to_kaddr(0);
-       end = (unsigned long)pfn_to_kaddr(end_pfn);
-
-       for (; start < end; start = next) {
-               pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC);
-               if (!pud)
-                       return -ENOMEM;
-               next = start + PGDIR_SIZE;
-               if (next > end)
-                       next = end;
-               if ((error = res_phys_pud_init(pud, __pa(start), __pa(next))))
-                       return error;
-               set_pgd(temp_level4_pgt + pgd_index(start),
-                       mk_kernel_pgd(__pa(pud)));
-       }
-       return 0;
-}
-
-int swsusp_arch_resume(void)
-{
-       int error;
-
-       /* We have got enough memory and from now on we cannot recover */
-       if ((error = set_up_temporary_mappings()))
-               return error;
-
-       relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
-       if (!relocated_restore_code)
-               return -ENOMEM;
-       memcpy(relocated_restore_code, &core_restore_code,
-              &restore_registers - &core_restore_code);
-
-       restore_image();
-       return 0;
-}
-
-/*
- *     pfn_is_nosave - check if given pfn is in the 'nosave' section
- */
-
-int pfn_is_nosave(unsigned long pfn)
-{
-       unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
-       unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
-       return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
-}
-
-struct restore_data_record {
-       unsigned long jump_address;
-       unsigned long cr3;
-       unsigned long magic;
-};
-
-#define RESTORE_MAGIC  0x0123456789ABCDEFUL
-
-/**
- *     arch_hibernation_header_save - populate the architecture specific part
- *             of a hibernation image header
- *     @addr: address to save the data at
- */
-int arch_hibernation_header_save(void *addr, unsigned int max_size)
-{
-       struct restore_data_record *rdr = addr;
-
-       if (max_size < sizeof(struct restore_data_record))
-               return -EOVERFLOW;
-       rdr->jump_address = restore_jump_address;
-       rdr->cr3 = restore_cr3;
-       rdr->magic = RESTORE_MAGIC;
-       return 0;
-}
-
-/**
- *     arch_hibernation_header_restore - read the architecture specific data
- *             from the hibernation image header
- *     @addr: address to read the data from
- */
-int arch_hibernation_header_restore(void *addr)
-{
-       struct restore_data_record *rdr = addr;
-
-       restore_jump_address = rdr->jump_address;
-       restore_cr3 = rdr->cr3;
-       return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
-}
-#endif /* CONFIG_HIBERNATION */
similarity index 96%
rename from arch/x86/power/suspend.c
rename to arch/x86/power/hibernate_32.c
index a0020b913f3126afaaa1b6d17dc6246c16894736..f2b6e3f11bfc58214dcbccdd87acdaa6a5d4b9a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Suspend support specific for i386 - temporary page tables
+ * Hibernation support specific for i386 - temporary page tables
  *
  * Distribute under GPLv2
  *
@@ -13,7 +13,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
-/* Defined in arch/i386/power/swsusp.S */
+/* Defined in hibernate_asm_32.S */
 extern int restore_image(void);
 
 /* References to section boundaries */
@@ -23,7 +23,7 @@ extern const void __nosave_begin, __nosave_end;
 pgd_t *resume_pg_dir;
 
 /* The following three functions are based on the analogous code in
- * arch/i386/mm/init.c
+ * arch/x86/mm/init_32.c
  */
 
 /*
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
new file mode 100644 (file)
index 0000000..b542355
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Hibernation support for x86-64
+ *
+ * Distribute under GPLv2
+ *
+ * Copyright (c) 2007 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright (c) 2002 Pavel Machek <pavel@suse.cz>
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ */
+
+#include <linux/smp.h>
+#include <linux/suspend.h>
+#include <asm/proto.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mtrr.h>
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+/* Defined in hibernate_asm_64.S */
+extern int restore_image(void);
+
+/*
+ * Address to jump to in the last phase of restore in order to get to the image
+ * kernel's text (this value is passed in the image header).
+ */
+unsigned long restore_jump_address;
+
+/*
+ * Value of the cr3 register from before the hibernation (this value is passed
+ * in the image header).
+ */
+unsigned long restore_cr3;
+
+pgd_t *temp_level4_pgt;
+
+void *relocated_restore_code;
+
+static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+{
+       long i, j;
+
+       i = pud_index(address);
+       pud = pud + i;
+       for (; i < PTRS_PER_PUD; pud++, i++) {
+               unsigned long paddr;
+               pmd_t *pmd;
+
+               paddr = address + i*PUD_SIZE;
+               if (paddr >= end)
+                       break;
+
+               pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
+               if (!pmd)
+                       return -ENOMEM;
+               set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+               for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) {
+                       unsigned long pe;
+
+                       if (paddr >= end)
+                               break;
+                       pe = __PAGE_KERNEL_LARGE_EXEC | paddr;
+                       pe &= __supported_pte_mask;
+                       set_pmd(pmd, __pmd(pe));
+               }
+       }
+       return 0;
+}
+
+static int set_up_temporary_mappings(void)
+{
+       unsigned long start, end, next;
+       int error;
+
+       temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
+       if (!temp_level4_pgt)
+               return -ENOMEM;
+
+       /* It is safe to reuse the original kernel mapping */
+       set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
+               init_level4_pgt[pgd_index(__START_KERNEL_map)]);
+
+       /* Set up the direct mapping from scratch */
+       start = (unsigned long)pfn_to_kaddr(0);
+       end = (unsigned long)pfn_to_kaddr(end_pfn);
+
+       for (; start < end; start = next) {
+               pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+               if (!pud)
+                       return -ENOMEM;
+               next = start + PGDIR_SIZE;
+               if (next > end)
+                       next = end;
+               if ((error = res_phys_pud_init(pud, __pa(start), __pa(next))))
+                       return error;
+               set_pgd(temp_level4_pgt + pgd_index(start),
+                       mk_kernel_pgd(__pa(pud)));
+       }
+       return 0;
+}
+
+int swsusp_arch_resume(void)
+{
+       int error;
+
+       /* We have got enough memory and from now on we cannot recover */
+       if ((error = set_up_temporary_mappings()))
+               return error;
+
+       relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
+       if (!relocated_restore_code)
+               return -ENOMEM;
+       memcpy(relocated_restore_code, &core_restore_code,
+              &restore_registers - &core_restore_code);
+
+       restore_image();
+       return 0;
+}
+
+/*
+ *     pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+       unsigned long nosave_begin_pfn = __pa_symbol(&__nosave_begin) >> PAGE_SHIFT;
+       unsigned long nosave_end_pfn = PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT;
+       return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
+}
+
+struct restore_data_record {
+       unsigned long jump_address;
+       unsigned long cr3;
+       unsigned long magic;
+};
+
+#define RESTORE_MAGIC  0x0123456789ABCDEFUL
+
+/**
+ *     arch_hibernation_header_save - populate the architecture specific part
+ *             of a hibernation image header
+ *     @addr: address to save the data at
+ */
+int arch_hibernation_header_save(void *addr, unsigned int max_size)
+{
+       struct restore_data_record *rdr = addr;
+
+       if (max_size < sizeof(struct restore_data_record))
+               return -EOVERFLOW;
+       rdr->jump_address = restore_jump_address;
+       rdr->cr3 = restore_cr3;
+       rdr->magic = RESTORE_MAGIC;
+       return 0;
+}
+
+/**
+ *     arch_hibernation_header_restore - read the architecture specific data
+ *             from the hibernation image header
+ *     @addr: address to read the data from
+ */
+int arch_hibernation_header_restore(void *addr)
+{
+       struct restore_data_record *rdr = addr;
+
+       restore_jump_address = rdr->jump_address;
+       restore_cr3 = rdr->cr3;
+       return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
+}
similarity index 96%
rename from arch/x86/power/swsusp.S
rename to arch/x86/power/hibernate_asm_32.S
index 53662e05b393e2c294734c71577705a5beb550c0..b95aa6cfe3cb207befad0a4337678317ec1f9606 100644 (file)
@@ -1,7 +1,6 @@
 .text
 
-/* Originally gcc generated, modified by hand
- *
+/*
  * This may not use any stack, nor any variable that is not "NoSave":
  *
  * Its rewriting one kernel image with another. What is stack in "old"
similarity index 95%
rename from arch/x86/kernel/suspend_asm_64.S
rename to arch/x86/power/hibernate_asm_64.S
index aeb9a4d7681e5b8c93157c9e146f3b7f950ed47e..1deb3244b99b766977565019790516ea98c48211 100644 (file)
@@ -1,7 +1,12 @@
-/* Copyright 2004,2005 Pavel Machek <pavel@suse.cz>, Andi Kleen <ak@suse.de>, Rafael J. Wysocki <rjw@sisk.pl>
+/*
+ * Hibernation support for x86-64
  *
  * Distribute under GPLv2.
  *
+ * Copyright 2007 Rafael J. Wysocki <rjw@sisk.pl>
+ * Copyright 2005 Andi Kleen <ak@suse.de>
+ * Copyright 2004 Pavel Machek <pavel@suse.cz>
+ *
  * swsusp_arch_resume must not use any stack or any nonlocal variables while
  * copying pages:
  *
@@ -9,7 +14,7 @@
  * image could very well be data page in "new" image, and overwriting
  * your own stack under you is bad idea.
  */
-       
+
        .text
 #include <linux/linkage.h>
 #include <asm/segment.h>
index 45aa771e73a9221792f703e99c980ada406c8fa9..0144395448ae8775c2609ecfb0c0072197e9b35b 100644 (file)
@@ -58,7 +58,7 @@
 
 xmaddr_t arbitrary_virt_to_machine(unsigned long address)
 {
-       int level;
+       unsigned int level;
        pte_t *pte = lookup_address(address, &level);
        unsigned offset = address & PAGE_MASK;
 
@@ -71,7 +71,7 @@ void make_lowmem_page_readonly(void *vaddr)
 {
        pte_t *pte, ptev;
        unsigned long address = (unsigned long)vaddr;
-       int level;
+       unsigned int level;
 
        pte = lookup_address(address, &level);
        BUG_ON(pte == NULL);
@@ -86,7 +86,7 @@ void make_lowmem_page_readwrite(void *vaddr)
 {
        pte_t *pte, ptev;
        unsigned long address = (unsigned long)vaddr;
-       int level;
+       unsigned int level;
 
        pte = lookup_address(address, &level);
        BUG_ON(pte == NULL);
index b3721fd6877b1ea03f1d22cc12c5c1a8566ef04a..c39e1a5aa241bcce2cb2a070d2dbbe391a28ae31 100644 (file)
@@ -217,17 +217,17 @@ unsigned long long xen_sched_clock(void)
 /* Get the CPU speed from Xen */
 unsigned long xen_cpu_khz(void)
 {
-       u64 cpu_khz = 1000000ULL << 32;
+       u64 xen_khz = 1000000ULL << 32;
        const struct vcpu_time_info *info =
                &HYPERVISOR_shared_info->vcpu_info[0].time;
 
-       do_div(cpu_khz, info->tsc_to_system_mul);
+       do_div(xen_khz, info->tsc_to_system_mul);
        if (info->tsc_shift < 0)
-               cpu_khz <<= -info->tsc_shift;
+               xen_khz <<= -info->tsc_shift;
        else
-               cpu_khz >>= info->tsc_shift;
+               xen_khz >>= info->tsc_shift;
 
-       return cpu_khz;
+       return xen_khz;
 }
 
 /*
index fd36764d7fb72358a65a3551ad9a0faf7b4a70e1..9fc8551a1cf685c53fce6564a004d40642bf3acc 100644 (file)
@@ -14,6 +14,7 @@ config ZONE_DMA
 config XTENSA
        bool
        default y
+       select HAVE_IDE
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
          primarily for embedded systems.  These processors are both
index b86877bdc7ac50ede83ed0e311c52e692548ef3f..3a0e3549739f5980c6458d53c135f33878346ead 100644 (file)
@@ -80,6 +80,8 @@ source "drivers/usb/Kconfig"
 
 source "drivers/mmc/Kconfig"
 
+source "drivers/memstick/Kconfig"
+
 source "drivers/leds/Kconfig"
 
 source "drivers/infiniband/Kconfig"
index 30ba97ec5eb525eefd89807600490c7f0dac0854..e5e394a7e6c0873be132cb10086b7a89c93332d7 100644 (file)
@@ -78,6 +78,7 @@ obj-y                         += lguest/
 obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_CPU_IDLE)         += cpuidle/
 obj-$(CONFIG_MMC)              += mmc/
+obj-$(CONFIG_MEMSTICK)         += memstick/
 obj-$(CONFIG_NEW_LEDS)         += leds/
 obj-$(CONFIG_INFINIBAND)       += infiniband/
 obj-$(CONFIG_SGI_SN)           += sn/
index f29812a86533778a28b211b5c601bcf4863fadc9..40b0fcae4c78a71ac083119c96f6396e6e3bab07 100644 (file)
@@ -60,5 +60,5 @@ obj-$(CONFIG_ACPI_ASUS)               += asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)     += toshiba_acpi.o
 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)      += acpi_memhotplug.o
 obj-$(CONFIG_ACPI_PROCFS_POWER)        += cm_sbs.o
-obj-$(CONFIG_ACPI_SBS)         += sbs.o
 obj-$(CONFIG_ACPI_SBS)         += sbshc.o
+obj-$(CONFIG_ACPI_SBS)         += sbs.o
index 8b0d4b7d188a4b2cae701f50459cd80f39fd4a63..ce3c0a2cbac4dc81e9c5ff2712b100ec8a942b46 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/pm.h>
 #include <linux/device.h>
 #include <linux/proc_fs.h>
+#include <linux/acpi.h>
 #ifdef CONFIG_X86
 #include <asm/mpspec.h>
 #endif
@@ -39,9 +40,6 @@
 
 #define _COMPONENT             ACPI_BUS_COMPONENT
 ACPI_MODULE_NAME("bus");
-#ifdef CONFIG_X86
-extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
-#endif
 
 struct acpi_device *acpi_root;
 struct proc_dir_entry *acpi_root_dir;
@@ -653,8 +651,6 @@ void __init acpi_early_init(void)
 
 #ifdef CONFIG_X86
        if (!acpi_ioapic) {
-               extern u8 acpi_sci_flags;
-
                /* compatible (0) means level (3) */
                if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) {
                        acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK;
@@ -664,7 +660,6 @@ void __init acpi_early_init(void)
                acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt,
                                         (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
        } else {
-               extern int acpi_sci_override_gsi;
                /*
                 * now that acpi_gbl_FADT is initialized,
                 * update it with result from INT_SRC_OVR parsing
index a14501c98f40908f7b415e18490914320c720d4e..34b3386dedca8ca4b70451ebeb63069bad1e1345 100644 (file)
@@ -200,15 +200,6 @@ acpi_status __init acpi_os_initialize(void)
 
 acpi_status acpi_os_initialize1(void)
 {
-       /*
-        * Initialize PCI configuration space access, as we'll need to access
-        * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
-        */
-       if (!raw_pci_ops) {
-               printk(KERN_ERR PREFIX
-                      "Access to PCI configuration space unavailable\n");
-               return AE_NULL_ENTRY;
-       }
        kacpid_wq = create_singlethread_workqueue("kacpid");
        kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
        BUG_ON(!kacpid_wq);
@@ -653,11 +644,9 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
                return AE_ERROR;
        }
 
-       BUG_ON(!raw_pci_ops);
-
-       result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
-                                  PCI_DEVFN(pci_id->device, pci_id->function),
-                                  reg, size, value);
+       result = raw_pci_read(pci_id->segment, pci_id->bus,
+                               PCI_DEVFN(pci_id->device, pci_id->function),
+                               reg, size, value);
 
        return (result ? AE_ERROR : AE_OK);
 }
@@ -682,11 +671,9 @@ acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
                return AE_ERROR;
        }
 
-       BUG_ON(!raw_pci_ops);
-
-       result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
-                                   PCI_DEVFN(pci_id->device, pci_id->function),
-                                   reg, size, value);
+       result = raw_pci_write(pci_id->segment, pci_id->bus,
+                               PCI_DEVFN(pci_id->device, pci_id->function),
+                               reg, size, value);
 
        return (result ? AE_ERROR : AE_OK);
 }
index 1194105cc3cad977c5472a528ba8a261a870d2a8..585ae3c9c8ea98651e33f46de53876fac237f48d 100644 (file)
@@ -827,7 +827,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
 #endif
        printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
               ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
-              battery->name, sbs->battery->present ? "present" : "absent");
+              battery->name, battery->present ? "present" : "absent");
        return result;
 }
 
index ae9a90438e2f32f497e207889bf4677c431c3383..a2cf3008ce6c03eb40ad564d3063700896a68d03 100644 (file)
@@ -117,6 +117,11 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
        int ret = -EFAULT, i;
        u8 temp, sz = 0;
 
+       if (!hc) {
+               printk(KERN_ERR PREFIX "host controller is not configured\n");
+               return ret;
+       }
+
        mutex_lock(&hc->lock);
        if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
                goto end;
@@ -292,6 +297,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
        hc = acpi_driver_data(device);
        acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
        kfree(hc);
+       acpi_driver_data(device) = NULL;
        return 0;
 }
 
index a70c1c29a7aa2c28e99c9fa352fa6f42b2048d17..c452e2d355eeb303bce96fbcddec96002f0449e2 100644 (file)
@@ -657,7 +657,6 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
        if ((cmd = ub_get_cmd(lun)) == NULL)
                return -1;
        memset(cmd, 0, sizeof(struct ub_scsi_cmd));
-       sg_init_table(cmd->sgv, UB_MAX_REQ_SG);
 
        blkdev_dequeue_request(rq);
 
@@ -668,6 +667,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
        /*
         * get scatterlist from block layer
         */
+       sg_init_table(&urq->sgv[0], UB_MAX_REQ_SG);
        n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
        if (n_elem < 0) {
                /* Impossible, because blk_rq_map_sg should not hit ENOMEM. */
index f01ac9a07bf5533a7b8917775aff88f0eb5ff901..47c6be84fc842c7855883d4fb93d2257a5637fe7 100644 (file)
@@ -875,7 +875,7 @@ config SONYPI
          Device which can be found in many (all ?) Sony Vaio laptops.
 
          If you have one of those laptops, read
-         <file:Documentation/sonypi.txt>, and say Y or M here.
+         <file:Documentation/laptops/sonypi.txt>, and say Y or M here.
 
          To compile this driver as a module, choose M here: the
          module will be called sonypi.
index 2c4b2d47973e195cbb0422a9b539400a2ad5ef5e..60f71e6345e32ac11747d1dbd608349650172189 100644 (file)
@@ -27,6 +27,17 @@ static void (*pm_idle_old)(void);
 
 static int enabled_devices;
 
+#if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
+static void cpuidle_kick_cpus(void)
+{
+       cpu_idle_wait();
+}
+#elif defined(CONFIG_SMP)
+# error "Arch needs cpu_idle_wait() equivalent here"
+#else /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT && !CONFIG_SMP */
+static void cpuidle_kick_cpus(void) {}
+#endif
+
 /**
  * cpuidle_idle_call - the main idle loop
  *
@@ -83,7 +94,7 @@ void cpuidle_uninstall_idle_handler(void)
 {
        if (enabled_devices && (pm_idle != pm_idle_old)) {
                pm_idle = pm_idle_old;
-               cpu_idle_wait();
+               cpuidle_kick_cpus();
        }
 }
 
index ab8fb257528ed51cb4e9bac0abb0710ce7543fbb..043c34ad0a05fee2659972d8e66ba41dcf9277b0 100644 (file)
@@ -4,10 +4,14 @@
 # Andre Hedrick <andre@linux-ide.org>
 #
 
+# Select HAVE_IDE if IDE is supported
+config HAVE_IDE
+       def_bool n
+
 menuconfig IDE
        tristate "ATA/ATAPI/MFM/RLL support"
+       depends on HAVE_IDE
        depends on BLOCK
-       depends on HAS_IOMEM
        ---help---
          If you say Y here, your kernel will be able to manage low cost mass
          storage units such as ATA/(E)IDE and ATAPI units. The most common
index c87fa3f9b298f4f6aa25b338b82ff492d8a6cfde..3039c6d68fc414606240a87f397348f0a5b5917d 100644 (file)
@@ -213,8 +213,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
        return 0;
 }
 
-int
-setup_avm_a1_pcmcia(struct IsdnCard *card)
+int __devinit setup_avm_a1_pcmcia(struct IsdnCard *card)
 {
        u_char model, vers;
        struct IsdnCardState *cs = card->cs;
index 97097ef3491e6622e4188136d224d3b38297c612..a0ee43c04dd507eb0302064e2d749c233009e59c 100644 (file)
@@ -847,7 +847,7 @@ static int init_card(struct IsdnCardState *cs)
        return 3;
 }
 
-static int hisax_cs_setup_card(struct IsdnCard *card)
+static int __devinit hisax_cs_setup_card(struct IsdnCard *card)
 {
        int ret;
 
@@ -1166,7 +1166,10 @@ outf_cs:
        return 0;
 }
 
-static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
+/* Used from an exported function but calls __devinit functions.
+ * Tell modpost not to warn (__ref)
+ */
+static int __ref checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
 {
        int ret;
        struct IsdnCard *card = cards + cardnr;
index 4fd09d21a27f587c52e9fd1485ab7132dff1151b..05482d2688e3f1742607147eea1c09992172a5e9 100644 (file)
@@ -1330,8 +1330,7 @@ hfcsx_bh(struct work_struct *work)
 /********************************/
 /* called for card init message */
 /********************************/
-static void __devinit
-inithfcsx(struct IsdnCardState *cs)
+static void inithfcsx(struct IsdnCardState *cs)
 {
        cs->setstack_d = setstack_hfcsx;
        cs->BC_Send_Data = &hfcsx_send_data;
index 4e9f23803daef8767388f16677c46182006543fe..07b1673122b8a8a6d34cb431cb2073281af78a24 100644 (file)
@@ -27,8 +27,7 @@ static char *ISACVer[] __devinitdata =
 {"2086/2186 V1.1", "2085 B1", "2085 B2",
  "2085 V2.3"};
 
-void
-ISACVersion(struct IsdnCardState *cs, char *s)
+void __devinit ISACVersion(struct IsdnCardState *cs, char *s)
 {
        int val;
 
@@ -616,8 +615,7 @@ dbusy_timer_handler(struct IsdnCardState *cs)
        }
 }
 
-void __devinit
-initisac(struct IsdnCardState *cs)
+void initisac(struct IsdnCardState *cs)
 {
        cs->setstack_d = setstack_isac;
        cs->DC_Close = DC_Close_isac;
@@ -648,8 +646,7 @@ initisac(struct IsdnCardState *cs)
        cs->writeisac(cs, ISAC_MASK, 0x0);
 }
 
-void __devinit
-clear_pending_isac_ints(struct IsdnCardState *cs)
+void clear_pending_isac_ints(struct IsdnCardState *cs)
 {
        int val, eval;
 
index c547a666505231be9847c50a84f7bd89f070a4a0..bfeb9b6aa04370e118f9eee04d0d29a454fb03d3 100644 (file)
@@ -1894,8 +1894,7 @@ isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
        return(0);
 }
 
-void __devinit
-initisar(struct IsdnCardState *cs)
+void initisar(struct IsdnCardState *cs)
 {
        cs->bcs[0].BC_SetStack = setstack_isar;
        cs->bcs[1].BC_SetStack = setstack_isar;
index 74b4cf2a6c417743c9556610961ef66b9dbf0bbf..275f23c2deb49ff302e836abfb4eb14e26395a06 100644 (file)
@@ -178,8 +178,8 @@ static void release_pte(pte_t pte)
 
 static void check_gpte(struct lg_cpu *cpu, pte_t gpte)
 {
-       if ((pte_flags(gpte) & (_PAGE_PWT|_PAGE_PSE))
-           || pte_pfn(gpte) >= cpu->lg->pfn_limit)
+       if ((pte_flags(gpte) & _PAGE_PSE) ||
+           pte_pfn(gpte) >= cpu->lg->pfn_limit)
                kill_guest(cpu, "bad page table entry");
 }
 
index abbd38c1ebba896f06256d75a8f145ef363ebfbd..0f7a0bd86ff4e87a0485f90f162f876a1f2f1202 100644 (file)
@@ -13,7 +13,8 @@ config VIDEO_EM28XX
          module will be called em28xx
 
 config VIDEO_EM28XX_ALSA
-       depends on VIDEO_EM28XX
+       depends on VIDEO_EM28XX && SND
+       select SND_PCM
        tristate "Empia EM28xx ALSA audio module"
        ---help---
          This is an ALSA driver for some Empia 28xx based TV cards.
diff --git a/drivers/memstick/Kconfig b/drivers/memstick/Kconfig
new file mode 100644 (file)
index 0000000..1093fdb
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# MemoryStick subsystem configuration
+#
+
+menuconfig MEMSTICK
+       tristate "Sony MemoryStick card support (EXPERIMENTAL)"
+       help
+         Sony MemoryStick is a proprietary storage/extension card protocol.
+
+         If you want MemoryStick support, you should say Y here and also
+         to the specific driver for your MMC interface.
+
+if MEMSTICK
+
+config MEMSTICK_DEBUG
+       bool "MemoryStick debugging"
+       help
+         This is an option for use by developers; most people should
+         say N here.  This enables MemoryStick core and driver debugging.
+
+
+source "drivers/memstick/core/Kconfig"
+
+source "drivers/memstick/host/Kconfig"
+
+endif # MEMSTICK
diff --git a/drivers/memstick/Makefile b/drivers/memstick/Makefile
new file mode 100644 (file)
index 0000000..dc160fb
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel MemoryStick device drivers.
+#
+
+ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
+obj-$(CONFIG_MEMSTICK)         += core/
+obj-$(CONFIG_MEMSTICK)         += host/
+
diff --git a/drivers/memstick/core/Kconfig b/drivers/memstick/core/Kconfig
new file mode 100644 (file)
index 0000000..95f1814
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# MemoryStick core configuration
+#
+
+comment "MemoryStick drivers"
+
+config MEMSTICK_UNSAFE_RESUME
+        bool "Allow unsafe resume (DANGEROUS)"
+        help
+          If you say Y here, the MemoryStick layer will assume that all
+          cards stayed in their respective slots during the suspend. The
+          normal behaviour is to remove them at suspend and
+          redetecting them at resume. Breaking this assumption will
+          in most cases result in data corruption.
+
+          This option is usually just for embedded systems which use
+          a MemoryStick card for rootfs. Most people should say N here.
+
+config MSPRO_BLOCK
+       tristate "MemoryStick Pro block device driver"
+       depends on BLOCK
+       help
+         Say Y here to enable the MemoryStick Pro block device driver
+         support. This provides a block device driver, which you can use
+         to mount the filesystem. Almost everyone wishing MemoryStick
+         support should say Y or M here.
diff --git a/drivers/memstick/core/Makefile b/drivers/memstick/core/Makefile
new file mode 100644 (file)
index 0000000..8b2b529
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel MemoryStick core.
+#
+
+ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
+obj-$(CONFIG_MEMSTICK)         += memstick.o
+
+obj-$(CONFIG_MSPRO_BLOCK)      += mspro_block.o
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
new file mode 100644 (file)
index 0000000..bba467f
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ *  Sony MemoryStick support
+ *
+ *  Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ * 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.
+ *
+ * Special thanks to Carlos Corbacho for providing various MemoryStick cards
+ * that made this driver possible.
+ *
+ */
+
+#include <linux/memstick.h>
+#include <linux/idr.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+
+#define DRIVER_NAME "memstick"
+#define DRIVER_VERSION "0.2"
+
+static unsigned int cmd_retries = 3;
+module_param(cmd_retries, uint, 0644);
+
+static struct workqueue_struct *workqueue;
+static DEFINE_IDR(memstick_host_idr);
+static DEFINE_SPINLOCK(memstick_host_lock);
+
+static int memstick_dev_match(struct memstick_dev *card,
+                             struct memstick_device_id *id)
+{
+       if (id->match_flags & MEMSTICK_MATCH_ALL) {
+               if ((id->type == card->id.type)
+                   && (id->category == card->id.category)
+                   && (id->class == card->id.class))
+                       return 1;
+       }
+
+       return 0;
+}
+
+static int memstick_bus_match(struct device *dev, struct device_driver *drv)
+{
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,
+                                                dev);
+       struct memstick_driver *ms_drv = container_of(drv,
+                                                     struct memstick_driver,
+                                                     driver);
+       struct memstick_device_id *ids = ms_drv->id_table;
+
+       if (ids) {
+               while (ids->match_flags) {
+                       if (memstick_dev_match(card, ids))
+                               return 1;
+                       ++ids;
+               }
+       }
+       return 0;
+}
+
+static int memstick_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,
+                                                 dev);
+
+       if (add_uevent_var(env, "MEMSTICK_TYPE=%02X", card->id.type))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "MEMSTICK_CATEGORY=%02X", card->id.category))
+               return -ENOMEM;
+
+       if (add_uevent_var(env, "MEMSTICK_CLASS=%02X", card->id.class))
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int memstick_device_probe(struct device *dev)
+{
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,
+                                                dev);
+       struct memstick_driver *drv = container_of(dev->driver,
+                                                  struct memstick_driver,
+                                                  driver);
+       int rc = -ENODEV;
+
+       if (dev->driver && drv->probe) {
+               rc = drv->probe(card);
+               if (!rc)
+                       get_device(dev);
+       }
+       return rc;
+}
+
+static int memstick_device_remove(struct device *dev)
+{
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,
+                                                 dev);
+       struct memstick_driver *drv = container_of(dev->driver,
+                                                  struct memstick_driver,
+                                                  driver);
+
+       if (dev->driver && drv->remove) {
+               drv->remove(card);
+               card->dev.driver = NULL;
+       }
+
+       put_device(dev);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int memstick_device_suspend(struct device *dev, pm_message_t state)
+{
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,
+                                                 dev);
+       struct memstick_driver *drv = container_of(dev->driver,
+                                                  struct memstick_driver,
+                                                  driver);
+
+       if (dev->driver && drv->suspend)
+               return drv->suspend(card, state);
+       return 0;
+}
+
+static int memstick_device_resume(struct device *dev)
+{
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,
+                                                 dev);
+       struct memstick_driver *drv = container_of(dev->driver,
+                                                  struct memstick_driver,
+                                                  driver);
+
+       if (dev->driver && drv->resume)
+               return drv->resume(card);
+       return 0;
+}
+
+#else
+
+#define memstick_device_suspend NULL
+#define memstick_device_resume NULL
+
+#endif /* CONFIG_PM */
+
+#define MEMSTICK_ATTR(name, format)                                           \
+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
+                           char *buf)                                        \
+{                                                                             \
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,    \
+                                                dev);                        \
+       return sprintf(buf, format, card->id.name);                           \
+}
+
+MEMSTICK_ATTR(type, "%02X");
+MEMSTICK_ATTR(category, "%02X");
+MEMSTICK_ATTR(class, "%02X");
+
+#define MEMSTICK_ATTR_RO(name) __ATTR(name, S_IRUGO, name##_show, NULL)
+
+static struct device_attribute memstick_dev_attrs[] = {
+       MEMSTICK_ATTR_RO(type),
+       MEMSTICK_ATTR_RO(category),
+       MEMSTICK_ATTR_RO(class),
+       __ATTR_NULL
+};
+
+static struct bus_type memstick_bus_type = {
+       .name           = "memstick",
+       .dev_attrs      = memstick_dev_attrs,
+       .match          = memstick_bus_match,
+       .uevent         = memstick_uevent,
+       .probe          = memstick_device_probe,
+       .remove         = memstick_device_remove,
+       .suspend        = memstick_device_suspend,
+       .resume         = memstick_device_resume
+};
+
+static void memstick_free(struct class_device *cdev)
+{
+       struct memstick_host *host = container_of(cdev, struct memstick_host,
+                                                 cdev);
+       kfree(host);
+}
+
+static struct class memstick_host_class = {
+       .name       = "memstick_host",
+       .release    = memstick_free
+};
+
+static void memstick_free_card(struct device *dev)
+{
+       struct memstick_dev *card = container_of(dev, struct memstick_dev,
+                                                dev);
+       kfree(card);
+}
+
+static int memstick_dummy_check(struct memstick_dev *card)
+{
+       return 0;
+}
+
+/**
+ * memstick_detect_change - schedule media detection on memstick host
+ * @host - host to use
+ */
+void memstick_detect_change(struct memstick_host *host)
+{
+       queue_work(workqueue, &host->media_checker);
+}
+EXPORT_SYMBOL(memstick_detect_change);
+
+/**
+ * memstick_next_req - called by host driver to obtain next request to process
+ * @host - host to use
+ * @mrq - pointer to stick the request to
+ *
+ * Host calls this function from idle state (*mrq == NULL) or after finishing
+ * previous request (*mrq should point to it). If previous request was
+ * unsuccessful, it is retried for predetermined number of times. Return value
+ * of 0 means that new request was assigned to the host.
+ */
+int memstick_next_req(struct memstick_host *host, struct memstick_request **mrq)
+{
+       int rc = -ENXIO;
+
+       if ((*mrq) && (*mrq)->error && host->retries) {
+               (*mrq)->error = rc;
+               host->retries--;
+               return 0;
+       }
+
+       if (host->card && host->card->next_request)
+               rc = host->card->next_request(host->card, mrq);
+
+       if (!rc)
+               host->retries = cmd_retries;
+       else
+               *mrq = NULL;
+
+       return rc;
+}
+EXPORT_SYMBOL(memstick_next_req);
+
+/**
+ * memstick_new_req - notify the host that some requests are pending
+ * @host - host to use
+ */
+void memstick_new_req(struct memstick_host *host)
+{
+       host->retries = cmd_retries;
+       host->request(host);
+}
+EXPORT_SYMBOL(memstick_new_req);
+
+/**
+ * memstick_init_req_sg - set request fields needed for bulk data transfer
+ * @mrq - request to use
+ * @tpc - memstick Transport Protocol Command
+ * @sg - TPC argument
+ */
+void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
+                         struct scatterlist *sg)
+{
+       mrq->tpc = tpc;
+       if (tpc & 8)
+               mrq->data_dir = WRITE;
+       else
+               mrq->data_dir = READ;
+
+       mrq->sg = *sg;
+       mrq->io_type = MEMSTICK_IO_SG;
+
+       if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
+               mrq->need_card_int = 1;
+       else
+               mrq->need_card_int = 0;
+
+       mrq->get_int_reg = 0;
+}
+EXPORT_SYMBOL(memstick_init_req_sg);
+
+/**
+ * memstick_init_req - set request fields needed for short data transfer
+ * @mrq - request to use
+ * @tpc - memstick Transport Protocol Command
+ * @buf - TPC argument buffer
+ * @length - TPC argument size
+ *
+ * The intended use of this function (transfer of data items several bytes
+ * in size) allows us to just copy the value between request structure and
+ * user supplied buffer.
+ */
+void memstick_init_req(struct memstick_request *mrq, unsigned char tpc,
+                      void *buf, size_t length)
+{
+       mrq->tpc = tpc;
+       if (tpc & 8)
+               mrq->data_dir = WRITE;
+       else
+               mrq->data_dir = READ;
+
+       mrq->data_len = length > sizeof(mrq->data) ? sizeof(mrq->data) : length;
+       if (mrq->data_dir == WRITE)
+               memcpy(mrq->data, buf, mrq->data_len);
+
+       mrq->io_type = MEMSTICK_IO_VAL;
+
+       if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
+               mrq->need_card_int = 1;
+       else
+               mrq->need_card_int = 0;
+
+       mrq->get_int_reg = 0;
+}
+EXPORT_SYMBOL(memstick_init_req);
+
+/*
+ * Functions prefixed with "h_" are protocol callbacks. They can be called from
+ * interrupt context. Return value of 0 means that request processing is still
+ * ongoing, while special error value of -EAGAIN means that current request is
+ * finished (and request processor should come back some time later).
+ */
+
+static int h_memstick_read_dev_id(struct memstick_dev *card,
+                                 struct memstick_request **mrq)
+{
+       struct ms_id_register id_reg;
+
+       if (!(*mrq)) {
+               memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL,
+                                 sizeof(struct ms_id_register));
+               *mrq = &card->current_mrq;
+               return 0;
+       } else {
+               if (!(*mrq)->error) {
+                       memcpy(&id_reg, (*mrq)->data, sizeof(id_reg));
+                       card->id.match_flags = MEMSTICK_MATCH_ALL;
+                       card->id.type = id_reg.type;
+                       card->id.category = id_reg.category;
+                       card->id.class = id_reg.class;
+               }
+               complete(&card->mrq_complete);
+               return -EAGAIN;
+       }
+}
+
+static int h_memstick_set_rw_addr(struct memstick_dev *card,
+                                 struct memstick_request **mrq)
+{
+       if (!(*mrq)) {
+               memstick_init_req(&card->current_mrq, MS_TPC_SET_RW_REG_ADRS,
+                                 (char *)&card->reg_addr,
+                                 sizeof(card->reg_addr));
+               *mrq = &card->current_mrq;
+               return 0;
+       } else {
+               complete(&card->mrq_complete);
+               return -EAGAIN;
+       }
+}
+
+/**
+ * memstick_set_rw_addr - issue SET_RW_REG_ADDR request and wait for it to
+ *                        complete
+ * @card - media device to use
+ */
+int memstick_set_rw_addr(struct memstick_dev *card)
+{
+       card->next_request = h_memstick_set_rw_addr;
+       memstick_new_req(card->host);
+       wait_for_completion(&card->mrq_complete);
+
+       return card->current_mrq.error;
+}
+EXPORT_SYMBOL(memstick_set_rw_addr);
+
+static struct memstick_dev *memstick_alloc_card(struct memstick_host *host)
+{
+       struct memstick_dev *card = kzalloc(sizeof(struct memstick_dev),
+                                           GFP_KERNEL);
+       struct memstick_dev *old_card = host->card;
+       struct ms_id_register id_reg;
+
+       if (card) {
+               card->host = host;
+               snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+                        "%s", host->cdev.class_id);
+               card->dev.parent = host->cdev.dev;
+               card->dev.bus = &memstick_bus_type;
+               card->dev.release = memstick_free_card;
+               card->check = memstick_dummy_check;
+
+               card->reg_addr.r_offset = offsetof(struct ms_register, id);
+               card->reg_addr.r_length = sizeof(id_reg);
+               card->reg_addr.w_offset = offsetof(struct ms_register, id);
+               card->reg_addr.w_length = sizeof(id_reg);
+
+               init_completion(&card->mrq_complete);
+
+               host->card = card;
+               if (memstick_set_rw_addr(card))
+                       goto err_out;
+
+               card->next_request = h_memstick_read_dev_id;
+               memstick_new_req(host);
+               wait_for_completion(&card->mrq_complete);
+
+               if (card->current_mrq.error)
+                       goto err_out;
+       }
+       host->card = old_card;
+       return card;
+err_out:
+       host->card = old_card;
+       kfree(card);
+       return NULL;
+}
+
+static void memstick_power_on(struct memstick_host *host)
+{
+       host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
+       host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
+       msleep(1);
+}
+
+static void memstick_check(struct work_struct *work)
+{
+       struct memstick_host *host = container_of(work, struct memstick_host,
+                                                 media_checker);
+       struct memstick_dev *card;
+
+       dev_dbg(host->cdev.dev, "memstick_check started\n");
+       mutex_lock(&host->lock);
+       if (!host->card)
+               memstick_power_on(host);
+
+       card = memstick_alloc_card(host);
+
+       if (!card) {
+               if (host->card) {
+                       device_unregister(&host->card->dev);
+                       host->card = NULL;
+               }
+       } else {
+               dev_dbg(host->cdev.dev, "new card %02x, %02x, %02x\n",
+                       card->id.type, card->id.category, card->id.class);
+               if (host->card) {
+                       if (memstick_set_rw_addr(host->card)
+                           || !memstick_dev_match(host->card, &card->id)
+                           || !(host->card->check(host->card))) {
+                               device_unregister(&host->card->dev);
+                               host->card = NULL;
+                       }
+               }
+
+               if (!host->card) {
+                       host->card = card;
+                       if (device_register(&card->dev)) {
+                               kfree(host->card);
+                               host->card = NULL;
+                       }
+               } else
+                       kfree(card);
+       }
+
+       if (!host->card)
+               host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+
+       mutex_unlock(&host->lock);
+       dev_dbg(host->cdev.dev, "memstick_check finished\n");
+}
+
+/**
+ * memstick_alloc_host - allocate a memstick_host structure
+ * @extra: size of the user private data to allocate
+ * @dev: parent device of the host
+ */
+struct memstick_host *memstick_alloc_host(unsigned int extra,
+                                         struct device *dev)
+{
+       struct memstick_host *host;
+
+       host = kzalloc(sizeof(struct memstick_host) + extra, GFP_KERNEL);
+       if (host) {
+               mutex_init(&host->lock);
+               INIT_WORK(&host->media_checker, memstick_check);
+               host->cdev.class = &memstick_host_class;
+               host->cdev.dev = dev;
+               class_device_initialize(&host->cdev);
+       }
+       return host;
+}
+EXPORT_SYMBOL(memstick_alloc_host);
+
+/**
+ * memstick_add_host - start request processing on memstick host
+ * @host - host to use
+ */
+int memstick_add_host(struct memstick_host *host)
+{
+       int rc;
+
+       if (!idr_pre_get(&memstick_host_idr, GFP_KERNEL))
+               return -ENOMEM;
+
+       spin_lock(&memstick_host_lock);
+       rc = idr_get_new(&memstick_host_idr, host, &host->id);
+       spin_unlock(&memstick_host_lock);
+       if (rc)
+               return rc;
+
+       snprintf(host->cdev.class_id, BUS_ID_SIZE,
+                "memstick%u", host->id);
+
+       rc = class_device_add(&host->cdev);
+       if (rc) {
+               spin_lock(&memstick_host_lock);
+               idr_remove(&memstick_host_idr, host->id);
+               spin_unlock(&memstick_host_lock);
+               return rc;
+       }
+
+       host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+       memstick_detect_change(host);
+       return 0;
+}
+EXPORT_SYMBOL(memstick_add_host);
+
+/**
+ * memstick_remove_host - stop request processing on memstick host
+ * @host - host to use
+ */
+void memstick_remove_host(struct memstick_host *host)
+{
+       flush_workqueue(workqueue);
+       mutex_lock(&host->lock);
+       if (host->card)
+               device_unregister(&host->card->dev);
+       host->card = NULL;
+       host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
+       mutex_unlock(&host->lock);
+
+       spin_lock(&memstick_host_lock);
+       idr_remove(&memstick_host_idr, host->id);
+       spin_unlock(&memstick_host_lock);
+       class_device_del(&host->cdev);
+}
+EXPORT_SYMBOL(memstick_remove_host);
+
+/**
+ * memstick_free_host - free memstick host
+ * @host - host to use
+ */
+void memstick_free_host(struct memstick_host *host)
+{
+       mutex_destroy(&host->lock);
+       class_device_put(&host->cdev);
+}
+EXPORT_SYMBOL(memstick_free_host);
+
+int memstick_register_driver(struct memstick_driver *drv)
+{
+       drv->driver.bus = &memstick_bus_type;
+
+       return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(memstick_register_driver);
+
+void memstick_unregister_driver(struct memstick_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(memstick_unregister_driver);
+
+
+static int __init memstick_init(void)
+{
+       int rc;
+
+       workqueue = create_freezeable_workqueue("kmemstick");
+       if (!workqueue)
+               return -ENOMEM;
+
+       rc = bus_register(&memstick_bus_type);
+       if (!rc)
+               rc = class_register(&memstick_host_class);
+
+       if (!rc)
+               return 0;
+
+       bus_unregister(&memstick_bus_type);
+       destroy_workqueue(workqueue);
+
+       return rc;
+}
+
+static void __exit memstick_exit(void)
+{
+       class_unregister(&memstick_host_class);
+       bus_unregister(&memstick_bus_type);
+       destroy_workqueue(workqueue);
+       idr_destroy(&memstick_host_idr);
+}
+
+module_init(memstick_init);
+module_exit(memstick_exit);
+
+MODULE_AUTHOR("Alex Dubov");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Sony MemoryStick core driver");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
new file mode 100644 (file)
index 0000000..423ad8c
--- /dev/null
@@ -0,0 +1,1351 @@
+/*
+ *  Sony MemoryStick Pro storage support
+ *
+ *  Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ * 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.
+ *
+ * Special thanks to Carlos Corbacho for providing various MemoryStick cards
+ * that made this driver possible.
+ *
+ */
+
+#include <linux/blkdev.h>
+#include <linux/idr.h>
+#include <linux/hdreg.h>
+#include <linux/kthread.h>
+#include <linux/memstick.h>
+
+#define DRIVER_NAME "mspro_block"
+#define DRIVER_VERSION "0.2"
+
+static int major;
+module_param(major, int, 0644);
+
+#define MSPRO_BLOCK_MAX_SEGS  32
+#define MSPRO_BLOCK_MAX_PAGES ((2 << 16) - 1)
+
+#define MSPRO_BLOCK_SIGNATURE        0xa5c3
+#define MSPRO_BLOCK_MAX_ATTRIBUTES   41
+
+enum {
+       MSPRO_BLOCK_ID_SYSINFO         = 0x10,
+       MSPRO_BLOCK_ID_MODELNAME       = 0x15,
+       MSPRO_BLOCK_ID_MBR             = 0x20,
+       MSPRO_BLOCK_ID_PBR16           = 0x21,
+       MSPRO_BLOCK_ID_PBR32           = 0x22,
+       MSPRO_BLOCK_ID_SPECFILEVALUES1 = 0x25,
+       MSPRO_BLOCK_ID_SPECFILEVALUES2 = 0x26,
+       MSPRO_BLOCK_ID_DEVINFO         = 0x30
+};
+
+struct mspro_sys_attr {
+       size_t                  size;
+       void                    *data;
+       unsigned char           id;
+       char                    name[32];
+       struct device_attribute dev_attr;
+};
+
+struct mspro_attr_entry {
+       unsigned int  address;
+       unsigned int  size;
+       unsigned char id;
+       unsigned char reserved[3];
+} __attribute__((packed));
+
+struct mspro_attribute {
+       unsigned short          signature;
+       unsigned short          version;
+       unsigned char           count;
+       unsigned char           reserved[11];
+       struct mspro_attr_entry entries[];
+} __attribute__((packed));
+
+struct mspro_sys_info {
+       unsigned char  class;
+       unsigned char  reserved0;
+       unsigned short block_size;
+       unsigned short block_count;
+       unsigned short user_block_count;
+       unsigned short page_size;
+       unsigned char  reserved1[2];
+       unsigned char  assembly_date[8];
+       unsigned int   serial_number;
+       unsigned char  assembly_maker_code;
+       unsigned char  assembly_model_code[3];
+       unsigned short memory_maker_code;
+       unsigned short memory_model_code;
+       unsigned char  reserved2[4];
+       unsigned char  vcc;
+       unsigned char  vpp;
+       unsigned short controller_number;
+       unsigned short controller_function;
+       unsigned short start_sector;
+       unsigned short unit_size;
+       unsigned char  ms_sub_class;
+       unsigned char  reserved3[4];
+       unsigned char  interface_type;
+       unsigned short controller_code;
+       unsigned char  format_type;
+       unsigned char  reserved4;
+       unsigned char  device_type;
+       unsigned char  reserved5[7];
+       unsigned char  mspro_id[16];
+       unsigned char  reserved6[16];
+} __attribute__((packed));
+
+struct mspro_mbr {
+       unsigned char boot_partition;
+       unsigned char start_head;
+       unsigned char start_sector;
+       unsigned char start_cylinder;
+       unsigned char partition_type;
+       unsigned char end_head;
+       unsigned char end_sector;
+       unsigned char end_cylinder;
+       unsigned int  start_sectors;
+       unsigned int  sectors_per_partition;
+} __attribute__((packed));
+
+struct mspro_devinfo {
+       unsigned short cylinders;
+       unsigned short heads;
+       unsigned short bytes_per_track;
+       unsigned short bytes_per_sector;
+       unsigned short sectors_per_track;
+       unsigned char  reserved[6];
+} __attribute__((packed));
+
+struct mspro_block_data {
+       struct memstick_dev   *card;
+       unsigned int          usage_count;
+       struct gendisk        *disk;
+       struct request_queue  *queue;
+       spinlock_t            q_lock;
+       wait_queue_head_t     q_wait;
+       struct task_struct    *q_thread;
+
+       unsigned short        page_size;
+       unsigned short        cylinders;
+       unsigned short        heads;
+       unsigned short        sectors_per_track;
+
+       unsigned char         system;
+       unsigned char         read_only:1,
+                             active:1,
+                             has_request:1,
+                             data_dir:1;
+       unsigned char         transfer_cmd;
+
+       int                   (*mrq_handler)(struct memstick_dev *card,
+                                            struct memstick_request **mrq);
+
+       struct attribute_group attr_group;
+
+       struct scatterlist    req_sg[MSPRO_BLOCK_MAX_SEGS];
+       unsigned int          seg_count;
+       unsigned int          current_seg;
+       unsigned short        current_page;
+};
+
+static DEFINE_IDR(mspro_block_disk_idr);
+static DEFINE_MUTEX(mspro_block_disk_lock);
+
+/*** Block device ***/
+
+static int mspro_block_bd_open(struct inode *inode, struct file *filp)
+{
+       struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct mspro_block_data *msb = disk->private_data;
+       int rc = -ENXIO;
+
+       mutex_lock(&mspro_block_disk_lock);
+
+       if (msb && msb->card) {
+               msb->usage_count++;
+               if ((filp->f_mode & FMODE_WRITE) && msb->read_only)
+                       rc = -EROFS;
+               else
+                       rc = 0;
+       }
+
+       mutex_unlock(&mspro_block_disk_lock);
+
+       return rc;
+}
+
+
+static int mspro_block_disk_release(struct gendisk *disk)
+{
+       struct mspro_block_data *msb = disk->private_data;
+       int disk_id = disk->first_minor >> MEMSTICK_PART_SHIFT;
+
+       mutex_lock(&mspro_block_disk_lock);
+
+       if (msb->usage_count) {
+               msb->usage_count--;
+               if (!msb->usage_count) {
+                       kfree(msb);
+                       disk->private_data = NULL;
+                       idr_remove(&mspro_block_disk_idr, disk_id);
+                       put_disk(disk);
+               }
+       }
+
+       mutex_unlock(&mspro_block_disk_lock);
+
+       return 0;
+}
+
+static int mspro_block_bd_release(struct inode *inode, struct file *filp)
+{
+       struct gendisk *disk = inode->i_bdev->bd_disk;
+       return mspro_block_disk_release(disk);
+}
+
+static int mspro_block_bd_getgeo(struct block_device *bdev,
+                                struct hd_geometry *geo)
+{
+       struct mspro_block_data *msb = bdev->bd_disk->private_data;
+
+       geo->heads = msb->heads;
+       geo->sectors = msb->sectors_per_track;
+       geo->cylinders = msb->cylinders;
+
+       return 0;
+}
+
+static struct block_device_operations ms_block_bdops = {
+       .open    = mspro_block_bd_open,
+       .release = mspro_block_bd_release,
+       .getgeo  = mspro_block_bd_getgeo,
+       .owner   = THIS_MODULE
+};
+
+/*** Information ***/
+
+static struct mspro_sys_attr *mspro_from_sysfs_attr(struct attribute *attr)
+{
+       struct device_attribute *dev_attr
+               = container_of(attr, struct device_attribute, attr);
+       return container_of(dev_attr, struct mspro_sys_attr, dev_attr);
+}
+
+static const char *mspro_block_attr_name(unsigned char tag)
+{
+       switch (tag) {
+       case MSPRO_BLOCK_ID_SYSINFO:
+               return "attr_sysinfo";
+       case MSPRO_BLOCK_ID_MODELNAME:
+               return "attr_modelname";
+       case MSPRO_BLOCK_ID_MBR:
+               return "attr_mbr";
+       case MSPRO_BLOCK_ID_PBR16:
+               return "attr_pbr16";
+       case MSPRO_BLOCK_ID_PBR32:
+               return "attr_pbr32";
+       case MSPRO_BLOCK_ID_SPECFILEVALUES1:
+               return "attr_specfilevalues1";
+       case MSPRO_BLOCK_ID_SPECFILEVALUES2:
+               return "attr_specfilevalues2";
+       case MSPRO_BLOCK_ID_DEVINFO:
+               return "attr_devinfo";
+       default:
+               return NULL;
+       };
+}
+
+typedef ssize_t (*sysfs_show_t)(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buffer);
+
+static ssize_t mspro_block_attr_show_default(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buffer)
+{
+       struct mspro_sys_attr *s_attr = container_of(attr,
+                                                    struct mspro_sys_attr,
+                                                    dev_attr);
+
+       ssize_t cnt, rc = 0;
+
+       for (cnt = 0; cnt < s_attr->size; cnt++) {
+               if (cnt && !(cnt % 16)) {
+                       if (PAGE_SIZE - rc)
+                               buffer[rc++] = '\n';
+               }
+
+               rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "%02x ",
+                               ((unsigned char *)s_attr->data)[cnt]);
+       }
+       return rc;
+}
+
+static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buffer)
+{
+       struct mspro_sys_attr *x_attr = container_of(attr,
+                                                    struct mspro_sys_attr,
+                                                    dev_attr);
+       struct mspro_sys_info *x_sys = x_attr->data;
+       ssize_t rc = 0;
+
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n",
+                       x_sys->class);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block size: %x\n",
+                       be16_to_cpu(x_sys->block_size));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "block count: %x\n",
+                       be16_to_cpu(x_sys->block_count));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "user block count: %x\n",
+                       be16_to_cpu(x_sys->user_block_count));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n",
+                       be16_to_cpu(x_sys->page_size));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: "
+                       "%d %04u-%02u-%02u %02u:%02u:%02u\n",
+                       x_sys->assembly_date[0],
+                       be16_to_cpu(*(unsigned short *)
+                                   &x_sys->assembly_date[1]),
+                       x_sys->assembly_date[3], x_sys->assembly_date[4],
+                       x_sys->assembly_date[5], x_sys->assembly_date[6],
+                       x_sys->assembly_date[7]);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "serial number: %x\n",
+                       be32_to_cpu(x_sys->serial_number));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc,
+                       "assembly maker code: %x\n",
+                       x_sys->assembly_maker_code);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly model code: "
+                       "%02x%02x%02x\n", x_sys->assembly_model_code[0],
+                       x_sys->assembly_model_code[1],
+                       x_sys->assembly_model_code[2]);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory maker code: %x\n",
+                       be16_to_cpu(x_sys->memory_maker_code));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "memory model code: %x\n",
+                       be16_to_cpu(x_sys->memory_model_code));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vcc: %x\n",
+                       x_sys->vcc);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "vpp: %x\n",
+                       x_sys->vpp);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller number: %x\n",
+                       be16_to_cpu(x_sys->controller_number));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc,
+                       "controller function: %x\n",
+                       be16_to_cpu(x_sys->controller_function));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n",
+                       be16_to_cpu(x_sys->start_sector));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "unit size: %x\n",
+                       be16_to_cpu(x_sys->unit_size));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sub class: %x\n",
+                       x_sys->ms_sub_class);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "interface type: %x\n",
+                       x_sys->interface_type);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "controller code: %x\n",
+                       be16_to_cpu(x_sys->controller_code));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "format type: %x\n",
+                       x_sys->format_type);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "device type: %x\n",
+                       x_sys->device_type);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "mspro id: %s\n",
+                       x_sys->mspro_id);
+       return rc;
+}
+
+static ssize_t mspro_block_attr_show_modelname(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buffer)
+{
+       struct mspro_sys_attr *s_attr = container_of(attr,
+                                                    struct mspro_sys_attr,
+                                                    dev_attr);
+
+       return scnprintf(buffer, PAGE_SIZE, "%s", (char *)s_attr->data);
+}
+
+static ssize_t mspro_block_attr_show_mbr(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buffer)
+{
+       struct mspro_sys_attr *x_attr = container_of(attr,
+                                                    struct mspro_sys_attr,
+                                                    dev_attr);
+       struct mspro_mbr *x_mbr = x_attr->data;
+       ssize_t rc = 0;
+
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "boot partition: %x\n",
+                       x_mbr->boot_partition);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start head: %x\n",
+                       x_mbr->start_head);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sector: %x\n",
+                       x_mbr->start_sector);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cylinder: %x\n",
+                       x_mbr->start_cylinder);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "partition type: %x\n",
+                       x_mbr->partition_type);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end head: %x\n",
+                       x_mbr->end_head);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end sector: %x\n",
+                       x_mbr->end_sector);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "end cylinder: %x\n",
+                       x_mbr->end_cylinder);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start sectors: %x\n",
+                       x_mbr->start_sectors);
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc,
+                       "sectors per partition: %x\n",
+                       x_mbr->sectors_per_partition);
+       return rc;
+}
+
+static ssize_t mspro_block_attr_show_devinfo(struct device *dev,
+                                            struct device_attribute *attr,
+                                            char *buffer)
+{
+       struct mspro_sys_attr *x_attr = container_of(attr,
+                                                    struct mspro_sys_attr,
+                                                    dev_attr);
+       struct mspro_devinfo *x_devinfo = x_attr->data;
+       ssize_t rc = 0;
+
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "cylinders: %x\n",
+                       be16_to_cpu(x_devinfo->cylinders));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "heads: %x\n",
+                       be16_to_cpu(x_devinfo->heads));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per track: %x\n",
+                       be16_to_cpu(x_devinfo->bytes_per_track));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "bytes per sector: %x\n",
+                       be16_to_cpu(x_devinfo->bytes_per_sector));
+       rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "sectors per track: %x\n",
+                       be16_to_cpu(x_devinfo->sectors_per_track));
+       return rc;
+}
+
+static sysfs_show_t mspro_block_attr_show(unsigned char tag)
+{
+       switch (tag) {
+       case MSPRO_BLOCK_ID_SYSINFO:
+               return mspro_block_attr_show_sysinfo;
+       case MSPRO_BLOCK_ID_MODELNAME:
+               return mspro_block_attr_show_modelname;
+       case MSPRO_BLOCK_ID_MBR:
+               return mspro_block_attr_show_mbr;
+       case MSPRO_BLOCK_ID_DEVINFO:
+               return mspro_block_attr_show_devinfo;
+       default:
+               return mspro_block_attr_show_default;
+       }
+}
+
+/*** Protocol handlers ***/
+
+/*
+ * Functions prefixed with "h_" are protocol callbacks. They can be called from
+ * interrupt context. Return value of 0 means that request processing is still
+ * ongoing, while special error value of -EAGAIN means that current request is
+ * finished (and request processor should come back some time later).
+ */
+
+static int h_mspro_block_req_init(struct memstick_dev *card,
+                                 struct memstick_request **mrq)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+
+       *mrq = &card->current_mrq;
+       card->next_request = msb->mrq_handler;
+       return 0;
+}
+
+static int h_mspro_block_default(struct memstick_dev *card,
+                                struct memstick_request **mrq)
+{
+       complete(&card->mrq_complete);
+       if (!(*mrq)->error)
+               return -EAGAIN;
+       else
+               return (*mrq)->error;
+}
+
+static int h_mspro_block_get_ro(struct memstick_dev *card,
+                               struct memstick_request **mrq)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+
+       if ((*mrq)->error) {
+               complete(&card->mrq_complete);
+               return (*mrq)->error;
+       }
+
+       if ((*mrq)->data[offsetof(struct ms_status_register, status0)]
+           & MEMSTICK_STATUS0_WP)
+               msb->read_only = 1;
+       else
+               msb->read_only = 0;
+
+       complete(&card->mrq_complete);
+       return -EAGAIN;
+}
+
+static int h_mspro_block_wait_for_ced(struct memstick_dev *card,
+                                     struct memstick_request **mrq)
+{
+       if ((*mrq)->error) {
+               complete(&card->mrq_complete);
+               return (*mrq)->error;
+       }
+
+       dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]);
+
+       if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) {
+               card->current_mrq.error = -EFAULT;
+               complete(&card->mrq_complete);
+               return card->current_mrq.error;
+       }
+
+       if (!((*mrq)->data[0] & MEMSTICK_INT_CED))
+               return 0;
+       else {
+               card->current_mrq.error = 0;
+               complete(&card->mrq_complete);
+               return -EAGAIN;
+       }
+}
+
+static int h_mspro_block_transfer_data(struct memstick_dev *card,
+                                      struct memstick_request **mrq)
+{
+       struct memstick_host *host = card->host;
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       unsigned char t_val = 0;
+       struct scatterlist t_sg = { 0 };
+       size_t t_offset;
+
+       if ((*mrq)->error) {
+               complete(&card->mrq_complete);
+               return (*mrq)->error;
+       }
+
+       switch ((*mrq)->tpc) {
+       case MS_TPC_WRITE_REG:
+               memstick_init_req(*mrq, MS_TPC_SET_CMD, &msb->transfer_cmd, 1);
+               (*mrq)->get_int_reg = 1;
+               return 0;
+       case MS_TPC_SET_CMD:
+               t_val = (*mrq)->int_reg;
+               memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
+               if (host->caps & MEMSTICK_CAP_AUTO_GET_INT)
+                       goto has_int_reg;
+               return 0;
+       case MS_TPC_GET_INT:
+               t_val = (*mrq)->data[0];
+has_int_reg:
+               if (t_val & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR)) {
+                       t_val = MSPRO_CMD_STOP;
+                       memstick_init_req(*mrq, MS_TPC_SET_CMD, &t_val, 1);
+                       card->next_request = h_mspro_block_default;
+                       return 0;
+               }
+
+               if (msb->current_page
+                   == (msb->req_sg[msb->current_seg].length
+                       / msb->page_size)) {
+                       msb->current_page = 0;
+                       msb->current_seg++;
+
+                       if (msb->current_seg == msb->seg_count) {
+                               if (t_val & MEMSTICK_INT_CED) {
+                                       complete(&card->mrq_complete);
+                                       return -EAGAIN;
+                               } else {
+                                       card->next_request
+                                               = h_mspro_block_wait_for_ced;
+                                       memstick_init_req(*mrq, MS_TPC_GET_INT,
+                                                         NULL, 1);
+                                       return 0;
+                               }
+                       }
+               }
+
+               if (!(t_val & MEMSTICK_INT_BREQ)) {
+                       memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
+                       return 0;
+               }
+
+               t_offset = msb->req_sg[msb->current_seg].offset;
+               t_offset += msb->current_page * msb->page_size;
+
+               sg_set_page(&t_sg,
+                           nth_page(sg_page(&(msb->req_sg[msb->current_seg])),
+                                    t_offset >> PAGE_SHIFT),
+                           msb->page_size, offset_in_page(t_offset));
+
+               memstick_init_req_sg(*mrq, msb->data_dir == READ
+                                          ? MS_TPC_READ_LONG_DATA
+                                          : MS_TPC_WRITE_LONG_DATA,
+                                    &t_sg);
+               (*mrq)->get_int_reg = 1;
+               return 0;
+       case MS_TPC_READ_LONG_DATA:
+       case MS_TPC_WRITE_LONG_DATA:
+               msb->current_page++;
+               if (host->caps & MEMSTICK_CAP_AUTO_GET_INT) {
+                       t_val = (*mrq)->int_reg;
+                       goto has_int_reg;
+               } else {
+                       memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
+                       return 0;
+               }
+
+       default:
+               BUG();
+       }
+}
+
+/*** Data transfer ***/
+
+static void mspro_block_process_request(struct memstick_dev *card,
+                                       struct request *req)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct mspro_param_register param;
+       int rc, chunk, cnt;
+       unsigned short page_count;
+       sector_t t_sec;
+       unsigned long flags;
+
+       do {
+               page_count = 0;
+               msb->current_seg = 0;
+               msb->seg_count = blk_rq_map_sg(req->q, req, msb->req_sg);
+
+               if (msb->seg_count) {
+                       msb->current_page = 0;
+                       for (rc = 0; rc < msb->seg_count; rc++)
+                               page_count += msb->req_sg[rc].length
+                                             / msb->page_size;
+
+                       t_sec = req->sector;
+                       sector_div(t_sec, msb->page_size >> 9);
+                       param.system = msb->system;
+                       param.data_count = cpu_to_be16(page_count);
+                       param.data_address = cpu_to_be32((uint32_t)t_sec);
+                       param.cmd_param = 0;
+
+                       msb->data_dir = rq_data_dir(req);
+                       msb->transfer_cmd = msb->data_dir == READ
+                                           ? MSPRO_CMD_READ_DATA
+                                           : MSPRO_CMD_WRITE_DATA;
+
+                       dev_dbg(&card->dev, "data transfer: cmd %x, "
+                               "lba %x, count %x\n", msb->transfer_cmd,
+                               be32_to_cpu(param.data_address),
+                               page_count);
+
+                       card->next_request = h_mspro_block_req_init;
+                       msb->mrq_handler = h_mspro_block_transfer_data;
+                       memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
+                                         &param, sizeof(param));
+                       memstick_new_req(card->host);
+                       wait_for_completion(&card->mrq_complete);
+                       rc = card->current_mrq.error;
+
+                       if (rc || (card->current_mrq.tpc == MSPRO_CMD_STOP)) {
+                               for (cnt = 0; cnt < msb->current_seg; cnt++)
+                                       page_count += msb->req_sg[cnt].length
+                                                     / msb->page_size;
+
+                               if (msb->current_page)
+                                       page_count += msb->current_page - 1;
+
+                               if (page_count && (msb->data_dir == READ))
+                                       rc = msb->page_size * page_count;
+                               else
+                                       rc = -EIO;
+                       } else
+                               rc = msb->page_size * page_count;
+               } else
+                       rc = -EFAULT;
+
+               spin_lock_irqsave(&msb->q_lock, flags);
+               if (rc >= 0)
+                       chunk = __blk_end_request(req, 0, rc);
+               else
+                       chunk = __blk_end_request(req, rc, 0);
+
+               dev_dbg(&card->dev, "end chunk %d, %d\n", rc, chunk);
+               spin_unlock_irqrestore(&msb->q_lock, flags);
+       } while (chunk);
+}
+
+static int mspro_block_has_request(struct mspro_block_data *msb)
+{
+       int rc = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&msb->q_lock, flags);
+       if (kthread_should_stop() || msb->has_request)
+               rc = 1;
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+       return rc;
+}
+
+static int mspro_block_queue_thread(void *data)
+{
+       struct memstick_dev *card = data;
+       struct memstick_host *host = card->host;
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct request *req;
+       unsigned long flags;
+
+       while (1) {
+               wait_event(msb->q_wait, mspro_block_has_request(msb));
+               dev_dbg(&card->dev, "thread iter\n");
+
+               spin_lock_irqsave(&msb->q_lock, flags);
+               req = elv_next_request(msb->queue);
+               dev_dbg(&card->dev, "next req %p\n", req);
+               if (!req) {
+                       msb->has_request = 0;
+                       if (kthread_should_stop()) {
+                               spin_unlock_irqrestore(&msb->q_lock, flags);
+                               break;
+                       }
+               } else
+                       msb->has_request = 1;
+               spin_unlock_irqrestore(&msb->q_lock, flags);
+
+               if (req) {
+                       mutex_lock(&host->lock);
+                       mspro_block_process_request(card, req);
+                       mutex_unlock(&host->lock);
+               }
+       }
+       dev_dbg(&card->dev, "thread finished\n");
+       return 0;
+}
+
+static void mspro_block_request(struct request_queue *q)
+{
+       struct memstick_dev *card = q->queuedata;
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct request *req = NULL;
+
+       if (msb->q_thread) {
+               msb->has_request = 1;
+               wake_up_all(&msb->q_wait);
+       } else {
+               while ((req = elv_next_request(q)) != NULL)
+                       end_queued_request(req, -ENODEV);
+       }
+}
+
+/*** Initialization ***/
+
+static int mspro_block_wait_for_ced(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+
+       card->next_request = h_mspro_block_req_init;
+       msb->mrq_handler = h_mspro_block_wait_for_ced;
+       memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
+       memstick_new_req(card->host);
+       wait_for_completion(&card->mrq_complete);
+       return card->current_mrq.error;
+}
+
+static int mspro_block_switch_to_parallel(struct memstick_dev *card)
+{
+       struct memstick_host *host = card->host;
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct mspro_param_register param = {
+               .system = 0,
+               .data_count = 0,
+               .data_address = 0,
+               .cmd_param = 0
+       };
+
+       card->next_request = h_mspro_block_req_init;
+       msb->mrq_handler = h_mspro_block_default;
+       memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
+                         sizeof(param));
+       memstick_new_req(host);
+       wait_for_completion(&card->mrq_complete);
+       if (card->current_mrq.error)
+               return card->current_mrq.error;
+
+       msb->system = 0;
+       host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PARALLEL);
+
+       card->next_request = h_mspro_block_req_init;
+       msb->mrq_handler = h_mspro_block_default;
+       memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
+       memstick_new_req(card->host);
+       wait_for_completion(&card->mrq_complete);
+
+       if (card->current_mrq.error) {
+               msb->system = 0x80;
+               host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
+               return -EFAULT;
+       }
+
+       return 0;
+}
+
+/* Memory allocated for attributes by this function should be freed by
+ * mspro_block_data_clear, no matter if the initialization process succeded
+ * or failed.
+ */
+static int mspro_block_read_attributes(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct mspro_param_register param = {
+               .system = msb->system,
+               .data_count = cpu_to_be16(1),
+               .data_address = 0,
+               .cmd_param = 0
+       };
+       struct mspro_attribute *attr = NULL;
+       struct mspro_sys_attr *s_attr = NULL;
+       unsigned char *buffer = NULL;
+       int cnt, rc, attr_count;
+       unsigned int addr;
+       unsigned short page_count;
+
+       attr = kmalloc(msb->page_size, GFP_KERNEL);
+       if (!attr)
+               return -ENOMEM;
+
+       sg_init_one(&msb->req_sg[0], attr, msb->page_size);
+       msb->seg_count = 1;
+       msb->current_seg = 0;
+       msb->current_page = 0;
+       msb->data_dir = READ;
+       msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
+
+       card->next_request = h_mspro_block_req_init;
+       msb->mrq_handler = h_mspro_block_transfer_data;
+       memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
+                         sizeof(param));
+       memstick_new_req(card->host);
+       wait_for_completion(&card->mrq_complete);
+       if (card->current_mrq.error) {
+               rc = card->current_mrq.error;
+               goto out_free_attr;
+       }
+
+       if (be16_to_cpu(attr->signature) != MSPRO_BLOCK_SIGNATURE) {
+               printk(KERN_ERR "%s: unrecognized device signature %x\n",
+                      card->dev.bus_id, be16_to_cpu(attr->signature));
+               rc = -ENODEV;
+               goto out_free_attr;
+       }
+
+       if (attr->count > MSPRO_BLOCK_MAX_ATTRIBUTES) {
+               printk(KERN_WARNING "%s: way too many attribute entries\n",
+                      card->dev.bus_id);
+               attr_count = MSPRO_BLOCK_MAX_ATTRIBUTES;
+       } else
+               attr_count = attr->count;
+
+       msb->attr_group.attrs = kzalloc((attr_count + 1)
+                                       * sizeof(struct attribute),
+                                       GFP_KERNEL);
+       if (!msb->attr_group.attrs) {
+               rc = -ENOMEM;
+               goto out_free_attr;
+       }
+       msb->attr_group.name = "media_attributes";
+
+       buffer = kmalloc(msb->page_size, GFP_KERNEL);
+       if (!buffer) {
+               rc = -ENOMEM;
+               goto out_free_attr;
+       }
+       memcpy(buffer, (char *)attr, msb->page_size);
+       page_count = 1;
+
+       for (cnt = 0; cnt < attr_count; ++cnt) {
+               s_attr = kzalloc(sizeof(struct mspro_sys_attr), GFP_KERNEL);
+               if (!s_attr) {
+                       rc = -ENOMEM;
+                       goto out_free_buffer;
+               }
+
+               msb->attr_group.attrs[cnt] = &s_attr->dev_attr.attr;
+               addr = be32_to_cpu(attr->entries[cnt].address);
+               rc = be32_to_cpu(attr->entries[cnt].size);
+               dev_dbg(&card->dev, "adding attribute %d: id %x, address %x, "
+                       "size %x\n", cnt, attr->entries[cnt].id, addr, rc);
+               s_attr->id = attr->entries[cnt].id;
+               if (mspro_block_attr_name(s_attr->id))
+                       snprintf(s_attr->name, sizeof(s_attr->name), "%s",
+                                mspro_block_attr_name(attr->entries[cnt].id));
+               else
+                       snprintf(s_attr->name, sizeof(s_attr->name),
+                                "attr_x%02x", attr->entries[cnt].id);
+
+               s_attr->dev_attr.attr.name = s_attr->name;
+               s_attr->dev_attr.attr.mode = S_IRUGO;
+               s_attr->dev_attr.attr.owner = THIS_MODULE;
+               s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id);
+
+               if (!rc)
+                       continue;
+
+               s_attr->size = rc;
+               s_attr->data = kmalloc(rc, GFP_KERNEL);
+               if (!s_attr->data) {
+                       rc = -ENOMEM;
+                       goto out_free_buffer;
+               }
+
+               if (((addr / msb->page_size)
+                    == be32_to_cpu(param.data_address))
+                   && (((addr + rc - 1) / msb->page_size)
+                       == be32_to_cpu(param.data_address))) {
+                       memcpy(s_attr->data, buffer + addr % msb->page_size,
+                              rc);
+                       continue;
+               }
+
+               if (page_count <= (rc / msb->page_size)) {
+                       kfree(buffer);
+                       page_count = (rc / msb->page_size) + 1;
+                       buffer = kmalloc(page_count * msb->page_size,
+                                        GFP_KERNEL);
+                       if (!buffer) {
+                               rc = -ENOMEM;
+                               goto out_free_attr;
+                       }
+               }
+
+               param.system = msb->system;
+               param.data_count = cpu_to_be16((rc / msb->page_size) + 1);
+               param.data_address = cpu_to_be32(addr / msb->page_size);
+               param.cmd_param = 0;
+
+               sg_init_one(&msb->req_sg[0], buffer,
+                           be16_to_cpu(param.data_count) * msb->page_size);
+               msb->seg_count = 1;
+               msb->current_seg = 0;
+               msb->current_page = 0;
+               msb->data_dir = READ;
+               msb->transfer_cmd = MSPRO_CMD_READ_ATRB;
+
+               dev_dbg(&card->dev, "reading attribute pages %x, %x\n",
+                       be32_to_cpu(param.data_address),
+                       be16_to_cpu(param.data_count));
+
+               card->next_request = h_mspro_block_req_init;
+               msb->mrq_handler = h_mspro_block_transfer_data;
+               memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG,
+                                 (char *)&param, sizeof(param));
+               memstick_new_req(card->host);
+               wait_for_completion(&card->mrq_complete);
+               if (card->current_mrq.error) {
+                       rc = card->current_mrq.error;
+                       goto out_free_buffer;
+               }
+
+               memcpy(s_attr->data, buffer + addr % msb->page_size, rc);
+       }
+
+       rc = 0;
+out_free_buffer:
+       kfree(buffer);
+out_free_attr:
+       kfree(attr);
+       return rc;
+}
+
+static int mspro_block_init_card(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct memstick_host *host = card->host;
+       int rc = 0;
+
+       msb->system = 0x80;
+       card->reg_addr.r_offset = offsetof(struct mspro_register, status);
+       card->reg_addr.r_length = sizeof(struct ms_status_register);
+       card->reg_addr.w_offset = offsetof(struct mspro_register, param);
+       card->reg_addr.w_length = sizeof(struct mspro_param_register);
+
+       if (memstick_set_rw_addr(card))
+               return -EIO;
+
+       if (host->caps & MEMSTICK_CAP_PARALLEL) {
+               if (mspro_block_switch_to_parallel(card))
+                       printk(KERN_WARNING "%s: could not switch to "
+                              "parallel interface\n", card->dev.bus_id);
+       }
+
+       rc = mspro_block_wait_for_ced(card);
+       if (rc)
+               return rc;
+       dev_dbg(&card->dev, "card activated\n");
+
+       card->next_request = h_mspro_block_req_init;
+       msb->mrq_handler = h_mspro_block_get_ro;
+       memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL,
+                         sizeof(struct ms_status_register));
+       memstick_new_req(card->host);
+       wait_for_completion(&card->mrq_complete);
+       if (card->current_mrq.error)
+               return card->current_mrq.error;
+
+       dev_dbg(&card->dev, "card r/w status %d\n", msb->read_only ? 0 : 1);
+
+       msb->page_size = 512;
+       rc = mspro_block_read_attributes(card);
+       if (rc)
+               return rc;
+
+       dev_dbg(&card->dev, "attributes loaded\n");
+       return 0;
+
+}
+
+static int mspro_block_init_disk(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct memstick_host *host = card->host;
+       struct mspro_devinfo *dev_info = NULL;
+       struct mspro_sys_info *sys_info = NULL;
+       struct mspro_sys_attr *s_attr = NULL;
+       int rc, disk_id;
+       u64 limit = BLK_BOUNCE_HIGH;
+       unsigned long capacity;
+
+       if (host->cdev.dev->dma_mask && *(host->cdev.dev->dma_mask))
+               limit = *(host->cdev.dev->dma_mask);
+
+       for (rc = 0; msb->attr_group.attrs[rc]; ++rc) {
+               s_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[rc]);
+
+               if (s_attr->id == MSPRO_BLOCK_ID_DEVINFO)
+                       dev_info = s_attr->data;
+               else if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO)
+                       sys_info = s_attr->data;
+       }
+
+       if (!dev_info || !sys_info)
+               return -ENODEV;
+
+       msb->cylinders = be16_to_cpu(dev_info->cylinders);
+       msb->heads = be16_to_cpu(dev_info->heads);
+       msb->sectors_per_track = be16_to_cpu(dev_info->sectors_per_track);
+
+       msb->page_size = be16_to_cpu(sys_info->unit_size);
+
+       if (!idr_pre_get(&mspro_block_disk_idr, GFP_KERNEL))
+               return -ENOMEM;
+
+       mutex_lock(&mspro_block_disk_lock);
+       rc = idr_get_new(&mspro_block_disk_idr, card, &disk_id);
+       mutex_unlock(&mspro_block_disk_lock);
+
+       if (rc)
+               return rc;
+
+       if ((disk_id << MEMSTICK_PART_SHIFT) > 255) {
+               rc = -ENOSPC;
+               goto out_release_id;
+       }
+
+       msb->disk = alloc_disk(1 << MEMSTICK_PART_SHIFT);
+       if (!msb->disk) {
+               rc = -ENOMEM;
+               goto out_release_id;
+       }
+
+       spin_lock_init(&msb->q_lock);
+       init_waitqueue_head(&msb->q_wait);
+
+       msb->queue = blk_init_queue(mspro_block_request, &msb->q_lock);
+       if (!msb->queue) {
+               rc = -ENOMEM;
+               goto out_put_disk;
+       }
+
+       msb->queue->queuedata = card;
+
+       blk_queue_bounce_limit(msb->queue, limit);
+       blk_queue_max_sectors(msb->queue, MSPRO_BLOCK_MAX_PAGES);
+       blk_queue_max_phys_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS);
+       blk_queue_max_hw_segments(msb->queue, MSPRO_BLOCK_MAX_SEGS);
+       blk_queue_max_segment_size(msb->queue,
+                                  MSPRO_BLOCK_MAX_PAGES * msb->page_size);
+
+       msb->disk->major = major;
+       msb->disk->first_minor = disk_id << MEMSTICK_PART_SHIFT;
+       msb->disk->fops = &ms_block_bdops;
+       msb->usage_count = 1;
+       msb->disk->private_data = msb;
+       msb->disk->queue = msb->queue;
+       msb->disk->driverfs_dev = &card->dev;
+
+       sprintf(msb->disk->disk_name, "mspblk%d", disk_id);
+
+       blk_queue_hardsect_size(msb->queue, msb->page_size);
+
+       capacity = be16_to_cpu(sys_info->user_block_count);
+       capacity *= be16_to_cpu(sys_info->block_size);
+       capacity *= msb->page_size >> 9;
+       set_capacity(msb->disk, capacity);
+       dev_dbg(&card->dev, "capacity set %ld\n", capacity);
+       msb->q_thread = kthread_run(mspro_block_queue_thread, card,
+                                   DRIVER_NAME"d");
+       if (IS_ERR(msb->q_thread))
+               goto out_put_disk;
+
+       mutex_unlock(&host->lock);
+       add_disk(msb->disk);
+       mutex_lock(&host->lock);
+       msb->active = 1;
+       return 0;
+
+out_put_disk:
+       put_disk(msb->disk);
+out_release_id:
+       mutex_lock(&mspro_block_disk_lock);
+       idr_remove(&mspro_block_disk_idr, disk_id);
+       mutex_unlock(&mspro_block_disk_lock);
+       return rc;
+}
+
+static void mspro_block_data_clear(struct mspro_block_data *msb)
+{
+       int cnt;
+       struct mspro_sys_attr *s_attr;
+
+       if (msb->attr_group.attrs) {
+               for (cnt = 0; msb->attr_group.attrs[cnt]; ++cnt) {
+                       s_attr = mspro_from_sysfs_attr(msb->attr_group
+                                                          .attrs[cnt]);
+                       kfree(s_attr->data);
+                       kfree(s_attr);
+               }
+               kfree(msb->attr_group.attrs);
+       }
+
+       msb->card = NULL;
+}
+
+static int mspro_block_check_card(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+
+       return (msb->active == 1);
+}
+
+static int mspro_block_probe(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb;
+       int rc = 0;
+
+       msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL);
+       if (!msb)
+               return -ENOMEM;
+       memstick_set_drvdata(card, msb);
+       msb->card = card;
+
+       rc = mspro_block_init_card(card);
+
+       if (rc)
+               goto out_free;
+
+       rc = sysfs_create_group(&card->dev.kobj, &msb->attr_group);
+       if (rc)
+               goto out_free;
+
+       rc = mspro_block_init_disk(card);
+       if (!rc) {
+               card->check = mspro_block_check_card;
+               return 0;
+       }
+
+       sysfs_remove_group(&card->dev.kobj, &msb->attr_group);
+out_free:
+       memstick_set_drvdata(card, NULL);
+       mspro_block_data_clear(msb);
+       kfree(msb);
+       return rc;
+}
+
+static void mspro_block_remove(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct task_struct *q_thread = NULL;
+       unsigned long flags;
+
+       del_gendisk(msb->disk);
+       dev_dbg(&card->dev, "mspro block remove\n");
+       spin_lock_irqsave(&msb->q_lock, flags);
+       q_thread = msb->q_thread;
+       msb->q_thread = NULL;
+       msb->active = 0;
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+
+       if (q_thread) {
+               mutex_unlock(&card->host->lock);
+               kthread_stop(q_thread);
+               mutex_lock(&card->host->lock);
+       }
+
+       dev_dbg(&card->dev, "queue thread stopped\n");
+
+       blk_cleanup_queue(msb->queue);
+
+       sysfs_remove_group(&card->dev.kobj, &msb->attr_group);
+
+       mutex_lock(&mspro_block_disk_lock);
+       mspro_block_data_clear(msb);
+       mutex_unlock(&mspro_block_disk_lock);
+
+       mspro_block_disk_release(msb->disk);
+       memstick_set_drvdata(card, NULL);
+}
+
+#ifdef CONFIG_PM
+
+static int mspro_block_suspend(struct memstick_dev *card, pm_message_t state)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       struct task_struct *q_thread = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&msb->q_lock, flags);
+       q_thread = msb->q_thread;
+       msb->q_thread = NULL;
+       msb->active = 0;
+       blk_stop_queue(msb->queue);
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+
+       if (q_thread)
+               kthread_stop(q_thread);
+
+       return 0;
+}
+
+static int mspro_block_resume(struct memstick_dev *card)
+{
+       struct mspro_block_data *msb = memstick_get_drvdata(card);
+       unsigned long flags;
+       int rc = 0;
+
+#ifdef CONFIG_MEMSTICK_UNSAFE_RESUME
+
+       struct mspro_block_data *new_msb;
+       struct memstick_host *host = card->host;
+       struct mspro_sys_attr *s_attr, *r_attr;
+       unsigned char cnt;
+
+       mutex_lock(&host->lock);
+       new_msb = kzalloc(sizeof(struct mspro_block_data), GFP_KERNEL);
+       if (!new_msb) {
+               rc = -ENOMEM;
+               goto out_unlock;
+       }
+
+       new_msb->card = card;
+       memstick_set_drvdata(card, new_msb);
+       if (mspro_block_init_card(card))
+               goto out_free;
+
+       for (cnt = 0; new_msb->attr_group.attrs[cnt]
+                     && msb->attr_group.attrs[cnt]; ++cnt) {
+               s_attr = mspro_from_sysfs_attr(new_msb->attr_group.attrs[cnt]);
+               r_attr = mspro_from_sysfs_attr(msb->attr_group.attrs[cnt]);
+
+               if (s_attr->id == MSPRO_BLOCK_ID_SYSINFO
+                   && r_attr->id == s_attr->id) {
+                       if (memcmp(s_attr->data, r_attr->data, s_attr->size))
+                               break;
+
+                       memstick_set_drvdata(card, msb);
+                       msb->q_thread = kthread_run(mspro_block_queue_thread,
+                                                   card, DRIVER_NAME"d");
+                       if (IS_ERR(msb->q_thread))
+                               msb->q_thread = NULL;
+                       else
+                               msb->active = 1;
+
+                       break;
+               }
+       }
+
+out_free:
+       memstick_set_drvdata(card, msb);
+       mspro_block_data_clear(new_msb);
+       kfree(new_msb);
+out_unlock:
+       mutex_unlock(&host->lock);
+
+#endif /* CONFIG_MEMSTICK_UNSAFE_RESUME */
+
+       spin_lock_irqsave(&msb->q_lock, flags);
+       blk_start_queue(msb->queue);
+       spin_unlock_irqrestore(&msb->q_lock, flags);
+       return rc;
+}
+
+#else
+
+#define mspro_block_suspend NULL
+#define mspro_block_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct memstick_device_id mspro_block_id_tbl[] = {
+       {MEMSTICK_MATCH_ALL, MEMSTICK_TYPE_PRO, MEMSTICK_CATEGORY_STORAGE_DUO,
+        MEMSTICK_CLASS_GENERIC_DUO},
+       {}
+};
+
+
+static struct memstick_driver mspro_block_driver = {
+       .driver = {
+               .name  = DRIVER_NAME,
+               .owner = THIS_MODULE
+       },
+       .id_table = mspro_block_id_tbl,
+       .probe    = mspro_block_probe,
+       .remove   = mspro_block_remove,
+       .suspend  = mspro_block_suspend,
+       .resume   = mspro_block_resume
+};
+
+static int __init mspro_block_init(void)
+{
+       int rc = -ENOMEM;
+
+       rc = register_blkdev(major, DRIVER_NAME);
+       if (rc < 0) {
+               printk(KERN_ERR DRIVER_NAME ": failed to register "
+                      "major %d, error %d\n", major, rc);
+               return rc;
+       }
+       if (!major)
+               major = rc;
+
+       rc = memstick_register_driver(&mspro_block_driver);
+       if (rc)
+               unregister_blkdev(major, DRIVER_NAME);
+       return rc;
+}
+
+static void __exit mspro_block_exit(void)
+{
+       memstick_unregister_driver(&mspro_block_driver);
+       unregister_blkdev(major, DRIVER_NAME);
+       idr_destroy(&mspro_block_disk_idr);
+}
+
+module_init(mspro_block_init);
+module_exit(mspro_block_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Alex Dubov");
+MODULE_DESCRIPTION("Sony MemoryStickPro block device driver");
+MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl);
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/memstick/host/Kconfig b/drivers/memstick/host/Kconfig
new file mode 100644 (file)
index 0000000..c002fcc
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# MemoryStick host controller drivers
+#
+
+comment "MemoryStick Host Controller Drivers"
+
+config MEMSTICK_TIFM_MS
+       tristate "TI Flash Media MemoryStick Interface support  (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && PCI
+       select TIFM_CORE
+       help
+         Say Y here if you want to be able to access MemoryStick cards with
+         the Texas Instruments(R) Flash Media card reader, found in many
+         laptops.
+         This option 'selects' (turns on, enables) 'TIFM_CORE', but you
+         probably also need appropriate card reader host adapter, such as
+         'Misc devices: TI Flash Media PCI74xx/PCI76xx host adapter support
+         (TIFM_7XX1)'.
+
+          To compile this driver as a module, choose M here: the
+         module will be called tifm_ms.
+
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
new file mode 100644 (file)
index 0000000..ee66638
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile for MemoryStick host controller drivers
+#
+
+ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
+       EXTRA_CFLAGS            += -DDEBUG
+endif
+
+obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
+
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
new file mode 100644 (file)
index 0000000..f55b71a
--- /dev/null
@@ -0,0 +1,685 @@
+/*
+ *  TI FlashMedia driver
+ *
+ *  Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ * 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.
+ *
+ * Special thanks to Carlos Corbacho for providing various MemoryStick cards
+ * that made this driver possible.
+ *
+ */
+
+#include <linux/tifm.h>
+#include <linux/memstick.h>
+#include <linux/highmem.h>
+#include <linux/scatterlist.h>
+#include <linux/log2.h>
+#include <asm/io.h>
+
+#define DRIVER_NAME "tifm_ms"
+#define DRIVER_VERSION "0.1"
+
+static int no_dma;
+module_param(no_dma, bool, 0644);
+
+#define TIFM_MS_TIMEOUT      0x00100
+#define TIFM_MS_BADCRC       0x00200
+#define TIFM_MS_EOTPC        0x01000
+#define TIFM_MS_INT          0x02000
+
+/* The meaning of the bit majority in this constant is unknown. */
+#define TIFM_MS_SERIAL       0x04010
+
+#define TIFM_MS_SYS_LATCH    0x00100
+#define TIFM_MS_SYS_NOT_RDY  0x00800
+#define TIFM_MS_SYS_DATA     0x10000
+
+/* Hardware flags */
+enum {
+       CMD_READY  = 0x0001,
+       FIFO_READY = 0x0002,
+       CARD_READY = 0x0004,
+       DATA_CARRY = 0x0008
+};
+
+struct tifm_ms {
+       struct tifm_dev         *dev;
+       unsigned short          eject:1,
+                               no_dma:1;
+       unsigned short          cmd_flags;
+       unsigned int            mode_mask;
+       unsigned int            block_pos;
+       unsigned long           timeout_jiffies;
+
+       struct timer_list       timer;
+       struct memstick_request *req;
+       unsigned int            io_word;
+};
+
+static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset,
+                             struct page *pg, unsigned int page_off,
+                             unsigned int length)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned int cnt = 0, off = 0;
+       unsigned char *buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + page_off;
+
+       if (host->cmd_flags & DATA_CARRY) {
+               while ((fifo_offset & 3) && length) {
+                       buf[off++] = host->io_word & 0xff;
+                       host->io_word >>= 8;
+                       length--;
+                       fifo_offset++;
+               }
+               if (!(fifo_offset & 3))
+                       host->cmd_flags &= ~DATA_CARRY;
+               if (!length)
+                       return;
+       }
+
+       do {
+               host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS
+                                     + fifo_offset);
+               cnt = 4;
+               while (length && cnt) {
+                       buf[off++] = (host->io_word >> 8) & 0xff;
+                       cnt--;
+                       length--;
+               }
+               fifo_offset += 4 - cnt;
+       } while (length);
+
+       if (cnt)
+               host->cmd_flags |= DATA_CARRY;
+
+       kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ);
+}
+
+static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset,
+                              struct page *pg, unsigned int page_off,
+                              unsigned int length)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned int cnt = 0, off = 0;
+       unsigned char *buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + page_off;
+
+       if (host->cmd_flags & DATA_CARRY) {
+               while (fifo_offset & 3) {
+                       host->io_word |= buf[off++] << (8 * (fifo_offset & 3));
+                       length--;
+                       fifo_offset++;
+               }
+               if (!(fifo_offset & 3)) {
+                       writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
+                              + fifo_offset - 4);
+
+                       host->cmd_flags &= ~DATA_CARRY;
+               }
+               if (!length)
+                       return;
+       }
+
+       do {
+               cnt = 4;
+               host->io_word = 0;
+               while (length && cnt) {
+                       host->io_word |= buf[off++] << (4 - cnt);
+                       cnt--;
+                       length--;
+               }
+               fifo_offset += 4 - cnt;
+               if (!cnt)
+                       writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
+                                             + fifo_offset - 4);
+
+       } while (length);
+
+       if (cnt)
+               host->cmd_flags |= DATA_CARRY;
+
+       kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ);
+}
+
+static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length)
+{
+       unsigned int t_size;
+       unsigned int off = host->req->sg.offset + host->block_pos;
+       unsigned int p_off, p_cnt;
+       struct page *pg;
+       unsigned long flags;
+
+       dev_dbg(&host->dev->dev, "moving block\n");
+       local_irq_save(flags);
+       t_size = length;
+       while (t_size) {
+               pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT);
+               p_off = offset_in_page(off);
+               p_cnt = PAGE_SIZE - p_off;
+               p_cnt = min(p_cnt, t_size);
+
+               if (host->req->data_dir == WRITE)
+                       tifm_ms_write_fifo(host, length - t_size,
+                                          pg, p_off, p_cnt);
+               else
+                       tifm_ms_read_fifo(host, length - t_size,
+                                         pg, p_off, p_cnt);
+
+               t_size -= p_cnt;
+       }
+       local_irq_restore(flags);
+}
+
+static int tifm_ms_transfer_data(struct tifm_ms *host, int skip)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned int length = host->req->sg.length - host->block_pos;
+
+       if (!length)
+               return 1;
+
+       if (length > TIFM_FIFO_SIZE)
+               length = TIFM_FIFO_SIZE;
+
+       if (!skip) {
+               tifm_ms_move_block(host, length);
+               host->block_pos += length;
+       }
+
+       if ((host->req->data_dir == READ)
+           && (host->block_pos == host->req->sg.length))
+               return 1;
+
+       writel(ilog2(length) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE);
+       if (host->req->data_dir == WRITE)
+               writel((1 << 8) | TIFM_DMA_TX, sock->addr + SOCK_DMA_CONTROL);
+       else
+               writel((1 << 8), sock->addr + SOCK_DMA_CONTROL);
+
+       return 0;
+}
+
+static int tifm_ms_issue_cmd(struct tifm_ms *host)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned char *data;
+       unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0;
+
+       host->cmd_flags = 0;
+
+       if (host->req->io_type == MEMSTICK_IO_SG) {
+               if (!host->no_dma) {
+                       if (1 != tifm_map_sg(sock, &host->req->sg, 1,
+                                            host->req->data_dir == READ
+                                            ? PCI_DMA_FROMDEVICE
+                                            : PCI_DMA_TODEVICE)) {
+                               host->req->error = -ENOMEM;
+                               return host->req->error;
+                       }
+                       data_len = sg_dma_len(&host->req->sg);
+               } else
+                       data_len = host->req->sg.length;
+
+               writel(TIFM_FIFO_INT_SETALL,
+                      sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+               writel(TIFM_FIFO_ENABLE,
+                      sock->addr + SOCK_FIFO_CONTROL);
+               writel(TIFM_FIFO_INTMASK,
+                      sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+
+               if (!host->no_dma) {
+                       writel(ilog2(data_len) - 2,
+                              sock->addr + SOCK_FIFO_PAGE_SIZE);
+                       writel(sg_dma_address(&host->req->sg),
+                              sock->addr + SOCK_DMA_ADDRESS);
+                       if (host->req->data_dir == WRITE)
+                               writel((1 << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
+                                      sock->addr + SOCK_DMA_CONTROL);
+                       else
+                               writel((1 << 8) | TIFM_DMA_EN,
+                                      sock->addr + SOCK_DMA_CONTROL);
+               } else {
+                       tifm_ms_transfer_data(host,
+                                             host->req->data_dir == READ);
+               }
+
+               cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
+               cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY;
+               writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
+       } else if (host->req->io_type == MEMSTICK_IO_VAL) {
+               data = host->req->data;
+               data_len = host->req->data_len;
+
+               cmd_mask = host->mode_mask | 0x2607; /* unknown constant */
+
+               if (host->req->data_dir == WRITE) {
+                       cmd_mask |= TIFM_MS_SYS_LATCH;
+                       writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
+                       for (cnt = 0; (data_len - cnt) >= 4; cnt += 4) {
+                               writel(TIFM_MS_SYS_LATCH
+                                      | readl(sock->addr + SOCK_MS_SYSTEM),
+                                      sock->addr + SOCK_MS_SYSTEM);
+                               __raw_writel(*(unsigned int *)(data + cnt),
+                                            sock->addr + SOCK_MS_DATA);
+                               dev_dbg(&sock->dev, "writing %x\n",
+                                       *(int *)(data + cnt));
+                       }
+                       switch (data_len - cnt) {
+                       case 3:
+                               tval |= data[cnt + 2] << 16;
+                       case 2:
+                               tval |= data[cnt + 1] << 8;
+                       case 1:
+                               tval |= data[cnt];
+                               writel(TIFM_MS_SYS_LATCH
+                                      | readl(sock->addr + SOCK_MS_SYSTEM),
+                                      sock->addr + SOCK_MS_SYSTEM);
+                               writel(tval, sock->addr + SOCK_MS_DATA);
+                               dev_dbg(&sock->dev, "writing %x\n", tval);
+                       }
+
+                       writel(TIFM_MS_SYS_LATCH
+                              | readl(sock->addr + SOCK_MS_SYSTEM),
+                              sock + SOCK_MS_SYSTEM);
+                       writel(0, sock->addr + SOCK_MS_DATA);
+                       dev_dbg(&sock->dev, "writing %x\n", 0);
+
+               } else
+                       writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
+
+               cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
+               cmd_mask &= ~TIFM_MS_SYS_DATA;
+               cmd_mask |= TIFM_MS_SYS_NOT_RDY;
+               dev_dbg(&sock->dev, "mask %x\n", cmd_mask);
+               writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
+       } else
+               BUG();
+
+       mod_timer(&host->timer, jiffies + host->timeout_jiffies);
+       writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
+       host->req->error = 0;
+
+       cmd = (host->req->tpc & 0xf) << 12;
+       cmd |= data_len;
+       writel(cmd, sock->addr + SOCK_MS_COMMAND);
+
+       dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask);
+       return 0;
+}
+
+static void tifm_ms_complete_cmd(struct tifm_ms *host)
+{
+       struct tifm_dev *sock = host->dev;
+       struct memstick_host *msh = tifm_get_drvdata(sock);
+       unsigned int tval = 0, data_len;
+       unsigned char *data;
+       int rc;
+
+       del_timer(&host->timer);
+       if (host->req->io_type == MEMSTICK_IO_SG) {
+               if (!host->no_dma)
+                       tifm_unmap_sg(sock, &host->req->sg, 1,
+                                     host->req->data_dir == READ
+                                     ? PCI_DMA_FROMDEVICE
+                                     : PCI_DMA_TODEVICE);
+       } else if (host->req->io_type == MEMSTICK_IO_VAL) {
+               writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM),
+                      sock->addr + SOCK_MS_SYSTEM);
+
+               data = host->req->data;
+               data_len = host->req->data_len;
+
+               if (host->req->data_dir == READ) {
+                       for (rc = 0; (data_len - rc) >= 4; rc += 4)
+                               *(int *)(data + rc)
+                                       = __raw_readl(sock->addr
+                                                     + SOCK_MS_DATA);
+
+                       if (data_len - rc)
+                               tval = readl(sock->addr + SOCK_MS_DATA);
+                       switch (data_len - rc) {
+                       case 3:
+                               data[rc + 2] = (tval >> 16) & 0xff;
+                       case 2:
+                               data[rc + 1] = (tval >> 8) & 0xff;
+                       case 1:
+                               data[rc] = tval & 0xff;
+                       }
+                       readl(sock->addr + SOCK_MS_DATA);
+               }
+       }
+
+       writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
+
+       do {
+               rc = memstick_next_req(msh, &host->req);
+       } while (!rc && tifm_ms_issue_cmd(host));
+}
+
+static int tifm_ms_check_status(struct tifm_ms *host)
+{
+       if (!host->req->error) {
+               if (!(host->cmd_flags & CMD_READY))
+                       return 1;
+               if ((host->req->io_type == MEMSTICK_IO_SG)
+                   && !(host->cmd_flags & FIFO_READY))
+                       return 1;
+               if (host->req->need_card_int
+                   && !(host->cmd_flags & CARD_READY))
+                       return 1;
+       }
+       return 0;
+}
+
+/* Called from interrupt handler */
+static void tifm_ms_data_event(struct tifm_dev *sock)
+{
+       struct tifm_ms *host;
+       unsigned int fifo_status = 0;
+       int rc = 1;
+
+       spin_lock(&sock->lock);
+       host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
+       fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
+       dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n",
+               fifo_status, host->cmd_flags);
+
+       if (host->req) {
+               if (fifo_status & TIFM_FIFO_READY) {
+                       if (!host->no_dma || tifm_ms_transfer_data(host, 0)) {
+                               host->cmd_flags |= FIFO_READY;
+                               rc = tifm_ms_check_status(host);
+                       }
+               }
+       }
+
+       writel(fifo_status, sock->addr + SOCK_DMA_FIFO_STATUS);
+       if (!rc)
+               tifm_ms_complete_cmd(host);
+
+       spin_unlock(&sock->lock);
+}
+
+
+/* Called from interrupt handler */
+static void tifm_ms_card_event(struct tifm_dev *sock)
+{
+       struct tifm_ms *host;
+       unsigned int host_status = 0;
+       int rc = 1;
+
+       spin_lock(&sock->lock);
+       host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
+       host_status = readl(sock->addr + SOCK_MS_STATUS);
+       dev_dbg(&sock->dev, "host event: host_status %x, flags %x\n",
+               host_status, host->cmd_flags);
+
+       if (host->req) {
+               if (host_status & TIFM_MS_TIMEOUT)
+                       host->req->error = -ETIME;
+               else if (host_status & TIFM_MS_BADCRC)
+                       host->req->error = -EILSEQ;
+
+               if (host->req->error) {
+                       writel(TIFM_FIFO_INT_SETALL,
+                              sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+                       writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
+               }
+
+               if (host_status & TIFM_MS_EOTPC)
+                       host->cmd_flags |= CMD_READY;
+               if (host_status & TIFM_MS_INT)
+                       host->cmd_flags |= CARD_READY;
+
+               rc = tifm_ms_check_status(host);
+
+       }
+
+       writel(TIFM_MS_SYS_NOT_RDY | readl(sock->addr + SOCK_MS_SYSTEM),
+              sock->addr + SOCK_MS_SYSTEM);
+       writel((~TIFM_MS_SYS_DATA) & readl(sock->addr + SOCK_MS_SYSTEM),
+              sock->addr + SOCK_MS_SYSTEM);
+
+       if (!rc)
+               tifm_ms_complete_cmd(host);
+
+       spin_unlock(&sock->lock);
+       return;
+}
+
+static void tifm_ms_request(struct memstick_host *msh)
+{
+       struct tifm_ms *host = memstick_priv(msh);
+       struct tifm_dev *sock = host->dev;
+       unsigned long flags;
+       int rc;
+
+       spin_lock_irqsave(&sock->lock, flags);
+       if (host->req) {
+               printk(KERN_ERR "%s : unfinished request detected\n",
+                      sock->dev.bus_id);
+               spin_unlock_irqrestore(&sock->lock, flags);
+               tifm_eject(host->dev);
+               return;
+       }
+
+       if (host->eject) {
+               do {
+                       rc = memstick_next_req(msh, &host->req);
+                       if (!rc)
+                               host->req->error = -ETIME;
+               } while (!rc);
+               spin_unlock_irqrestore(&sock->lock, flags);
+               return;
+       }
+
+       do {
+               rc = memstick_next_req(msh, &host->req);
+       } while (!rc && tifm_ms_issue_cmd(host));
+
+       spin_unlock_irqrestore(&sock->lock, flags);
+       return;
+}
+
+static void tifm_ms_set_param(struct memstick_host *msh,
+                             enum memstick_param param,
+                             int value)
+{
+       struct tifm_ms *host = memstick_priv(msh);
+       struct tifm_dev *sock = host->dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sock->lock, flags);
+
+       switch (param) {
+       case MEMSTICK_POWER:
+               /* this is set by card detection mechanism */
+               break;
+       case MEMSTICK_INTERFACE:
+               if (value == MEMSTICK_SERIAL) {
+                       host->mode_mask = TIFM_MS_SERIAL;
+                       writel((~TIFM_CTRL_FAST_CLK)
+                              & readl(sock->addr + SOCK_CONTROL),
+                              sock->addr + SOCK_CONTROL);
+               } else if (value == MEMSTICK_PARALLEL) {
+                       host->mode_mask = 0;
+                       writel(TIFM_CTRL_FAST_CLK
+                              | readl(sock->addr + SOCK_CONTROL),
+                              sock->addr + SOCK_CONTROL);
+               }
+               break;
+       };
+
+       spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static void tifm_ms_abort(unsigned long data)
+{
+       struct tifm_ms *host = (struct tifm_ms *)data;
+
+       dev_dbg(&host->dev->dev, "status %x\n",
+               readl(host->dev->addr + SOCK_MS_STATUS));
+       printk(KERN_ERR
+              "%s : card failed to respond for a long period of time "
+              "(%x, %x)\n",
+              host->dev->dev.bus_id, host->req ? host->req->tpc : 0,
+              host->cmd_flags);
+
+       tifm_eject(host->dev);
+}
+
+static int tifm_ms_initialize_host(struct tifm_ms *host)
+{
+       struct tifm_dev *sock = host->dev;
+       struct memstick_host *msh = tifm_get_drvdata(sock);
+
+       host->mode_mask = TIFM_MS_SERIAL;
+       writel(0x8000, sock->addr + SOCK_MS_SYSTEM);
+       writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
+       writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
+       if (tifm_has_ms_pif(sock))
+               msh->caps |= MEMSTICK_CAP_PARALLEL;
+
+       return 0;
+}
+
+static int tifm_ms_probe(struct tifm_dev *sock)
+{
+       struct memstick_host *msh;
+       struct tifm_ms *host;
+       int rc = -EIO;
+
+       if (!(TIFM_SOCK_STATE_OCCUPIED
+             & readl(sock->addr + SOCK_PRESENT_STATE))) {
+               printk(KERN_WARNING "%s : card gone, unexpectedly\n",
+                      sock->dev.bus_id);
+               return rc;
+       }
+
+       msh = memstick_alloc_host(sizeof(struct tifm_ms), &sock->dev);
+       if (!msh)
+               return -ENOMEM;
+
+       host = memstick_priv(msh);
+       tifm_set_drvdata(sock, msh);
+       host->dev = sock;
+       host->timeout_jiffies = msecs_to_jiffies(1000);
+       host->no_dma = no_dma;
+
+       setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
+
+       msh->request = tifm_ms_request;
+       msh->set_param = tifm_ms_set_param;
+       sock->card_event = tifm_ms_card_event;
+       sock->data_event = tifm_ms_data_event;
+       rc = tifm_ms_initialize_host(host);
+
+       if (!rc)
+               rc = memstick_add_host(msh);
+       if (!rc)
+               return 0;
+
+       memstick_free_host(msh);
+       return rc;
+}
+
+static void tifm_ms_remove(struct tifm_dev *sock)
+{
+       struct memstick_host *msh = tifm_get_drvdata(sock);
+       struct tifm_ms *host = memstick_priv(msh);
+       int rc = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sock->lock, flags);
+       host->eject = 1;
+       if (host->req) {
+               del_timer(&host->timer);
+               writel(TIFM_FIFO_INT_SETALL,
+                      sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+               writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
+               if ((host->req->io_type == MEMSTICK_IO_SG) && !host->no_dma)
+                       tifm_unmap_sg(sock, &host->req->sg, 1,
+                                     host->req->data_dir == READ
+                                     ? PCI_DMA_TODEVICE
+                                     : PCI_DMA_FROMDEVICE);
+               host->req->error = -ETIME;
+
+               do {
+                       rc = memstick_next_req(msh, &host->req);
+                       if (!rc)
+                               host->req->error = -ETIME;
+               } while (!rc);
+       }
+       spin_unlock_irqrestore(&sock->lock, flags);
+
+       memstick_remove_host(msh);
+
+       writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
+       writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
+
+       memstick_free_host(msh);
+}
+
+#ifdef CONFIG_PM
+
+static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
+{
+       return 0;
+}
+
+static int tifm_ms_resume(struct tifm_dev *sock)
+{
+       struct memstick_host *msh = tifm_get_drvdata(sock);
+       struct tifm_ms *host = memstick_priv(msh);
+
+       tifm_ms_initialize_host(host);
+       memstick_detect_change(msh);
+
+       return 0;
+}
+
+#else
+
+#define tifm_ms_suspend NULL
+#define tifm_ms_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct tifm_device_id tifm_ms_id_tbl[] = {
+       { TIFM_TYPE_MS }, { 0 }
+};
+
+static struct tifm_driver tifm_ms_driver = {
+       .driver = {
+               .name  = DRIVER_NAME,
+               .owner = THIS_MODULE
+       },
+       .id_table = tifm_ms_id_tbl,
+       .probe    = tifm_ms_probe,
+       .remove   = tifm_ms_remove,
+       .suspend  = tifm_ms_suspend,
+       .resume   = tifm_ms_resume
+};
+
+static int __init tifm_ms_init(void)
+{
+       return tifm_register_driver(&tifm_ms_driver);
+}
+
+static void __exit tifm_ms_exit(void)
+{
+       tifm_unregister_driver(&tifm_ms_driver);
+}
+
+MODULE_AUTHOR("Alex Dubov");
+MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(tifm_ms_init);
+module_exit(tifm_ms_exit);
index c143a86c2ea6f03b6379220a20e04d254ecc54be..1abc95ca9dfa2fe67aaa85405b259d16427c639c 100644 (file)
@@ -114,6 +114,9 @@ config ACER_WMI
          wireless radio and bluetooth control, and on some laptops,
          exposes the mail LED and LCD backlight.
 
+         For more information about this driver see
+         <file:Documentation/laptops/acer-wmi.txt>
+
          If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
          here.
 
@@ -152,8 +155,9 @@ config FUJITSU_LAPTOP
          If you have a Fujitsu laptop, say Y or M here.
 
 config TC1100_WMI
-       tristate "HP Compaq TC1100 Tablet WMI Extras"
+       tristate "HP Compaq TC1100 Tablet WMI Extras (EXPERIMENTAL)"
        depends on X86 && !X86_64
+       depends on EXPERIMENTAL
        depends on ACPI
        select ACPI_WMI
        ---help---
@@ -192,7 +196,7 @@ config SONY_LAPTOP
          screen brightness control, Fn keys and allows powering on/off some
          devices.
 
-         Read <file:Documentation/sony-laptop.txt> for more information.
+         Read <file:Documentation/laptops/sony-laptop.txt> for more information.
 
 config SONYPI_COMPAT
        bool "Sonypi compatibility"
@@ -211,8 +215,9 @@ config THINKPAD_ACPI
          This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
          support for Fn-Fx key combinations, Bluetooth control, video
          output switching, ThinkLight control, UltraBay eject and more.
-         For more information about this driver see 
-         <file:Documentation/thinkpad-acpi.txt> and <http://ibm-acpi.sf.net/> .
+         For more information about this driver see
+         <file:Documentation/laptops/thinkpad-acpi.txt> and
+         <http://ibm-acpi.sf.net/> .
 
          This driver was formerly known as ibm-acpi.
 
index a4d6775042506a66d87bb3dd80dcf20a190b7f43..d7aea93081f26f98310ebbb1db6a4e29e1ed7ffb 100644 (file)
@@ -428,11 +428,9 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface)
                if (value > max_brightness)
                        return AE_BAD_PARAMETER;
                switch (quirks->brightness) {
-               case 1:
-                       return ec_write(0x83, value);
                default:
-                       return AE_BAD_ADDRESS;
-               break;
+                       return ec_write(0x83, value);
+                       break;
                }
        default:
                return AE_BAD_ADDRESS;
index 54380da343a530ab4a4513eef7501d9e52b6d487..63a089b29545a3bd34eb1e64327c6b693ce04e85 100644 (file)
@@ -302,6 +302,21 @@ static int tifm_7xx1_resume(struct pci_dev *dev)
 
 #endif /* CONFIG_PM */
 
+static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm,
+                                     struct tifm_dev *sock)
+{
+       return 0;
+}
+
+static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock)
+{
+       if (((fm->num_sockets == 4) && (sock->socket_id == 2))
+           || ((fm->num_sockets == 2) && (sock->socket_id == 0)))
+               return 1;
+
+       return 0;
+}
+
 static int tifm_7xx1_probe(struct pci_dev *dev,
                           const struct pci_device_id *dev_id)
 {
@@ -336,6 +351,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
 
        INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
        fm->eject = tifm_7xx1_eject;
+       fm->has_ms_pif = tifm_7xx1_has_ms_pif;
        pci_set_drvdata(dev, fm);
 
        fm->addr = ioremap(pci_resource_start(dev, 0),
@@ -377,6 +393,7 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
        int cnt;
 
        fm->eject = tifm_7xx1_dummy_eject;
+       fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif;
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
        mmiowb();
        free_irq(dev->irq, fm);
index 97544052e7684dda18611c356ca65eab5d9da839..82dc72a1484f888b29665151d61fb35e7aa169e3 100644 (file)
@@ -284,6 +284,13 @@ void tifm_eject(struct tifm_dev *sock)
 }
 EXPORT_SYMBOL(tifm_eject);
 
+int tifm_has_ms_pif(struct tifm_dev *sock)
+{
+       struct tifm_adapter *fm = dev_get_drvdata(sock->dev.parent);
+       return fm->has_ms_pif(fm, sock);
+}
+EXPORT_SYMBOL(tifm_has_ms_pif);
+
 int tifm_map_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
                int direction)
 {
index 5fef6783c7161fc8cf95b836e49dcc13259ff655..3b3cd0e74715c63161a5a3746ce0155cec420f6a 100644 (file)
@@ -25,8 +25,8 @@ config MMC_PXA
          If unsure, say N.
 
 config MMC_SDHCI
-       tristate "Secure Digital Host Controller Interface support  (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
+       tristate "Secure Digital Host Controller Interface support"
+       depends on PCI
        help
          This select the generic Secure Digital Host Controller Interface.
          It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@@ -118,8 +118,8 @@ config MMC_TIFM_SD
          module will be called tifm_sd.
 
 config MMC_SPI
-       tristate "MMC/SD over SPI (EXPERIMENTAL)"
-       depends on MMC && SPI_MASTER && !HIGHMEM && EXPERIMENTAL
+       tristate "MMC/SD over SPI"
+       depends on MMC && SPI_MASTER && !HIGHMEM
        select CRC7
        select CRC_ITU_T
        help
index b1edcefdd4f9e7a615e2e38238f4d43e8456a9b4..21acecc9fe3a929063f626a4d06990cf0216dbc6 100644 (file)
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/gpio.h>
+
 #include <asm/mach/mmc.h>
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/at91_mci.h>
 
 #define DRIVER_NAME "at91_mci"
@@ -659,11 +660,11 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        if (host->board->vcc_pin) {
                switch (ios->power_mode) {
                        case MMC_POWER_OFF:
-                               at91_set_gpio_value(host->board->vcc_pin, 0);
+                               gpio_set_value(host->board->vcc_pin, 0);
                                break;
                        case MMC_POWER_UP:
                        case MMC_POWER_ON:
-                               at91_set_gpio_value(host->board->vcc_pin, 1);
+                               gpio_set_value(host->board->vcc_pin, 1);
                                break;
                }
        }
@@ -768,7 +769,7 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
 static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
 {
        struct at91mci_host *host = _host;
-       int present = !at91_get_gpio_value(irq);
+       int present = !gpio_get_value(irq_to_gpio(irq));
 
        /*
         * we expect this irq on both insert and remove,
@@ -793,7 +794,7 @@ static int at91_mci_get_ro(struct mmc_host *mmc)
        struct at91mci_host *host = mmc_priv(mmc);
 
        if (host->board->wp_pin) {
-               read_only = at91_get_gpio_value(host->board->wp_pin);
+               read_only = gpio_get_value(host->board->wp_pin);
                printk(KERN_WARNING "%s: card is %s\n", mmc_hostname(mmc),
                                (read_only ? "read-only" : "read-write") );
        }
@@ -820,8 +821,6 @@ static int __init at91_mci_probe(struct platform_device *pdev)
        struct resource *res;
        int ret;
 
-       pr_debug("Probe MCI devices\n");
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENXIO;
@@ -831,9 +830,9 @@ static int __init at91_mci_probe(struct platform_device *pdev)
 
        mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
        if (!mmc) {
-               pr_debug("Failed to allocate mmc host\n");
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
+               goto fail6;
        }
 
        mmc->ops = &at91_mci_ops;
@@ -853,19 +852,44 @@ static int __init at91_mci_probe(struct platform_device *pdev)
                if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
                        mmc->caps |= MMC_CAP_4_BIT_DATA;
                else
-                       printk("AT91 MMC: 4 wire bus mode not supported"
+                       dev_warn(&pdev->dev, "4 wire bus mode not supported"
                                " - using 1 wire\n");
        }
 
+       /*
+        * Reserve GPIOs ... board init code makes sure these pins are set
+        * up as GPIOs with the right direction (input, except for vcc)
+        */
+       if (host->board->det_pin) {
+               ret = gpio_request(host->board->det_pin, "mmc_detect");
+               if (ret < 0) {
+                       dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
+                       goto fail5;
+               }
+       }
+       if (host->board->wp_pin) {
+               ret = gpio_request(host->board->wp_pin, "mmc_wp");
+               if (ret < 0) {
+                       dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
+                       goto fail4;
+               }
+       }
+       if (host->board->vcc_pin) {
+               ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
+               if (ret < 0) {
+                       dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
+                       goto fail3;
+               }
+       }
+
        /*
         * Get Clock
         */
        host->mci_clk = clk_get(&pdev->dev, "mci_clk");
        if (IS_ERR(host->mci_clk)) {
-               printk(KERN_ERR "AT91 MMC: no clock defined.\n");
-               mmc_free_host(mmc);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENODEV;
+               ret = -ENODEV;
+               dev_dbg(&pdev->dev, "no mci_clk?\n");
+               goto fail2;
        }
 
        /*
@@ -873,10 +897,8 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         */
        host->baseaddr = ioremap(res->start, res->end - res->start + 1);
        if (!host->baseaddr) {
-               clk_put(host->mci_clk);
-               mmc_free_host(mmc);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto fail1;
        }
 
        /*
@@ -890,15 +912,11 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         * Allocate the MCI interrupt
         */
        host->irq = platform_get_irq(pdev, 0);
-       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED, DRIVER_NAME, host);
+       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
+                       mmc_hostname(mmc), host);
        if (ret) {
-               printk(KERN_ERR "AT91 MMC: Failed to request MCI interrupt\n");
-               clk_disable(host->mci_clk);
-               clk_put(host->mci_clk);
-               mmc_free_host(mmc);
-               iounmap(host->baseaddr);
-               release_mem_region(res->start, res->end - res->start + 1);
-               return ret;
+               dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
+               goto fail0;
        }
 
        platform_set_drvdata(pdev, mmc);
@@ -907,8 +925,7 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         * Add host to MMC layer
         */
        if (host->board->det_pin) {
-               host->present = !at91_get_gpio_value(host->board->det_pin);
-               device_init_wakeup(&pdev->dev, 1);
+               host->present = !gpio_get_value(host->board->det_pin);
        }
        else
                host->present = -1;
@@ -919,15 +936,38 @@ static int __init at91_mci_probe(struct platform_device *pdev)
         * monitor card insertion/removal if we can
         */
        if (host->board->det_pin) {
-               ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
-                               0, DRIVER_NAME, host);
+               ret = request_irq(gpio_to_irq(host->board->det_pin),
+                               at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
                if (ret)
-                       printk(KERN_ERR "AT91 MMC: Couldn't allocate MMC detect irq\n");
+                       dev_warn(&pdev->dev, "request MMC detect irq failed\n");
+               else
+                       device_init_wakeup(&pdev->dev, 1);
        }
 
        pr_debug("Added MCI driver\n");
 
        return 0;
+
+fail0:
+       clk_disable(host->mci_clk);
+       iounmap(host->baseaddr);
+fail1:
+       clk_put(host->mci_clk);
+fail2:
+       if (host->board->vcc_pin)
+               gpio_free(host->board->vcc_pin);
+fail3:
+       if (host->board->wp_pin)
+               gpio_free(host->board->wp_pin);
+fail4:
+       if (host->board->det_pin)
+               gpio_free(host->board->det_pin);
+fail5:
+       mmc_free_host(mmc);
+fail6:
+       release_mem_region(res->start, res->end - res->start + 1);
+       dev_err(&pdev->dev, "probe failed, err %d\n", ret);
+       return ret;
 }
 
 /*
@@ -945,9 +985,10 @@ static int __exit at91_mci_remove(struct platform_device *pdev)
        host = mmc_priv(mmc);
 
        if (host->board->det_pin) {
+               if (device_can_wakeup(&pdev->dev))
+                       free_irq(gpio_to_irq(host->board->det_pin), host);
                device_init_wakeup(&pdev->dev, 0);
-               free_irq(host->board->det_pin, host);
-               cancel_delayed_work(&host->mmc->detect);
+               gpio_free(host->board->det_pin);
        }
 
        at91_mci_disable(host);
@@ -957,6 +998,11 @@ static int __exit at91_mci_remove(struct platform_device *pdev)
        clk_disable(host->mci_clk);                     /* Disable the peripheral clock */
        clk_put(host->mci_clk);
 
+       if (host->board->vcc_pin)
+               gpio_free(host->board->vcc_pin);
+       if (host->board->wp_pin)
+               gpio_free(host->board->wp_pin);
+
        iounmap(host->baseaddr);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, res->end - res->start + 1);
index 1e8704533bc5280ecf15ccdae202feb289f2d4fe..a16d7609e4eede4fa88f4ecc6b3ac9dce699038a 100644 (file)
@@ -41,10 +41,91 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, pci_ids);
 
+static int ricoh_mmc_disable(struct pci_dev *fw_dev)
+{
+       u8 write_enable;
+       u8 write_target;
+       u8 disable;
+
+       if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
+               /* via RL5C476 */
+
+               pci_read_config_byte(fw_dev, 0xB7, &disable);
+               if (disable & 0x02) {
+                       printk(KERN_INFO DRIVER_NAME
+                               ": Controller already disabled. " \
+                               "Nothing to do.\n");
+                       return -ENODEV;
+               }
+
+               pci_read_config_byte(fw_dev, 0x8E, &write_enable);
+               pci_write_config_byte(fw_dev, 0x8E, 0xAA);
+               pci_read_config_byte(fw_dev, 0x8D, &write_target);
+               pci_write_config_byte(fw_dev, 0x8D, 0xB7);
+               pci_write_config_byte(fw_dev, 0xB7, disable | 0x02);
+               pci_write_config_byte(fw_dev, 0x8E, write_enable);
+               pci_write_config_byte(fw_dev, 0x8D, write_target);
+       } else {
+               /* via R5C832 */
+
+               pci_read_config_byte(fw_dev, 0xCB, &disable);
+               if (disable & 0x02) {
+                       printk(KERN_INFO DRIVER_NAME
+                              ": Controller already disabled. " \
+                               "Nothing to do.\n");
+                       return -ENODEV;
+               }
+
+               pci_read_config_byte(fw_dev, 0xCA, &write_enable);
+               pci_write_config_byte(fw_dev, 0xCA, 0x57);
+               pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
+               pci_write_config_byte(fw_dev, 0xCA, write_enable);
+       }
+
+       printk(KERN_INFO DRIVER_NAME
+              ": Controller is now disabled.\n");
+
+       return 0;
+}
+
+static int ricoh_mmc_enable(struct pci_dev *fw_dev)
+{
+       u8 write_enable;
+       u8 write_target;
+       u8 disable;
+
+       if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
+               /* via RL5C476 */
+
+               pci_read_config_byte(fw_dev, 0x8E, &write_enable);
+               pci_write_config_byte(fw_dev, 0x8E, 0xAA);
+               pci_read_config_byte(fw_dev, 0x8D, &write_target);
+               pci_write_config_byte(fw_dev, 0x8D, 0xB7);
+               pci_read_config_byte(fw_dev, 0xB7, &disable);
+               pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02);
+               pci_write_config_byte(fw_dev, 0x8E, write_enable);
+               pci_write_config_byte(fw_dev, 0x8D, write_target);
+       } else {
+               /* via R5C832 */
+
+               pci_read_config_byte(fw_dev, 0xCA, &write_enable);
+               pci_read_config_byte(fw_dev, 0xCB, &disable);
+               pci_write_config_byte(fw_dev, 0xCA, 0x57);
+               pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
+               pci_write_config_byte(fw_dev, 0xCA, write_enable);
+       }
+
+       printk(KERN_INFO DRIVER_NAME
+              ": Controller is now re-enabled.\n");
+
+       return 0;
+}
+
 static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
                                     const struct pci_device_id *ent)
 {
        u8 rev;
+       u8 ctrlfound = 0;
 
        struct pci_dev *fw_dev = NULL;
 
@@ -58,34 +139,38 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
                pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
                (int)rev);
 
-       while ((fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
+       while ((fw_dev =
+               pci_get_device(PCI_VENDOR_ID_RICOH,
+                       PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) {
                if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
                    pdev->bus == fw_dev->bus) {
-                       u8 write_enable;
-                       u8 disable;
-
-                       pci_read_config_byte(fw_dev, 0xCB, &disable);
-                       if (disable & 0x02) {
-                               printk(KERN_INFO DRIVER_NAME
-                                      ": Controller already disabled. Nothing to do.\n");
+                       if (ricoh_mmc_disable(fw_dev) != 0)
                                return -ENODEV;
-                       }
-
-                       pci_read_config_byte(fw_dev, 0xCA, &write_enable);
-                       pci_write_config_byte(fw_dev, 0xCA, 0x57);
-                       pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
-                       pci_write_config_byte(fw_dev, 0xCA, write_enable);
 
                        pci_set_drvdata(pdev, fw_dev);
 
-                       printk(KERN_INFO DRIVER_NAME
-                              ": Controller is now disabled.\n");
-
+                       ++ctrlfound;
                        break;
                }
        }
 
-       if (pci_get_drvdata(pdev) == NULL) {
+       fw_dev = NULL;
+
+       while (!ctrlfound &&
+           (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH,
+                                       PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
+               if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
+                   pdev->bus == fw_dev->bus) {
+                       if (ricoh_mmc_disable(fw_dev) != 0)
+                               return -ENODEV;
+
+                       pci_set_drvdata(pdev, fw_dev);
+
+                       ++ctrlfound;
+               }
+       }
+
+       if (!ctrlfound) {
                printk(KERN_WARNING DRIVER_NAME
                       ": Main firewire function not found. Cannot disable controller.\n");
                return -ENODEV;
@@ -96,30 +181,51 @@ static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
 
 static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
 {
-       u8 write_enable;
-       u8 disable;
        struct pci_dev *fw_dev = NULL;
 
        fw_dev = pci_get_drvdata(pdev);
        BUG_ON(fw_dev == NULL);
 
-       pci_read_config_byte(fw_dev, 0xCA, &write_enable);
-       pci_read_config_byte(fw_dev, 0xCB, &disable);
-       pci_write_config_byte(fw_dev, 0xCA, 0x57);
-       pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
-       pci_write_config_byte(fw_dev, 0xCA, write_enable);
-
-       printk(KERN_INFO DRIVER_NAME
-              ": Controller is now re-enabled.\n");
+       ricoh_mmc_enable(fw_dev);
 
        pci_set_drvdata(pdev, NULL);
 }
 
+static int ricoh_mmc_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct pci_dev *fw_dev = NULL;
+
+       fw_dev = pci_get_drvdata(pdev);
+       BUG_ON(fw_dev == NULL);
+
+       printk(KERN_INFO DRIVER_NAME ": Suspending.\n");
+
+       ricoh_mmc_enable(fw_dev);
+
+       return 0;
+}
+
+static int ricoh_mmc_resume(struct pci_dev *pdev)
+{
+       struct pci_dev *fw_dev = NULL;
+
+       fw_dev = pci_get_drvdata(pdev);
+       BUG_ON(fw_dev == NULL);
+
+       printk(KERN_INFO DRIVER_NAME ": Resuming.\n");
+
+       ricoh_mmc_disable(fw_dev);
+
+       return 0;
+}
+
 static struct pci_driver ricoh_mmc_driver = {
        .name =         DRIVER_NAME,
        .id_table =     pci_ids,
        .probe =        ricoh_mmc_probe,
        .remove =       __devexit_p(ricoh_mmc_remove),
+       .suspend =      ricoh_mmc_suspend,
+       .resume =       ricoh_mmc_resume,
 };
 
 /*****************************************************************************\
index 785bbdcf4a58212e4371fbdc024a1ef1919ffc88..4b673aa2dc3cae7a7e588e1d306e59437848f54f 100644 (file)
 
 static unsigned int debug_quirks = 0;
 
+/* For multi controllers in one platform case */
+static u16 chip_index = 0;
+static spinlock_t index_lock;
+
 /*
  * Different quirks to handle when the hardware deviates from a strict
  * interpretation of the SDHCI specification.
@@ -1320,7 +1324,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
 
-       snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
+       snprintf(host->slot_descr, 20, "sdhc%d:slot%d", chip->index, slot);
 
        ret = pci_request_region(pdev, host->bar, host->slot_descr);
        if (ret)
@@ -1585,6 +1589,11 @@ static int __devinit sdhci_probe(struct pci_dev *pdev,
        chip->num_slots = slots;
        pci_set_drvdata(pdev, chip);
 
+       /* Add for multi controller case */
+       spin_lock(&index_lock);
+       chip->index = chip_index++;
+       spin_unlock(&index_lock);
+
        for (i = 0;i < slots;i++) {
                ret = sdhci_probe_slot(pdev, i);
                if (ret) {
@@ -1645,6 +1654,8 @@ static int __init sdhci_drv_init(void)
                ": Secure Digital Host Controller Interface driver\n");
        printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
+       spin_lock_init(&index_lock);
+
        return pci_register_driver(&sdhci_driver);
 }
 
index e4d77b038bfa5e9e12c976294c3dfecb5b86d156..d5a38f1b755ae1855cca9a0d40713fe3a7c77d65 100644 (file)
@@ -208,6 +208,7 @@ struct sdhci_chip {
 
        unsigned long           quirks;
 
+       int                     index;          /* Index for chip0, chip1 ...*/
        int                     num_slots;      /* Slots on controller */
        struct sdhci_host       *hosts[0];      /* Pointers to hosts */
 };
index 19e1594421a476cae392e4b5f2b6b48c6fb18bb3..8dab69657b1914eefb5ebb0eebf1420f2b78edba 100644 (file)
  *  Overview:
  *   This is a device driver for the NAND flash controller found on
  *   the AMD CS5535/CS5536 companion chipsets for the Geode processor.
+ *   mtd-id for command line partitioning is cs553x_nand_cs[0-3]
+ *   where 0-3 reflects the chip select for NAND.
  *
  */
 
+#include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -244,6 +247,8 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
                goto out_ior;
        }
 
+       new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs);
+
        cs553x_mtd[cs] = new_mtd;
        goto out;
 
@@ -272,12 +277,21 @@ static int is_geode(void)
        return 0;
 }
 
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+#endif
+
+
 static int __init cs553x_init(void)
 {
        int err = -ENXIO;
        int i;
        uint64_t val;
 
+       int mtd_parts_nb = 0;
+       struct mtd_partition *mtd_parts = NULL;
+
        /* If the CPU isn't a Geode GX or LX, abort */
        if (!is_geode())
                return -ENXIO;
@@ -290,7 +304,7 @@ static int __init cs553x_init(void)
 
        /* If it doesn't have the NAND controller enabled, abort */
        rdmsrl(MSR_DIVIL_BALL_OPTS, val);
-       if (val & 1) {
+       if (val & PIN_OPT_IDE) {
                printk(KERN_INFO "CS553x NAND controller: Flash I/O not enabled in MSR_DIVIL_BALL_OPTS.\n");
                return -ENXIO;
        }
@@ -306,9 +320,19 @@ static int __init cs553x_init(void)
           do mtdconcat etc. if we want to. */
        for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
                if (cs553x_mtd[i]) {
-                       add_mtd_device(cs553x_mtd[i]);
 
                        /* If any devices registered, return success. Else the last error. */
+#ifdef CONFIG_MTD_PARTITIONS
+                       mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0);
+                       if (mtd_parts_nb > 0) {
+                               printk(KERN_NOTICE "Using command line partition definition\n");
+                               add_mtd_partitions(cs553x_mtd[i], mtd_parts, mtd_parts_nb);
+                       } else {
+                               add_mtd_device(cs553x_mtd[i]);
+                       }
+#else
+                       add_mtd_device(cs553x_mtd[i]);
+#endif
                        err = 0;
                }
        }
@@ -328,13 +352,14 @@ static void __exit cs553x_cleanup(void)
                void __iomem *mmio_base;
 
                if (!mtd)
-                       break;
+                       continue;
 
                this = cs553x_mtd[i]->priv;
                mmio_base = this->IO_ADDR_R;
 
                /* Release resources, unregister device */
                nand_release(cs553x_mtd[i]);
+               kfree(cs553x_mtd[i]->name);
                cs553x_mtd[i] = NULL;
 
                /* unmap physical address */
index 8b552c6dd2e7b053248eff254abc103cbef38e87..471c7f3e8a4a074f40c9a10110acf9adf6dd4db9 100644 (file)
@@ -64,7 +64,7 @@
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5*HZ)
 
-static const char version[] __devinitdata =
+static char version[] __devinitdata =
        "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
@@ -90,7 +90,7 @@ typedef enum {
 } board_t;
 
 /* indexed by board_t, above */
-static const struct {
+static struct {
        char *name;
 } board_info[] __devinitdata = {
        { "Broadcom NetXtreme II BCM5706 1000Base-T" },
index 4a73c884d0c4dab1cdda1bf309a6b516c1bc85bc..afc7f34b1dcf3afbf8dd6eb02b272abe94c8edf5 100644 (file)
@@ -70,7 +70,7 @@
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT             (5*HZ)
 
-static const char version[] __devinitdata =
+static char version[] __devinitdata =
        "Broadcom NetXtreme II 577xx 10Gigabit Ethernet Driver "
        DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
@@ -107,7 +107,7 @@ enum bnx2x_board_type {
 };
 
 /* indexed by board_t, above */
-static const struct {
+static struct {
        char *name;
 } board_info[] __devinitdata = {
        { "Broadcom NetXtreme II BCM57710 XGb" }
index 0a3e60418e53372beec40c8d50a1a78e086c8534..385f69c1438712d60ddc57acc4a01356bed54b81 100644 (file)
@@ -127,7 +127,7 @@ static int full_duplex[MAX_UNITS];
 #define NATSEMI_RX_LIMIT       2046    /* maximum supported by hardware */
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitdata =
+static char version[] __devinitdata =
   KERN_INFO DRV_NAME " dp8381x driver, version "
       DRV_VERSION ", " DRV_RELDATE "\n"
   KERN_INFO "  originally by Donald Becker <becker@scyld.com>\n"
@@ -238,7 +238,7 @@ enum {
 };
 
 /* array of board data directly indexed by pci_tbl[x].driver_data */
-static const struct {
+static struct {
        const char *name;
        unsigned long flags;
        unsigned int eeprom_size;
@@ -247,7 +247,7 @@ static const struct {
        { "NatSemi DP8381[56]", 0, 24 },
 };
 
-static const struct pci_device_id natsemi_pci_tbl[] __devinitdata = {
+static struct pci_device_id natsemi_pci_tbl[] __devinitdata = {
        { PCI_VENDOR_ID_NS, 0x0020, 0x12d9,     0x000c,     0, 0, 0 },
        { PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
        { }     /* terminate list */
index 5aa0a80896945c994ec574e0c5cb8d035eda5466..e0b072d9fdb7caf571e6594af1f732068cba5dab 100644 (file)
@@ -2289,10 +2289,12 @@ static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
                   atomic_read(&tunnel->ref_count) - 1);
        seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n",
                   tunnel->debug,
-                  tunnel->stats.tx_packets, tunnel->stats.tx_bytes,
-                  tunnel->stats.tx_errors,
-                  tunnel->stats.rx_packets, tunnel->stats.rx_bytes,
-                  tunnel->stats.rx_errors);
+                  (unsigned long long)tunnel->stats.tx_packets,
+                  (unsigned long long)tunnel->stats.tx_bytes,
+                  (unsigned long long)tunnel->stats.tx_errors,
+                  (unsigned long long)tunnel->stats.rx_packets,
+                  (unsigned long long)tunnel->stats.rx_bytes,
+                  (unsigned long long)tunnel->stats.rx_errors);
 }
 
 static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
@@ -2320,12 +2322,12 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
                   jiffies_to_msecs(session->reorder_timeout));
        seq_printf(m, "   %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n",
                   session->nr, session->ns,
-                  session->stats.tx_packets,
-                  session->stats.tx_bytes,
-                  session->stats.tx_errors,
-                  session->stats.rx_packets,
-                  session->stats.rx_bytes,
-                  session->stats.rx_errors);
+                  (unsigned long long)session->stats.tx_packets,
+                  (unsigned long long)session->stats.tx_bytes,
+                  (unsigned long long)session->stats.tx_errors,
+                  (unsigned long long)session->stats.rx_packets,
+                  (unsigned long long)session->stats.rx_bytes,
+                  (unsigned long long)session->stats.rx_errors);
 }
 
 static int pppol2tp_seq_show(struct seq_file *m, void *v)
index 6e00dc857afabf6b2d5ef3a20ae900d8083b622b..c49214feae9159c19aeaad05a43686ece54c97ca 100644 (file)
@@ -216,7 +216,7 @@ do { \
 
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitdata =
+static char version[] =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
index f50cb520dffbf6029e2c5dcb728bd6ec49dd1861..333961bb7873973df7c75e5870aaee1f458ec47f 100644 (file)
@@ -134,7 +134,7 @@ static const int multicast_filter_limit = 32;
 #include "typhoon.h"
 #include "typhoon-firmware.h"
 
-static const char version[] __devinitdata =
+static char version[] __devinitdata =
     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
@@ -178,7 +178,7 @@ enum typhoon_cards {
 };
 
 /* directly indexed by enum typhoon_cards, above */
-static const struct typhoon_card_info typhoon_card_info[] __devinitdata = {
+static struct typhoon_card_info typhoon_card_info[] __devinitdata = {
        { "3Com Typhoon (3C990-TX)",
                TYPHOON_CRYPTO_NONE},
        { "3Com Typhoon (3CR990-TX-95)",
index 8c9fb824cbd4015afe9685ba9b8bc20a0c4b13e8..cc0addb5640c0854f2ec88f124eee7497dc149d4 100644 (file)
@@ -440,7 +440,7 @@ static void velocity_unregister_notifier(void)
  *     Internal board variants. At the moment we have only one
  */
 
-static const struct velocity_info_tbl chip_info_table[] __devinitdata = {
+static struct velocity_info_tbl chip_info_table[] = {
        {CHIP_TYPE_VT6110, "VIA Networking Velocity Family Gigabit Ethernet Adapter", 1, 0x00FFFFFFUL},
        { }
 };
index 5e2d763c6b5fb9252c6648da00ce85ba6829d626..0f8aca8a4d4331b484226f749f6f33012c1a9cf3 100644 (file)
@@ -554,7 +554,6 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 static int x25_asy_open_tty(struct tty_struct *tty)
 {
        struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
-       struct tty_ldisc *ld;
        int err;
 
        /* First make sure we're not already connected. */
index 519b4ff79f7f9edd073ef829ed1cb3f17be2aa5c..8b22281b087f6964c9a13a013efa037458a25be8 100644 (file)
@@ -38,6 +38,7 @@ config PCMCIA_DEBUG
 config PCMCIA
        tristate "16-bit PCMCIA support"
        select CRC32
+       select HAVE_IDE
        default y
        ---help---
           This option enables support for 16-bit PCMCIA cards. Most older
index a64626a82d0b34bfc7c7e4ce1f0c7afe3bf14e8a..b35f9bfa2af4db00df60d0ae74cec8bc0251dfd2 100644 (file)
@@ -71,7 +71,6 @@ static int read_regs(struct device *dev, unsigned char *regs, int no_regs)
 
 static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
 {
-       unsigned long time;
        int ret;
        unsigned char buf[] = { RSECCNT, RMINCNT, RHRCNT,
                                RDAYCNT, RMONCNT, RYRCNT };
index 68071622d4bb13bf768ef2494dd040f2972508d7..f47f4a768be5cf53019d259edaf544daa6230a1c 100644 (file)
@@ -3,7 +3,7 @@
  *    SCLP VT220 terminal driver.
  *
  *  S390 version
- *    Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2003,2008
  *    Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>
  */
 
@@ -632,6 +632,9 @@ static void __init __sclp_vt220_cleanup(void)
                else
                        free_bootmem((unsigned long) page, PAGE_SIZE);
        }
+       if (!list_empty(&sclp_vt220_register.list))
+               sclp_unregister(&sclp_vt220_register);
+       sclp_vt220_initialized = 0;
 }
 
 static int __init __sclp_vt220_init(void)
@@ -639,6 +642,7 @@ static int __init __sclp_vt220_init(void)
        void *page;
        int i;
        int num_pages;
+       int rc;
 
        if (sclp_vt220_initialized)
                return 0;
@@ -667,7 +671,14 @@ static int __init __sclp_vt220_init(void)
                }
                list_add_tail((struct list_head *) page, &sclp_vt220_empty);
        }
-       return 0;
+       rc = sclp_register(&sclp_vt220_register);
+       if (rc) {
+               printk(KERN_ERR SCLP_VT220_PRINT_HEADER
+                      "could not register vt220 - "
+                      "sclp_register returned %d\n", rc);
+               __sclp_vt220_cleanup();
+       }
+       return rc;
 }
 
 static const struct tty_operations sclp_vt220_ops = {
@@ -688,22 +699,17 @@ static int __init sclp_vt220_tty_init(void)
 {
        struct tty_driver *driver;
        int rc;
+       int cleanup;
 
        /* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
         * symmetry between VM and LPAR systems regarding ttyS1. */
        driver = alloc_tty_driver(1);
        if (!driver)
                return -ENOMEM;
+       cleanup = !sclp_vt220_initialized;
        rc = __sclp_vt220_init();
        if (rc)
                goto out_driver;
-       rc = sclp_register(&sclp_vt220_register);
-       if (rc) {
-               printk(KERN_ERR SCLP_VT220_PRINT_HEADER
-                      "could not register tty - "
-                      "sclp_register returned %d\n", rc);
-               goto out_init;
-       }
 
        driver->owner = THIS_MODULE;
        driver->driver_name = SCLP_VT220_DRIVER_NAME;
@@ -721,15 +727,14 @@ static int __init sclp_vt220_tty_init(void)
                printk(KERN_ERR SCLP_VT220_PRINT_HEADER
                       "could not register tty - "
                       "tty_register_driver returned %d\n", rc);
-               goto out_sclp;
+               goto out_init;
        }
        sclp_vt220_driver = driver;
        return 0;
 
-out_sclp:
-       sclp_unregister(&sclp_vt220_register);
 out_init:
-       __sclp_vt220_cleanup();
+       if (cleanup)
+               __sclp_vt220_cleanup();
 out_driver:
        put_tty_driver(driver);
        return rc;
index e2a781b6b21db091af54b3ba5b8fd691a33b0740..097fc0967e9d2925594d4062c308dc7274be48b4 100644 (file)
@@ -3189,13 +3189,11 @@ qdio_establish(struct qdio_initialize *init_data)
        spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags);
 
        ccw_device_set_options_mask(cdev, 0);
-       result=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
-                                       QDIO_DOING_ESTABLISH,0, 0,
-                                       QDIO_ESTABLISH_TIMEOUT);
+       result = ccw_device_start(cdev, &irq_ptr->ccw,
+                               QDIO_DOING_ESTABLISH, 0, 0);
        if (result) {
-               result2=ccw_device_start_timeout(cdev,&irq_ptr->ccw,
-                                                QDIO_DOING_ESTABLISH,0,0,
-                                                QDIO_ESTABLISH_TIMEOUT);
+               result2 = ccw_device_start(cdev, &irq_ptr->ccw,
+                                       QDIO_DOING_ESTABLISH, 0, 0);
                sprintf(dbf_text,"eq:io%4x",result);
                QDIO_DBF_TEXT2(1,setup,dbf_text);
                if (result2) {
@@ -3219,10 +3217,10 @@ qdio_establish(struct qdio_initialize *init_data)
                return result;
        }
        
-       /* Timeout is cared for already by using ccw_device_start_timeout(). */
-       wait_event_interruptible(cdev->private->wait_q,
-                irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED ||
-                irq_ptr->state == QDIO_IRQ_STATE_ERR);
+       wait_event_interruptible_timeout(cdev->private->wait_q,
+               irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED ||
+               irq_ptr->state == QDIO_IRQ_STATE_ERR,
+               QDIO_ESTABLISH_TIMEOUT);
 
        if (irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED)
                result = 0;
index 67aaff3e668d8a3354c06ae23099e8611b921065..d0c6fd3b1c19a02af51665e657fc102829d4d488 100644 (file)
@@ -61,9 +61,9 @@ module_param_named(domain, ap_domain_index, int, 0000);
 MODULE_PARM_DESC(domain, "domain index for ap devices");
 EXPORT_SYMBOL(ap_domain_index);
 
-static int ap_thread_flag = 1;
+static int ap_thread_flag = 0;
 module_param_named(poll_thread, ap_thread_flag, int, 0000);
-MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 1 (on).");
+MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
 
 static struct device *ap_root_device = NULL;
 static DEFINE_SPINLOCK(ap_device_lock);
index 4c549540a35dcccfce967d2e53f498a8a987801c..741d81861d17f777e8fd814edd469004e0491040 100644 (file)
@@ -44,8 +44,8 @@ clean-files += aic79xx_seq.h aic79xx_reg.h aic79xx_reg_print.c
 
 # Dependencies for generated files need to be listed explicitly
 
-$(addprefix $(src)/,$(aic7xxx-y:.o=.c)): $(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h
-$(addprefix $(src)/,$(aic79xx-y:.o=.c)): $(obj)/aic79xx_seq.h $(obj)/aic79xx_reg.h
+$(addprefix $(obj)/,$(aic7xxx-y)): $(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h
+$(addprefix $(obj)/,$(aic79xx-y)): $(obj)/aic79xx_seq.h $(obj)/aic79xx_reg.h
 
 aic7xxx-gen-$(CONFIG_AIC7XXX_BUILD_FIRMWARE)   := $(obj)/aic7xxx_reg.h
 aic7xxx-gen-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT) += $(obj)/aic7xxx_reg_print.c
index f4e3874522465cb52324fa7d317dbc2a11e83fb4..7dd9b50d5ebc7d10f2a0dc2f7e09560ee7784db8 100644 (file)
@@ -892,7 +892,16 @@ out:
        return err;
 }
 
-#define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32)
+/* Maximum number of blocks we map for direct IO at once. */
+#define DIO_MAX_BLOCKS 4096
+/*
+ * Number of credits we need for writing DIO_MAX_BLOCKS:
+ * We need sb + group descriptor + bitmap + inode -> 4
+ * For B blocks with A block pointers per block we need:
+ * 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect).
+ * If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25.
+ */
+#define DIO_CREDITS 25
 
 int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block,
                        unsigned long max_blocks, struct buffer_head *bh,
@@ -939,49 +948,31 @@ static int ext4_get_block(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh_result, int create)
 {
        handle_t *handle = ext4_journal_current_handle();
-       int ret = 0;
+       int ret = 0, started = 0;
        unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
 
-       if (!create)
-               goto get_block;         /* A read */
-
-       if (max_blocks == 1)
-               goto get_block;         /* A single block get */
-
-       if (handle->h_transaction->t_state == T_LOCKED) {
-               /*
-                * Huge direct-io writes can hold off commits for long
-                * periods of time.  Let this commit run.
-                */
-               ext4_journal_stop(handle);
-               handle = ext4_journal_start(inode, DIO_CREDITS);
-               if (IS_ERR(handle))
+       if (create && !handle) {
+               /* Direct IO write... */
+               if (max_blocks > DIO_MAX_BLOCKS)
+                       max_blocks = DIO_MAX_BLOCKS;
+               handle = ext4_journal_start(inode, DIO_CREDITS +
+                             2 * EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb));
+               if (IS_ERR(handle)) {
                        ret = PTR_ERR(handle);
-               goto get_block;
-       }
-
-       if (handle->h_buffer_credits <= EXT4_RESERVE_TRANS_BLOCKS) {
-               /*
-                * Getting low on buffer credits...
-                */
-               ret = ext4_journal_extend(handle, DIO_CREDITS);
-               if (ret > 0) {
-                       /*
-                        * Couldn't extend the transaction.  Start a new one.
-                        */
-                       ret = ext4_journal_restart(handle, DIO_CREDITS);
+                       goto out;
                }
+               started = 1;
        }
 
-get_block:
-       if (ret == 0) {
-               ret = ext4_get_blocks_wrap(handle, inode, iblock,
+       ret = ext4_get_blocks_wrap(handle, inode, iblock,
                                        max_blocks, bh_result, create, 0);
-               if (ret > 0) {
-                       bh_result->b_size = (ret << inode->i_blkbits);
-                       ret = 0;
-               }
+       if (ret > 0) {
+               bh_result->b_size = (ret << inode->i_blkbits);
+               ret = 0;
        }
+       if (started)
+               ext4_journal_stop(handle);
+out:
        return ret;
 }
 
@@ -1671,7 +1662,8 @@ static int ext4_releasepage(struct page *page, gfp_t wait)
  * if the machine crashes during the write.
  *
  * If the O_DIRECT write is intantiating holes inside i_size and the machine
- * crashes then stale disk data _may_ be exposed inside the file.
+ * crashes then stale disk data _may_ be exposed inside the file. But current
+ * VFS code falls back into buffered path in that case so we are safe.
  */
 static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
                        const struct iovec *iov, loff_t offset,
@@ -1680,7 +1672,7 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
        struct ext4_inode_info *ei = EXT4_I(inode);
-       handle_t *handle = NULL;
+       handle_t *handle;
        ssize_t ret;
        int orphan = 0;
        size_t count = iov_length(iov, nr_segs);
@@ -1688,17 +1680,21 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
        if (rw == WRITE) {
                loff_t final_size = offset + count;
 
-               handle = ext4_journal_start(inode, DIO_CREDITS);
-               if (IS_ERR(handle)) {
-                       ret = PTR_ERR(handle);
-                       goto out;
-               }
                if (final_size > inode->i_size) {
+                       /* Credits for sb + inode write */
+                       handle = ext4_journal_start(inode, 2);
+                       if (IS_ERR(handle)) {
+                               ret = PTR_ERR(handle);
+                               goto out;
+                       }
                        ret = ext4_orphan_add(handle, inode);
-                       if (ret)
-                               goto out_stop;
+                       if (ret) {
+                               ext4_journal_stop(handle);
+                               goto out;
+                       }
                        orphan = 1;
                        ei->i_disksize = inode->i_size;
+                       ext4_journal_stop(handle);
                }
        }
 
@@ -1706,18 +1702,21 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb,
                                 offset, nr_segs,
                                 ext4_get_block, NULL);
 
-       /*
-        * Reacquire the handle: ext4_get_block() can restart the transaction
-        */
-       handle = ext4_journal_current_handle();
-
-out_stop:
-       if (handle) {
+       if (orphan) {
                int err;
 
-               if (orphan && inode->i_nlink)
+               /* Credits for sb + inode write */
+               handle = ext4_journal_start(inode, 2);
+               if (IS_ERR(handle)) {
+                       /* This is really bad luck. We've written the data
+                        * but cannot extend i_size. Bail out and pretend
+                        * the write failed... */
+                       ret = PTR_ERR(handle);
+                       goto out;
+               }
+               if (inode->i_nlink)
                        ext4_orphan_del(handle, inode);
-               if (orphan && ret > 0) {
+               if (ret > 0) {
                        loff_t end = offset + ret;
                        if (end > inode->i_size) {
                                ei->i_disksize = end;
@@ -2758,13 +2757,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                ei->i_data[block] = raw_inode->i_block[block];
        INIT_LIST_HEAD(&ei->i_orphan);
 
-       if (inode->i_ino >= EXT4_FIRST_INO(inode->i_sb) + 1 &&
-           EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
-               /*
-                * When mke2fs creates big inodes it does not zero out
-                * the unused bytes above EXT4_GOOD_OLD_INODE_SIZE,
-                * so ignore those first few inodes.
-                */
+       if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
                ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
                if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
                    EXT4_INODE_SIZE(inode->i_sb)) {
index 76e5fedc0a0b4c7e581852d9eeab4374ba246a24..dd0fcfcb35ce85f9af3b81331a20b14348b48694 100644 (file)
 #define MB_DEFAULT_GROUP_PREALLOC      512
 
 static struct kmem_cache *ext4_pspace_cachep;
+static struct kmem_cache *ext4_ac_cachep;
 
 #ifdef EXT4_BB_MAX_BLOCKS
 #undef EXT4_BB_MAX_BLOCKS
@@ -680,7 +681,6 @@ static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max)
 {
        char *bb;
 
-       /* FIXME!! is this needed */
        BUG_ON(EXT4_MB_BITMAP(e4b) == EXT4_MB_BUDDY(e4b));
        BUG_ON(max == NULL);
 
@@ -964,7 +964,7 @@ static void ext4_mb_generate_buddy(struct super_block *sb,
        grp->bb_fragments = fragments;
 
        if (free != grp->bb_free) {
-               printk(KERN_DEBUG
+               ext4_error(sb, __FUNCTION__,
                        "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n",
                        group, free, grp->bb_free);
                grp->bb_free = free;
@@ -1821,13 +1821,24 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                i = ext4_find_next_zero_bit(bitmap,
                                                EXT4_BLOCKS_PER_GROUP(sb), i);
                if (i >= EXT4_BLOCKS_PER_GROUP(sb)) {
-                       BUG_ON(free != 0);
+                       /*
+                        * IF we corrupt the bitmap  we won't find any
+                        * free blocks even though group info says we
+                        * we have free blocks
+                        */
+                       ext4_error(sb, __FUNCTION__, "%d free blocks as per "
+                                       "group info. But bitmap says 0\n",
+                                       free);
                        break;
                }
 
                mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex);
                BUG_ON(ex.fe_len <= 0);
-               BUG_ON(free < ex.fe_len);
+               if (free < ex.fe_len) {
+                       ext4_error(sb, __FUNCTION__, "%d free blocks as per "
+                                       "group info. But got %d blocks\n",
+                                       free, ex.fe_len);
+               }
 
                ext4_mb_measure_extent(ac, &ex, e4b);
 
@@ -2959,12 +2970,19 @@ int __init init_ext4_mballoc(void)
        if (ext4_pspace_cachep == NULL)
                return -ENOMEM;
 
+       ext4_ac_cachep =
+               kmem_cache_create("ext4_alloc_context",
+                                    sizeof(struct ext4_allocation_context),
+                                    0, SLAB_RECLAIM_ACCOUNT, NULL);
+       if (ext4_ac_cachep == NULL) {
+               kmem_cache_destroy(ext4_pspace_cachep);
+               return -ENOMEM;
+       }
 #ifdef CONFIG_PROC_FS
        proc_root_ext4 = proc_mkdir(EXT4_ROOT, proc_root_fs);
        if (proc_root_ext4 == NULL)
                printk(KERN_ERR "EXT4-fs: Unable to create %s\n", EXT4_ROOT);
 #endif
-
        return 0;
 }
 
@@ -2972,6 +2990,7 @@ void exit_ext4_mballoc(void)
 {
        /* XXX: synchronize_rcu(); */
        kmem_cache_destroy(ext4_pspace_cachep);
+       kmem_cache_destroy(ext4_ac_cachep);
 #ifdef CONFIG_PROC_FS
        remove_proc_entry(EXT4_ROOT, proc_root_fs);
 #endif
@@ -3069,7 +3088,7 @@ static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
 
 out_err:
        sb->s_dirt = 1;
-       put_bh(bitmap_bh);
+       brelse(bitmap_bh);
        return err;
 }
 
@@ -3354,13 +3373,10 @@ static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac,
        ac->ac_pa = pa;
 
        /* we don't correct pa_pstart or pa_plen here to avoid
-        * possible race when tte group is being loaded concurrently
+        * possible race when the group is being loaded concurrently
         * instead we correct pa later, after blocks are marked
-        * in on-disk bitmap -- see ext4_mb_release_context() */
-       /*
-        * FIXME!! but the other CPUs can look at this particular
-        * pa and think that it have enought free blocks if we
-        * don't update pa_free here right ?
+        * in on-disk bitmap -- see ext4_mb_release_context()
+        * Other CPUs are prevented from allocating from this pa by lg_mutex
         */
        mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa);
 }
@@ -3699,7 +3715,7 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
                                struct buffer_head *bitmap_bh,
                                struct ext4_prealloc_space *pa)
 {
-       struct ext4_allocation_context ac;
+       struct ext4_allocation_context *ac;
        struct super_block *sb = e4b->bd_sb;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        unsigned long end;
@@ -3715,9 +3731,13 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
        BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
        end = bit + pa->pa_len;
 
-       ac.ac_sb = sb;
-       ac.ac_inode = pa->pa_inode;
-       ac.ac_op = EXT4_MB_HISTORY_DISCARD;
+       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+
+       if (ac) {
+               ac->ac_sb = sb;
+               ac->ac_inode = pa->pa_inode;
+               ac->ac_op = EXT4_MB_HISTORY_DISCARD;
+       }
 
        while (bit < end) {
                bit = ext4_find_next_zero_bit(bitmap_bh->b_data, end, bit);
@@ -3733,24 +3753,28 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
                                (unsigned) group);
                free += next - bit;
 
-               ac.ac_b_ex.fe_group = group;
-               ac.ac_b_ex.fe_start = bit;
-               ac.ac_b_ex.fe_len = next - bit;
-               ac.ac_b_ex.fe_logical = 0;
-               ext4_mb_store_history(&ac);
+               if (ac) {
+                       ac->ac_b_ex.fe_group = group;
+                       ac->ac_b_ex.fe_start = bit;
+                       ac->ac_b_ex.fe_len = next - bit;
+                       ac->ac_b_ex.fe_logical = 0;
+                       ext4_mb_store_history(ac);
+               }
 
                mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
                bit = next + 1;
        }
        if (free != pa->pa_free) {
-               printk(KERN_ERR "pa %p: logic %lu, phys. %lu, len %lu\n",
+               printk(KERN_CRIT "pa %p: logic %lu, phys. %lu, len %lu\n",
                        pa, (unsigned long) pa->pa_lstart,
                        (unsigned long) pa->pa_pstart,
                        (unsigned long) pa->pa_len);
-               printk(KERN_ERR "free %u, pa_free %u\n", free, pa->pa_free);
+               ext4_error(sb, __FUNCTION__, "free %u, pa_free %u\n",
+                                               free, pa->pa_free);
        }
-       BUG_ON(free != pa->pa_free);
        atomic_add(free, &sbi->s_mb_discarded);
+       if (ac)
+               kmem_cache_free(ext4_ac_cachep, ac);
 
        return err;
 }
@@ -3758,12 +3782,15 @@ static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b,
 static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
                                struct ext4_prealloc_space *pa)
 {
-       struct ext4_allocation_context ac;
+       struct ext4_allocation_context *ac;
        struct super_block *sb = e4b->bd_sb;
        ext4_group_t group;
        ext4_grpblk_t bit;
 
-       ac.ac_op = EXT4_MB_HISTORY_DISCARD;
+       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+
+       if (ac)
+               ac->ac_op = EXT4_MB_HISTORY_DISCARD;
 
        BUG_ON(pa->pa_deleted == 0);
        ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
@@ -3771,13 +3798,16 @@ static int ext4_mb_release_group_pa(struct ext4_buddy *e4b,
        mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len);
        atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded);
 
-       ac.ac_sb = sb;
-       ac.ac_inode = NULL;
-       ac.ac_b_ex.fe_group = group;
-       ac.ac_b_ex.fe_start = bit;
-       ac.ac_b_ex.fe_len = pa->pa_len;
-       ac.ac_b_ex.fe_logical = 0;
-       ext4_mb_store_history(&ac);
+       if (ac) {
+               ac->ac_sb = sb;
+               ac->ac_inode = NULL;
+               ac->ac_b_ex.fe_group = group;
+               ac->ac_b_ex.fe_start = bit;
+               ac->ac_b_ex.fe_len = pa->pa_len;
+               ac->ac_b_ex.fe_logical = 0;
+               ext4_mb_store_history(ac);
+               kmem_cache_free(ext4_ac_cachep, ac);
+       }
 
        return 0;
 }
@@ -4231,7 +4261,7 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed)
 ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
                                 struct ext4_allocation_request *ar, int *errp)
 {
-       struct ext4_allocation_context ac;
+       struct ext4_allocation_context *ac = NULL;
        struct ext4_sb_info *sbi;
        struct super_block *sb;
        ext4_fsblk_t block = 0;
@@ -4257,53 +4287,60 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
        }
        inquota = ar->len;
 
+       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+       if (!ac) {
+               *errp = -ENOMEM;
+               return 0;
+       }
+
        ext4_mb_poll_new_transaction(sb, handle);
 
-       *errp = ext4_mb_initialize_context(&ac, ar);
+       *errp = ext4_mb_initialize_context(ac, ar);
        if (*errp) {
                ar->len = 0;
                goto out;
        }
 
-       ac.ac_op = EXT4_MB_HISTORY_PREALLOC;
-       if (!ext4_mb_use_preallocated(&ac)) {
+       ac->ac_op = EXT4_MB_HISTORY_PREALLOC;
+       if (!ext4_mb_use_preallocated(ac)) {
 
-               ac.ac_op = EXT4_MB_HISTORY_ALLOC;
-               ext4_mb_normalize_request(&ac, ar);
+               ac->ac_op = EXT4_MB_HISTORY_ALLOC;
+               ext4_mb_normalize_request(ac, ar);
 
 repeat:
                /* allocate space in core */
-               ext4_mb_regular_allocator(&ac);
+               ext4_mb_regular_allocator(ac);
 
                /* as we've just preallocated more space than
                 * user requested orinally, we store allocated
                 * space in a special descriptor */
-               if (ac.ac_status == AC_STATUS_FOUND &&
-                               ac.ac_o_ex.fe_len < ac.ac_b_ex.fe_len)
-                       ext4_mb_new_preallocation(&ac);
+               if (ac->ac_status == AC_STATUS_FOUND &&
+                               ac->ac_o_ex.fe_len < ac->ac_b_ex.fe_len)
+                       ext4_mb_new_preallocation(ac);
        }
 
-       if (likely(ac.ac_status == AC_STATUS_FOUND)) {
-               ext4_mb_mark_diskspace_used(&ac, handle);
+       if (likely(ac->ac_status == AC_STATUS_FOUND)) {
+               ext4_mb_mark_diskspace_used(ac, handle);
                *errp = 0;
-               block = ext4_grp_offs_to_block(sb, &ac.ac_b_ex);
-               ar->len = ac.ac_b_ex.fe_len;
+               block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
+               ar->len = ac->ac_b_ex.fe_len;
        } else {
-               freed  = ext4_mb_discard_preallocations(sb, ac.ac_o_ex.fe_len);
+               freed  = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len);
                if (freed)
                        goto repeat;
                *errp = -ENOSPC;
-               ac.ac_b_ex.fe_len = 0;
+               ac->ac_b_ex.fe_len = 0;
                ar->len = 0;
-               ext4_mb_show_ac(&ac);
+               ext4_mb_show_ac(ac);
        }
 
-       ext4_mb_release_context(&ac);
+       ext4_mb_release_context(ac);
 
 out:
        if (ar->len < inquota)
                DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len);
 
+       kmem_cache_free(ext4_ac_cachep, ac);
        return block;
 }
 static void ext4_mb_poll_new_transaction(struct super_block *sb,
@@ -4405,9 +4442,9 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
                        unsigned long block, unsigned long count,
                        int metadata, unsigned long *freed)
 {
-       struct buffer_head *bitmap_bh = 0;
+       struct buffer_head *bitmap_bh = NULL;
        struct super_block *sb = inode->i_sb;
-       struct ext4_allocation_context ac;
+       struct ext4_allocation_context *ac = NULL;
        struct ext4_group_desc *gdp;
        struct ext4_super_block *es;
        unsigned long overflow;
@@ -4436,9 +4473,12 @@ void ext4_mb_free_blocks(handle_t *handle, struct inode *inode,
 
        ext4_debug("freeing block %lu\n", block);
 
-       ac.ac_op = EXT4_MB_HISTORY_FREE;
-       ac.ac_inode = inode;
-       ac.ac_sb = sb;
+       ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
+       if (ac) {
+               ac->ac_op = EXT4_MB_HISTORY_FREE;
+               ac->ac_inode = inode;
+               ac->ac_sb = sb;
+       }
 
 do_more:
        overflow = 0;
@@ -4504,10 +4544,12 @@ do_more:
        BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
        err = ext4_journal_dirty_metadata(handle, bitmap_bh);
 
-       ac.ac_b_ex.fe_group = block_group;
-       ac.ac_b_ex.fe_start = bit;
-       ac.ac_b_ex.fe_len = count;
-       ext4_mb_store_history(&ac);
+       if (ac) {
+               ac->ac_b_ex.fe_group = block_group;
+               ac->ac_b_ex.fe_start = bit;
+               ac->ac_b_ex.fe_len = count;
+               ext4_mb_store_history(ac);
+       }
 
        if (metadata) {
                /* blocks being freed are metadata. these blocks shouldn't
@@ -4548,5 +4590,7 @@ do_more:
 error_return:
        brelse(bitmap_bh);
        ext4_std_error(sb, err);
+       if (ac)
+               kmem_cache_free(ext4_ac_cachep, ac);
        return;
 }
index 3ebc2332f52ec072da353ef1466dfaaea3cd2baf..8c6c685b9d22e1d399d34066e5e6a497150c81a9 100644 (file)
@@ -61,10 +61,9 @@ static int finish_range(handle_t *handle, struct inode *inode,
                retval = ext4_journal_restart(handle, needed);
                if (retval)
                        goto err_out;
-       }
-       if (needed) {
+       } else if (needed) {
                retval = ext4_journal_extend(handle, needed);
-               if (retval != 0) {
+               if (retval) {
                        /*
                         * IF not able to extend the journal restart the journal
                         */
@@ -220,6 +219,26 @@ static int update_tind_extent_range(handle_t *handle, struct inode *inode,
 
 }
 
+static int extend_credit_for_blkdel(handle_t *handle, struct inode *inode)
+{
+       int retval = 0, needed;
+
+       if (handle->h_buffer_credits > EXT4_RESERVE_TRANS_BLOCKS)
+               return 0;
+       /*
+        * We are freeing a blocks. During this we touch
+        * superblock, group descriptor and block bitmap.
+        * So allocate a credit of 3. We may update
+        * quota (user and group).
+        */
+       needed = 3 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb);
+
+       if (ext4_journal_extend(handle, needed) != 0)
+               retval = ext4_journal_restart(handle, needed);
+
+       return retval;
+}
+
 static int free_dind_blocks(handle_t *handle,
                                struct inode *inode, __le32 i_data)
 {
@@ -234,11 +253,14 @@ static int free_dind_blocks(handle_t *handle,
 
        tmp_idata = (__le32 *)bh->b_data;
        for (i = 0; i < max_entries; i++) {
-               if (tmp_idata[i])
+               if (tmp_idata[i]) {
+                       extend_credit_for_blkdel(handle, inode);
                        ext4_free_blocks(handle, inode,
                                        le32_to_cpu(tmp_idata[i]), 1, 1);
+               }
        }
        put_bh(bh);
+       extend_credit_for_blkdel(handle, inode);
        ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1);
        return 0;
 }
@@ -267,29 +289,32 @@ static int free_tind_blocks(handle_t *handle,
                }
        }
        put_bh(bh);
+       extend_credit_for_blkdel(handle, inode);
        ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1);
        return 0;
 }
 
-static int free_ind_block(handle_t *handle, struct inode *inode)
+static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data)
 {
        int retval;
-       struct ext4_inode_info *ei = EXT4_I(inode);
 
-       if (ei->i_data[EXT4_IND_BLOCK])
+       /* ei->i_data[EXT4_IND_BLOCK] */
+       if (i_data[0]) {
+               extend_credit_for_blkdel(handle, inode);
                ext4_free_blocks(handle, inode,
-                               le32_to_cpu(ei->i_data[EXT4_IND_BLOCK]), 1, 1);
+                               le32_to_cpu(i_data[0]), 1, 1);
+       }
 
-       if (ei->i_data[EXT4_DIND_BLOCK]) {
-               retval = free_dind_blocks(handle, inode,
-                                               ei->i_data[EXT4_DIND_BLOCK]);
+       /* ei->i_data[EXT4_DIND_BLOCK] */
+       if (i_data[1]) {
+               retval = free_dind_blocks(handle, inode, i_data[1]);
                if (retval)
                        return retval;
        }
 
-       if (ei->i_data[EXT4_TIND_BLOCK]) {
-               retval = free_tind_blocks(handle, inode,
-                                               ei->i_data[EXT4_TIND_BLOCK]);
+       /* ei->i_data[EXT4_TIND_BLOCK] */
+       if (i_data[2]) {
+               retval = free_tind_blocks(handle, inode, i_data[2]);
                if (retval)
                        return retval;
        }
@@ -297,15 +322,13 @@ static int free_ind_block(handle_t *handle, struct inode *inode)
 }
 
 static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
-                               struct inode *tmp_inode, int retval)
+                               struct inode *tmp_inode)
 {
+       int retval;
+       __le32  i_data[3];
        struct ext4_inode_info *ei = EXT4_I(inode);
        struct ext4_inode_info *tmp_ei = EXT4_I(tmp_inode);
 
-       retval = free_ind_block(handle, inode);
-       if (retval)
-               goto err_out;
-
        /*
         * One credit accounted for writing the
         * i_data field of the original inode
@@ -317,6 +340,11 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
                        goto err_out;
        }
 
+       i_data[0] = ei->i_data[EXT4_IND_BLOCK];
+       i_data[1] = ei->i_data[EXT4_DIND_BLOCK];
+       i_data[2] = ei->i_data[EXT4_TIND_BLOCK];
+
+       down_write(&EXT4_I(inode)->i_data_sem);
        /*
         * We have the extent map build with the tmp inode.
         * Now copy the i_data across
@@ -336,8 +364,15 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode,
        spin_lock(&inode->i_lock);
        inode->i_blocks += tmp_inode->i_blocks;
        spin_unlock(&inode->i_lock);
+       up_write(&EXT4_I(inode)->i_data_sem);
 
+       /*
+        * We mark the inode dirty after, because we decrement the
+        * i_blocks when freeing the indirect meta-data blocks
+        */
+       retval = free_ind_block(handle, inode, i_data);
        ext4_mark_inode_dirty(handle, inode);
+
 err_out:
        return retval;
 }
@@ -365,6 +400,7 @@ static int free_ext_idx(handle_t *handle, struct inode *inode,
                }
        }
        put_bh(bh);
+       extend_credit_for_blkdel(handle, inode);
        ext4_free_blocks(handle, inode, block, 1, 1);
        return retval;
 }
@@ -414,7 +450,12 @@ int ext4_ext_migrate(struct inode *inode, struct file *filp,
        if ((EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL))
                return -EINVAL;
 
-       down_write(&EXT4_I(inode)->i_data_sem);
+       if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0)
+               /*
+                * don't migrate fast symlink
+                */
+               return retval;
+
        handle = ext4_journal_start(inode,
                                        EXT4_DATA_TRANS_BLOCKS(inode->i_sb) +
                                        EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 +
@@ -448,13 +489,6 @@ int ext4_ext_migrate(struct inode *inode, struct file *filp,
        ext4_orphan_add(handle, tmp_inode);
        ext4_journal_stop(handle);
 
-       ei = EXT4_I(inode);
-       i_data = ei->i_data;
-       memset(&lb, 0, sizeof(lb));
-
-       /* 32 bit block address 4 bytes */
-       max_entries = inode->i_sb->s_blocksize >> 2;
-
        /*
         * start with one credit accounted for
         * superblock modification.
@@ -463,7 +497,20 @@ int ext4_ext_migrate(struct inode *inode, struct file *filp,
         * trascation that created the inode. Later as and
         * when we add extents we extent the journal
         */
+       /*
+        * inode_mutex prevent write and truncate on the file. Read still goes
+        * through. We take i_data_sem in ext4_ext_swap_inode_data before we
+        * switch the inode format to prevent read.
+        */
+       mutex_lock(&(inode->i_mutex));
        handle = ext4_journal_start(inode, 1);
+
+       ei = EXT4_I(inode);
+       i_data = ei->i_data;
+       memset(&lb, 0, sizeof(lb));
+
+       /* 32 bit block address 4 bytes */
+       max_entries = inode->i_sb->s_blocksize >> 2;
        for (i = 0; i < EXT4_NDIR_BLOCKS; i++, blk_count++) {
                if (i_data[i]) {
                        retval = update_extent_range(handle, tmp_inode,
@@ -501,19 +548,6 @@ int ext4_ext_migrate(struct inode *inode, struct file *filp,
         */
        retval = finish_range(handle, tmp_inode, &lb);
 err_out:
-       /*
-        * We are either freeing extent information or indirect
-        * blocks. During this we touch superblock, group descriptor
-        * and block bitmap. Later we mark the tmp_inode dirty
-        * via ext4_ext_tree_init. So allocate a credit of 4
-        * We may update quota (user and group).
-        *
-        * FIXME!! we may be touching bitmaps in different block groups.
-        */
-       if (ext4_journal_extend(handle,
-                       4 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb)) != 0)
-               ext4_journal_restart(handle,
-                               4 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb));
        if (retval)
                /*
                 * Failure case delete the extent information with the
@@ -522,7 +556,11 @@ err_out:
                free_ext_block(handle, tmp_inode);
        else
                retval = ext4_ext_swap_inode_data(handle, inode,
-                                                       tmp_inode, retval);
+                                                       tmp_inode);
+
+       /* We mark the tmp_inode dirty via ext4_ext_tree_init. */
+       if (ext4_journal_extend(handle, 1) != 0)
+               ext4_journal_restart(handle, 1);
 
        /*
         * Mark the tmp_inode as of size zero
@@ -550,8 +588,7 @@ err_out:
        tmp_inode->i_nlink = 0;
 
        ext4_journal_stop(handle);
-
-       up_write(&EXT4_I(inode)->i_data_sem);
+       mutex_unlock(&(inode->i_mutex));
 
        if (tmp_inode)
                iput(tmp_inode);
index d153bb5922fc1dc79021e5ad84d5108d81702e74..a9347fb43bcca34dde35173aa1eb1dcccbc50d27 100644 (file)
@@ -2223,6 +2223,7 @@ retry:
                inode->i_op = &ext4_fast_symlink_inode_operations;
                memcpy((char*)&EXT4_I(inode)->i_data,symname,l);
                inode->i_size = l-1;
+               EXT4_I(inode)->i_flags &= ~EXT4_EXTENTS_FL;
        }
        EXT4_I(inode)->i_disksize = inode->i_size;
        err = ext4_add_nondir(handle, dentry, inode);
index 93beb865c20d30f129bac6fb1ed0d99fb699a485..0072da75221fe0c5ff933943b9ceb5170dcd347f 100644 (file)
@@ -1919,6 +1919,17 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
                printk(KERN_WARNING
                       "EXT4-fs warning: feature flags set on rev 0 fs, "
                       "running e2fsck is recommended\n");
+
+       /*
+        * Since ext4 is still considered development code, we require
+        * that the TEST_FILESYS flag in s->flags be set.
+        */
+       if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) {
+               printk(KERN_WARNING "EXT4-fs: %s: not marked "
+                      "OK to use with test code.\n", sb->s_id);
+               goto failed_mount;
+       }
+
        /*
         * Check feature flags regardless of the revision level, since we
         * previously didn't change the revision level when setting the flags,
index d0549cb4fb23640a79d0221262b14742b5c1a468..5222345ddccf6525a13cd74fe801da1bde50a304 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pagemap.h>
 #include <linux/statfs.h>
 #include <linux/seq_file.h>
+#include <linux/mount.h>
 #include "hostfs.h"
 #include "init.h"
 #include "kern.h"
index 683002fefa556875a84c7a0fd79c5249cba04557..f32fbde2175e84d6bb3bc59fdeacc9860f5837b3 100644 (file)
 
 /**
  * vfs_ioctl - call filesystem specific ioctl methods
- * @filp: [in]     open file to invoke ioctl method on
- * @cmd:  [in]     ioctl command to execute
- * @arg:  [in/out] command-specific argument for ioctl
+ * @filp:      open file to invoke ioctl method on
+ * @cmd:       ioctl command to execute
+ * @arg:       command-specific argument for ioctl
  *
  * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise
- * invokes filesystem specific ->ioctl method.  If neither method exists,
+ * invokes filesystem specific ->ioctl method.  If neither method exists,
  * returns -ENOTTY.
  *
  * Returns 0 on success, -errno on error.
index 8e08efcaede26c06d01271b5dbebeafd55a0183d..a38c7186c5704e438236994baa18014b4bacb801 100644 (file)
@@ -104,7 +104,8 @@ static int journal_write_commit_record(journal_t *journal,
 {
        struct journal_head *descriptor;
        struct buffer_head *bh;
-       int i, ret;
+       journal_header_t *header;
+       int ret;
        int barrier_done = 0;
 
        if (is_journal_aborted(journal))
@@ -116,13 +117,10 @@ static int journal_write_commit_record(journal_t *journal,
 
        bh = jh2bh(descriptor);
 
-       /* AKPM: buglet - add `i' to tmp! */
-       for (i = 0; i < bh->b_size; i += 512) {
-               journal_header_t *tmp = (journal_header_t*)bh->b_data;
-               tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
-               tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
-               tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
-       }
+       header = (journal_header_t *)(bh->b_data);
+       header->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
+       header->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
+       header->h_sequence = cpu_to_be32(commit_transaction->t_tid);
 
        JBUFFER_TRACE(descriptor, "write commit block");
        set_buffer_dirty(bh);
index 4f302d2792794008351326bf9d6e128cf8b18a33..a8173081f83124d316181460f06645514490355a 100644 (file)
@@ -136,18 +136,20 @@ static int journal_submit_commit_record(journal_t *journal,
 
        JBUFFER_TRACE(descriptor, "submit commit block");
        lock_buffer(bh);
-
+       get_bh(bh);
        set_buffer_dirty(bh);
        set_buffer_uptodate(bh);
        bh->b_end_io = journal_end_buffer_io_sync;
 
        if (journal->j_flags & JBD2_BARRIER &&
-               !JBD2_HAS_COMPAT_FEATURE(journal,
+               !JBD2_HAS_INCOMPAT_FEATURE(journal,
                                         JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) {
                set_buffer_ordered(bh);
                barrier_done = 1;
        }
        ret = submit_bh(WRITE, bh);
+       if (barrier_done)
+               clear_buffer_ordered(bh);
 
        /* is it possible for another commit to fail at roughly
         * the same time as this one?  If so, we don't want to
@@ -166,7 +168,6 @@ static int journal_submit_commit_record(journal_t *journal,
                spin_unlock(&journal->j_state_lock);
 
                /* And try again, without the barrier */
-               clear_buffer_ordered(bh);
                set_buffer_uptodate(bh);
                set_buffer_dirty(bh);
                ret = submit_bh(WRITE, bh);
@@ -872,7 +873,8 @@ wait_for_iobuf:
                if (err)
                        __jbd2_journal_abort_hard(journal);
        }
-       err = journal_wait_on_commit_record(cbh);
+       if (!err && !is_journal_aborted(journal))
+               err = journal_wait_on_commit_record(cbh);
 
        if (err)
                jbd2_journal_abort(journal, err);
index d36356f7d222c94f63f5c64d16137a2692c09841..146411387adaf1950511e58eab8f29d15b9afea1 100644 (file)
@@ -641,7 +641,7 @@ static int do_one_pass(journal_t *journal,
                                if (chksum_err) {
                                        info->end_transaction = next_commit_ID;
 
-                                       if (!JBD2_HAS_COMPAT_FEATURE(journal,
+                                       if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
                                           JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)){
                                                printk(KERN_ERR
                                                       "JBD: Transaction %u "
index 14e2262c0a046641ece8086c7f7329a8a114ebda..9b559ee711a8e59f8e12fb0029b4d5a0356b7df4 100644 (file)
@@ -1234,7 +1234,7 @@ static int get_iovec_page_array(const struct iovec __user *iov,
                if (unlikely(!len))
                        break;
                error = -EFAULT;
-               if (unlikely(!base))
+               if (!access_ok(VERIFY_READ, base, len))
                        break;
 
                /*
index d5c9d1433781233e75871debc2bdebdfaf994b17..c7db0220fbd6dd74d7a8b97a4bae4fe801fdfc25 100644 (file)
@@ -39,6 +39,7 @@ typedef struct {
 typedef struct {
        unsigned long pgprot;
 } pgprot_t;
+typedef struct page *pgtable_t;
 
 #define pte_val(x)     ((x).pte)
 #define pmd_val(x)     ((&x)->pmd[0])
index a83492449130eb994a650ddb6b986e180aa298c6..d6a3eaf3b27eebfb53395cbeb9ac50cf492124a1 100644 (file)
@@ -31,6 +31,7 @@ typedef struct { unsigned long pte; } pte_t;
 typedef struct { unsigned long pmd[16]; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
 
 #define pte_val(x)     ((x).pte)
 #define pmd_val(x)     ((&x)->pmd[0])
index 6af480c7f2916b5583ba0feb6a1a25afbfebd4ec..1e82ebb7d6442d755266ac2b452f04964ab52b61 100644 (file)
@@ -31,6 +31,7 @@ typedef struct { unsigned long pte; } pte_t;
 typedef struct { unsigned long pmd[16]; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
 
 #define pte_val(x)     ((x).pte)
 #define pmd_val(x)     ((&x)->pmd[0])
diff --git a/include/asm-s390/a.out.h b/include/asm-s390/a.out.h
deleted file mode 100644 (file)
index 8d6bd9c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  include/asm-s390/a.out.h
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *
- *  Derived from "include/asm-i386/a.out.h"
- *    Copyright (C) 1992, Linus Torvalds
- *
- * I don't think we'll ever need a.out ...
- */
-
-#ifndef __S390_A_OUT_H__
-#define __S390_A_OUT_H__
-
-struct exec
-{
-  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
-  unsigned a_text;             /* length of text, in bytes */
-  unsigned a_data;             /* length of data, in bytes */
-  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
-  unsigned a_syms;             /* length of symbol table data in file, in bytes */
-  unsigned a_entry;            /* start address */
-  unsigned a_trsize;           /* length of relocation info for text, in bytes */
-  unsigned a_drsize;           /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* __A_OUT_GNU_H__ */
index 882db054110cbe9f8c7487e6dfe89cdc0647776e..ab83c844d04c106ad216f2c4c2d78243e470e5cb 100644 (file)
@@ -472,7 +472,7 @@ static inline unsigned long __ffz_word_loop(const unsigned long *addr,
                "       brct    %1,0b\n"
                "1:\n"
 #endif
-               : "+a" (bytes), "+d" (size)
+               : "+&a" (bytes), "+&d" (size)
                : "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr)
                : "cc" );
        return bytes;
@@ -507,7 +507,7 @@ static inline unsigned long __ffs_word_loop(const unsigned long *addr,
                "       brct    %1,0b\n"
                "1:\n"
 #endif
-               : "+a" (bytes), "+a" (size)
+               : "+&a" (bytes), "+&a" (size)
                : "d" (0UL), "a" (addr), "m" (*(addrtype *) addr)
                : "cc" );
        return bytes;
index b73a424d0f97906d9b2fc8e0640f2b7fefe07d40..b3ac262c4582f94738376cfcefff762cd50a26b1 100644 (file)
@@ -115,6 +115,7 @@ typedef s390_regs elf_gregset_t;
 
 #include <linux/sched.h>       /* for task_struct */
 #include <asm/system.h>                /* for save_access_regs */
+#include <asm/mmu_context.h>
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
@@ -137,14 +138,7 @@ typedef s390_regs elf_gregset_t;
    use of this is to invoke "./ld.so someprog" to test out a new version of
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
-
-#ifndef __s390x__
-#define ELF_ET_DYN_BASE         ((TASK_SIZE & 0x80000000) \
-                                ? TASK_SIZE / 3 * 2 \
-                                : 2 * TASK_SIZE / 3)
-#else /* __s390x__ */
-#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
-#endif /* __s390x__ */
+#define ELF_ET_DYN_BASE                (STACK_TOP / 3 * 2)
 
 /* Wow, the "main" arch needs arch dependent functions too.. :) */
 
@@ -214,4 +208,16 @@ do {                                                       \
 } while (0)
 #endif /* __s390x__ */
 
+/*
+ * An executable for which elf_read_implies_exec() returns TRUE will
+ * have the READ_IMPLIES_EXEC personality flag set automatically.
+ */
+#define elf_read_implies_exec(ex, executable_stack)    \
+({                                                     \
+       if (current->mm->context.noexec &&              \
+           executable_stack != EXSTACK_DISABLE_X)      \
+               disable_noexec(current->mm, current);   \
+       current->mm->context.noexec == 0;               \
+})
+
 #endif
index ccd36d26615a7c12abc6ec328e2295152038f833..1698e29c5b20fc5b38831bfe0a4b7de80b1487ba 100644 (file)
@@ -1,7 +1,12 @@
 #ifndef __MMU_H
 #define __MMU_H
 
-/* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
+typedef struct {
+       struct list_head crst_list;
+       struct list_head pgtable_list;
+       unsigned long asce_bits;
+       unsigned long asce_limit;
+       int noexec;
+} mm_context_t;
 
 #endif
index a77d4ba3c8ebc5c63ef4fbaa60104ffa6d296fc3..b5a34c6f91a932c0841933c6db88da84ed5a7318 100644 (file)
 #define __S390_MMU_CONTEXT_H
 
 #include <asm/pgalloc.h>
+#include <asm/uaccess.h>
 #include <asm-generic/mm_hooks.h>
 
 static inline int init_new_context(struct task_struct *tsk,
                                   struct mm_struct *mm)
 {
-       mm->context = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
+       mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
 #ifdef CONFIG_64BIT
-       mm->context |= _ASCE_TYPE_REGION3;
+       mm->context.asce_bits |= _ASCE_TYPE_REGION3;
 #endif
+       mm->context.noexec = s390_noexec;
+       mm->context.asce_limit = STACK_TOP_MAX;
+       crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
        return 0;
 }
 
@@ -32,24 +36,25 @@ static inline int init_new_context(struct task_struct *tsk,
 
 static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
 {
-       S390_lowcore.user_asce = mm->context | __pa(mm->pgd);
+       pgd_t *pgd = mm->pgd;
+
+       S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
        if (switch_amode) {
                /* Load primary space page table origin. */
-               pgd_t *shadow_pgd = get_shadow_table(mm->pgd) ? : mm->pgd;
-               S390_lowcore.user_exec_asce = mm->context | __pa(shadow_pgd);
+               pgd = mm->context.noexec ? get_shadow_table(pgd) : pgd;
+               S390_lowcore.user_exec_asce = mm->context.asce_bits | __pa(pgd);
                asm volatile(LCTL_OPCODE" 1,1,%0\n"
                             : : "m" (S390_lowcore.user_exec_asce) );
        } else
                /* Load home space page table origin. */
                asm volatile(LCTL_OPCODE" 13,13,%0"
                             : : "m" (S390_lowcore.user_asce) );
+       set_fs(current->thread.mm_segment);
 }
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                             struct task_struct *tsk)
 {
-       if (unlikely(prev == next))
-               return;
        cpu_set(smp_processor_id(), next->cpu_vm_mask);
        update_mm(next, tsk);
 }
@@ -61,7 +66,6 @@ static inline void activate_mm(struct mm_struct *prev,
                                struct mm_struct *next)
 {
         switch_mm(prev, next, current);
-       set_fs(current->thread.mm_segment);
 }
 
 #endif /* __S390_MMU_CONTEXT_H */
index 7f29a981f48c78580bc80060bc72c798e7599ce7..fe7f92b6ae6df2c415688fa52a7d4b1157ac2641 100644 (file)
@@ -74,43 +74,17 @@ static inline void copy_page(void *to, void *from)
 
 typedef struct { unsigned long pgprot; } pgprot_t;
 typedef struct { unsigned long pte; } pte_t;
-
-#define pte_val(x)      ((x).pte)
-#define pgprot_val(x)   ((x).pgprot)
-
-#ifndef __s390x__
-
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pud; } pud_t;
-typedef struct {
-        unsigned long pgd0;
-        unsigned long pgd1;
-        unsigned long pgd2;
-        unsigned long pgd3;
-        } pgd_t;
-
-#define pmd_val(x)      ((x).pmd)
-#define pud_val(x)     ((x).pud)
-#define pgd_val(x)      ((x).pgd0)
-
-#else /* __s390x__ */
-
-typedef struct { 
-        unsigned long pmd0;
-        unsigned long pmd1; 
-        } pmd_t;
-typedef struct { unsigned long pud; } pud_t;
 typedef struct { unsigned long pgd; } pgd_t;
+typedef pte_t *pgtable_t;
 
-#define pmd_val(x)      ((x).pmd0)
-#define pmd_val1(x)     ((x).pmd1)
+#define pgprot_val(x)  ((x).pgprot)
+#define pte_val(x)     ((x).pte)
+#define pmd_val(x)     ((x).pmd)
 #define pud_val(x)     ((x).pud)
 #define pgd_val(x)      ((x).pgd)
 
-#endif /* __s390x__ */
-
-typedef struct page *pgtable_t;
-
 #define __pte(x)        ((pte_t) { (x) } )
 #define __pmd(x)        ((pmd_t) { (x) } )
 #define __pgd(x)        ((pgd_t) { (x) } )
@@ -167,7 +141,7 @@ static inline int pfn_valid(unsigned long pfn)
 #define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
 #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
-#define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
+#define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
 #include <asm-generic/memory_model.h>
index 900d44807e107bf2d8ce042b433cad88bf50f7e3..f5b2bf3d7c1d4b7a103e3a1089360be7669cb848 100644 (file)
 #define check_pgt_cache()      do {} while (0)
 
 unsigned long *crst_table_alloc(struct mm_struct *, int);
-void crst_table_free(unsigned long *);
+void crst_table_free(struct mm_struct *, unsigned long *);
 
-unsigned long *page_table_alloc(int);
-void page_table_free(unsigned long *);
+unsigned long *page_table_alloc(struct mm_struct *);
+void page_table_free(struct mm_struct *, unsigned long *);
+void disable_noexec(struct mm_struct *, struct task_struct *);
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
@@ -72,23 +73,49 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm)
 
 static inline unsigned long pgd_entry_type(struct mm_struct *mm)
 {
-       return _REGION3_ENTRY_EMPTY;
+       if (mm->context.asce_limit <= (1UL << 31))
+               return _SEGMENT_ENTRY_EMPTY;
+       if (mm->context.asce_limit <= (1UL << 42))
+               return _REGION3_ENTRY_EMPTY;
+       return _REGION2_ENTRY_EMPTY;
 }
 
-#define pud_alloc_one(mm,address)              ({ BUG(); ((pud_t *)2); })
-#define pud_free(mm, x)                                do { } while (0)
+int crst_table_upgrade(struct mm_struct *, unsigned long limit);
+void crst_table_downgrade(struct mm_struct *, unsigned long limit);
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+       unsigned long *table = crst_table_alloc(mm, mm->context.noexec);
+       if (table)
+               crst_table_init(table, _REGION3_ENTRY_EMPTY);
+       return (pud_t *) table;
+}
+#define pud_free(mm, pud) crst_table_free(mm, (unsigned long *) pud)
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
-       unsigned long *crst = crst_table_alloc(mm, s390_noexec);
-       if (crst)
-               crst_table_init(crst, _SEGMENT_ENTRY_EMPTY);
-       return (pmd_t *) crst;
+       unsigned long *table = crst_table_alloc(mm, mm->context.noexec);
+       if (table)
+               crst_table_init(table, _SEGMENT_ENTRY_EMPTY);
+       return (pmd_t *) table;
 }
-#define pmd_free(mm, pmd) crst_table_free((unsigned long *)pmd)
+#define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd)
 
-#define pgd_populate(mm, pgd, pud)             BUG()
-#define pgd_populate_kernel(mm, pgd, pud)      BUG()
+static inline void pgd_populate_kernel(struct mm_struct *mm,
+                                      pgd_t *pgd, pud_t *pud)
+{
+       pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud);
+}
+
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+       pgd_populate_kernel(mm, pgd, pud);
+       if (mm->context.noexec) {
+               pgd = get_shadow_table(pgd);
+               pud = get_shadow_table(pud);
+               pgd_populate_kernel(mm, pgd, pud);
+       }
+}
 
 static inline void pud_populate_kernel(struct mm_struct *mm,
                                       pud_t *pud, pmd_t *pmd)
@@ -98,63 +125,50 @@ static inline void pud_populate_kernel(struct mm_struct *mm,
 
 static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 {
-       pud_t *shadow_pud = get_shadow_table(pud);
-       pmd_t *shadow_pmd = get_shadow_table(pmd);
-
-       if (shadow_pud && shadow_pmd)
-               pud_populate_kernel(mm, shadow_pud, shadow_pmd);
        pud_populate_kernel(mm, pud, pmd);
+       if (mm->context.noexec) {
+               pud = get_shadow_table(pud);
+               pmd = get_shadow_table(pmd);
+               pud_populate_kernel(mm, pud, pmd);
+       }
 }
 
 #endif /* __s390x__ */
 
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       unsigned long *crst = crst_table_alloc(mm, s390_noexec);
-       if (crst)
-               crst_table_init(crst, pgd_entry_type(mm));
-       return (pgd_t *) crst;
+       INIT_LIST_HEAD(&mm->context.crst_list);
+       INIT_LIST_HEAD(&mm->context.pgtable_list);
+       return (pgd_t *) crst_table_alloc(mm, s390_noexec);
 }
-#define pgd_free(mm, pgd) crst_table_free((unsigned long *) pgd)
+#define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd)
 
-static inline void 
-pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
+static inline void pmd_populate_kernel(struct mm_struct *mm,
+                                      pmd_t *pmd, pte_t *pte)
 {
-#ifndef __s390x__
-       pmd_val(pmd[0]) = _SEGMENT_ENTRY + __pa(pte);
-       pmd_val(pmd[1]) = _SEGMENT_ENTRY + __pa(pte+256);
-       pmd_val(pmd[2]) = _SEGMENT_ENTRY + __pa(pte+512);
-       pmd_val(pmd[3]) = _SEGMENT_ENTRY + __pa(pte+768);
-#else /* __s390x__ */
        pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte);
-       pmd_val1(*pmd) = _SEGMENT_ENTRY + __pa(pte+256);
-#endif /* __s390x__ */
 }
 
-static inline void
-pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page)
+static inline void pmd_populate(struct mm_struct *mm,
+                               pmd_t *pmd, pgtable_t pte)
 {
-       pte_t *pte = (pte_t *)page_to_phys(page);
-       pmd_t *shadow_pmd = get_shadow_table(pmd);
-       pte_t *shadow_pte = get_shadow_pte(pte);
-
        pmd_populate_kernel(mm, pmd, pte);
-       if (shadow_pmd && shadow_pte)
-               pmd_populate_kernel(mm, shadow_pmd, shadow_pte);
+       if (mm->context.noexec) {
+               pmd = get_shadow_table(pmd);
+               pmd_populate_kernel(mm, pmd, pte + PTRS_PER_PTE);
+       }
 }
-#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#define pmd_pgtable(pmd) \
+       (pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)
 
 /*
  * page table entry allocation/free routines.
  */
-#define pte_alloc_one_kernel(mm, vmaddr) \
-       ((pte_t *) page_table_alloc(s390_noexec))
-#define pte_alloc_one(mm, vmaddr) \
-       virt_to_page(page_table_alloc(s390_noexec))
-
-#define pte_free_kernel(mm, pte) \
-       page_table_free((unsigned long *) pte)
-#define pte_free(mm, pte) \
-       page_table_free((unsigned long *) page_to_phys((struct page *) pte))
+#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
+#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm))
+
+#define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)
+#define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte)
 
 #endif /* _S390_PGALLOC_H */
index 3f520754e71c4472db5d2570cb42cd8a795ab7d1..65154dc9a9e538aea84f867c8aab6ac19cdeba3e 100644 (file)
@@ -57,21 +57,21 @@ extern char empty_zero_page[PAGE_SIZE];
  * PGDIR_SHIFT determines what a third-level page table entry can map
  */
 #ifndef __s390x__
-# define PMD_SHIFT     22
-# define PUD_SHIFT     22
-# define PGDIR_SHIFT   22
+# define PMD_SHIFT     20
+# define PUD_SHIFT     20
+# define PGDIR_SHIFT   20
 #else /* __s390x__ */
-# define PMD_SHIFT     21
+# define PMD_SHIFT     20
 # define PUD_SHIFT     31
-# define PGDIR_SHIFT   31
+# define PGDIR_SHIFT   42
 #endif /* __s390x__ */
 
 #define PMD_SIZE        (1UL << PMD_SHIFT)
 #define PMD_MASK        (~(PMD_SIZE-1))
 #define PUD_SIZE       (1UL << PUD_SHIFT)
 #define PUD_MASK       (~(PUD_SIZE-1))
-#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK      (~(PGDIR_SIZE-1))
+#define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
 /*
  * entries per page directory level: the S390 is two-level, so
@@ -79,17 +79,15 @@ extern char empty_zero_page[PAGE_SIZE];
  * for S390 segment-table entries are combined to one PGD
  * that leads to 1024 pte per pgd
  */
+#define PTRS_PER_PTE   256
 #ifndef __s390x__
-# define PTRS_PER_PTE    1024
-# define PTRS_PER_PMD    1
-# define PTRS_PER_PUD  1
-# define PTRS_PER_PGD    512
+#define PTRS_PER_PMD   1
+#define PTRS_PER_PUD   1
 #else /* __s390x__ */
-# define PTRS_PER_PTE    512
-# define PTRS_PER_PMD    1024
-# define PTRS_PER_PUD  1
-# define PTRS_PER_PGD    2048
+#define PTRS_PER_PMD   2048
+#define PTRS_PER_PUD   2048
 #endif /* __s390x__ */
+#define PTRS_PER_PGD   2048
 
 #define FIRST_USER_ADDRESS  0
 
@@ -127,8 +125,9 @@ extern char empty_zero_page[PAGE_SIZE];
  * mapping. This needs to be calculated at compile time since the size of the
  * VMEM_MAP is static but the size of struct page can change.
  */
-#define VMEM_MAX_PHYS  min(VMALLOC_START, ((VMEM_MAP_END - VMALLOC_END) / \
-                         sizeof(struct page) * PAGE_SIZE) & ~((16 << 20) - 1))
+#define VMEM_MAX_PAGES ((VMEM_MAP_END - VMALLOC_END) / sizeof(struct page))
+#define VMEM_MAX_PFN   min(VMALLOC_START >> PAGE_SHIFT, VMEM_MAX_PAGES)
+#define VMEM_MAX_PHYS  ((VMEM_MAX_PFN << PAGE_SHIFT) & ~((16 << 20) - 1))
 #define VMEM_MAP       ((struct page *) VMALLOC_END)
 
 /*
@@ -375,24 +374,6 @@ extern char empty_zero_page[PAGE_SIZE];
 # define PxD_SHADOW_SHIFT      2
 #endif /* __s390x__ */
 
-static inline struct page *get_shadow_page(struct page *page)
-{
-       if (s390_noexec && page->index)
-               return virt_to_page((void *)(addr_t) page->index);
-       return NULL;
-}
-
-static inline void *get_shadow_pte(void *table)
-{
-       unsigned long addr, offset;
-       struct page *page;
-
-       addr = (unsigned long) table;
-       offset = addr & (PAGE_SIZE - 1);
-       page = virt_to_page((void *)(addr ^ offset));
-       return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL);
-}
-
 static inline void *get_shadow_table(void *table)
 {
        unsigned long addr, offset;
@@ -410,17 +391,16 @@ static inline void *get_shadow_table(void *table)
  * hook is made available.
  */
 static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
-                             pte_t *pteptr, pte_t pteval)
+                             pte_t *ptep, pte_t entry)
 {
-       pte_t *shadow_pte = get_shadow_pte(pteptr);
-
-       *pteptr = pteval;
-       if (shadow_pte) {
-               if (!(pte_val(pteval) & _PAGE_INVALID) &&
-                   (pte_val(pteval) & _PAGE_SWX))
-                       pte_val(*shadow_pte) = pte_val(pteval) | _PAGE_RO;
+       *ptep = entry;
+       if (mm->context.noexec) {
+               if (!(pte_val(entry) & _PAGE_INVALID) &&
+                   (pte_val(entry) & _PAGE_SWX))
+                       pte_val(entry) |= _PAGE_RO;
                else
-                       pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
+                       pte_val(entry) = _PAGE_TYPE_EMPTY;
+               ptep[PTRS_PER_PTE] = entry;
        }
 }
 
@@ -439,24 +419,58 @@ static inline int pud_bad(pud_t pud)       { return 0; }
 
 #else /* __s390x__ */
 
-static inline int pgd_present(pgd_t pgd) { return 1; }
-static inline int pgd_none(pgd_t pgd)   { return 0; }
-static inline int pgd_bad(pgd_t pgd)    { return 0; }
+static inline int pgd_present(pgd_t pgd)
+{
+       if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2)
+               return 1;
+       return (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) != 0UL;
+}
+
+static inline int pgd_none(pgd_t pgd)
+{
+       if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2)
+               return 0;
+       return (pgd_val(pgd) & _REGION_ENTRY_INV) != 0UL;
+}
+
+static inline int pgd_bad(pgd_t pgd)
+{
+       /*
+        * With dynamic page table levels the pgd can be a region table
+        * entry or a segment table entry. Check for the bit that are
+        * invalid for either table entry.
+        */
+       unsigned long mask =
+               ~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV &
+               ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH;
+       return (pgd_val(pgd) & mask) != 0;
+}
 
 static inline int pud_present(pud_t pud)
 {
+       if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3)
+               return 1;
        return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL;
 }
 
 static inline int pud_none(pud_t pud)
 {
+       if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3)
+               return 0;
        return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL;
 }
 
 static inline int pud_bad(pud_t pud)
 {
-       unsigned long mask = ~_REGION_ENTRY_ORIGIN & ~_REGION_ENTRY_INV;
-       return (pud_val(pud) & mask) != _REGION3_ENTRY;
+       /*
+        * With dynamic page table levels the pud can be a region table
+        * entry or a segment table entry. Check for the bit that are
+        * invalid for either table entry.
+        */
+       unsigned long mask =
+               ~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV &
+               ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH;
+       return (pud_val(pud) & mask) != 0;
 }
 
 #endif /* __s390x__ */
@@ -535,24 +549,30 @@ static inline int pte_young(pte_t pte)
 #define pgd_clear(pgd)         do { } while (0)
 #define pud_clear(pud)         do { } while (0)
 
-static inline void pmd_clear_kernel(pmd_t * pmdp)
+#else /* __s390x__ */
+
+static inline void pgd_clear_kernel(pgd_t * pgd)
 {
-       pmd_val(pmdp[0]) = _SEGMENT_ENTRY_EMPTY;
-       pmd_val(pmdp[1]) = _SEGMENT_ENTRY_EMPTY;
-       pmd_val(pmdp[2]) = _SEGMENT_ENTRY_EMPTY;
-       pmd_val(pmdp[3]) = _SEGMENT_ENTRY_EMPTY;
+       if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2)
+               pgd_val(*pgd) = _REGION2_ENTRY_EMPTY;
 }
 
-#else /* __s390x__ */
+static inline void pgd_clear(pgd_t * pgd)
+{
+       pgd_t *shadow = get_shadow_table(pgd);
 
-#define pgd_clear(pgd)         do { } while (0)
+       pgd_clear_kernel(pgd);
+       if (shadow)
+               pgd_clear_kernel(shadow);
+}
 
 static inline void pud_clear_kernel(pud_t *pud)
 {
-       pud_val(*pud) = _REGION3_ENTRY_EMPTY;
+       if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
+               pud_val(*pud) = _REGION3_ENTRY_EMPTY;
 }
 
-static inline void pud_clear(pud_t * pud)
+static inline void pud_clear(pud_t *pud)
 {
        pud_t *shadow = get_shadow_table(pud);
 
@@ -561,30 +581,27 @@ static inline void pud_clear(pud_t * pud)
                pud_clear_kernel(shadow);
 }
 
+#endif /* __s390x__ */
+
 static inline void pmd_clear_kernel(pmd_t * pmdp)
 {
        pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY;
-       pmd_val1(*pmdp) = _SEGMENT_ENTRY_EMPTY;
 }
 
-#endif /* __s390x__ */
-
-static inline void pmd_clear(pmd_t * pmdp)
+static inline void pmd_clear(pmd_t *pmd)
 {
-       pmd_t *shadow_pmd = get_shadow_table(pmdp);
+       pmd_t *shadow = get_shadow_table(pmd);
 
-       pmd_clear_kernel(pmdp);
-       if (shadow_pmd)
-               pmd_clear_kernel(shadow_pmd);
+       pmd_clear_kernel(pmd);
+       if (shadow)
+               pmd_clear_kernel(shadow);
 }
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
-       pte_t *shadow_pte = get_shadow_pte(ptep);
-
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
-       if (shadow_pte)
-               pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
+       if (mm->context.noexec)
+               pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY;
 }
 
 /*
@@ -665,7 +682,7 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
 {
        if (!(pte_val(*ptep) & _PAGE_INVALID)) {
 #ifndef __s390x__
-               /* S390 has 1mb segments, we are emulating 4MB segments */
+               /* pto must point to the start of the segment table */
                pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00);
 #else
                /* ipte in zarch mode can do the math */
@@ -679,12 +696,12 @@ static inline void __ptep_ipte(unsigned long address, pte_t *ptep)
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
 }
 
-static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
+static inline void ptep_invalidate(struct mm_struct *mm,
+                                  unsigned long address, pte_t *ptep)
 {
        __ptep_ipte(address, ptep);
-       ptep = get_shadow_pte(ptep);
-       if (ptep)
-               __ptep_ipte(address, ptep);
+       if (mm->context.noexec)
+               __ptep_ipte(address, ptep + PTRS_PER_PTE);
 }
 
 /*
@@ -706,7 +723,7 @@ static inline void ptep_invalidate(unsigned long address, pte_t *ptep)
        pte_t __pte = *(__ptep);                                        \
        if (atomic_read(&(__mm)->mm_users) > 1 ||                       \
            (__mm) != current->active_mm)                               \
-               ptep_invalidate(__address, __ptep);                     \
+               ptep_invalidate(__mm, __address, __ptep);               \
        else                                                            \
                pte_clear((__mm), (__address), (__ptep));               \
        __pte;                                                          \
@@ -717,7 +734,7 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
                                     unsigned long address, pte_t *ptep)
 {
        pte_t pte = *ptep;
-       ptep_invalidate(address, ptep);
+       ptep_invalidate(vma->vm_mm, address, ptep);
        return pte;
 }
 
@@ -738,7 +755,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
        if (full)
                pte_clear(mm, addr, ptep);
        else
-               ptep_invalidate(addr, ptep);
+               ptep_invalidate(mm, addr, ptep);
        return pte;
 }
 
@@ -749,7 +766,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
        if (pte_write(__pte)) {                                         \
                if (atomic_read(&(__mm)->mm_users) > 1 ||               \
                    (__mm) != current->active_mm)                       \
-                       ptep_invalidate(__addr, __ptep);                \
+                       ptep_invalidate(__mm, __addr, __ptep);          \
                set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \
        }                                                               \
 })
@@ -759,7 +776,7 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
 ({                                                                     \
        int __changed = !pte_same(*(__ptep), __entry);                  \
        if (__changed) {                                                \
-               ptep_invalidate(__addr, __ptep);                        \
+               ptep_invalidate((__vma)->vm_mm, __addr, __ptep);        \
                set_pte_at((__vma)->vm_mm, __addr, __ptep, __entry);    \
        }                                                               \
        __changed;                                                      \
@@ -840,13 +857,21 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
 
 #define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)
 #define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN)
-#define pgd_deref(pgd) ({ BUG(); 0UL; })
+#define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN)
 
-#define pud_offset(pgd, address) ((pud_t *) pgd)
+static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
+{
+       pud_t *pud = (pud_t *) pgd;
+       if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2)
+               pud = (pud_t *) pgd_deref(*pgd);
+       return pud  + pud_index(address);
+}
 
 static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
 {
-       pmd_t *pmd = (pmd_t *) pud_deref(*pud);
+       pmd_t *pmd = (pmd_t *) pud;
+       if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
+               pmd = (pmd_t *) pud_deref(*pud);
        return pmd + pmd_index(address);
 }
 
index e8785634cbdbf99540d8fca6a843a016904178e8..51d88912aa200857bd6b57fee339f41a3a8421d2 100644 (file)
@@ -64,24 +64,29 @@ extern int get_cpu_capability(unsigned int *);
  */
 #ifndef __s390x__
 
-# define TASK_SIZE             (0x80000000UL)
-# define TASK_UNMAPPED_BASE    (TASK_SIZE / 2)
-# define DEFAULT_TASK_SIZE     (0x80000000UL)
+#define TASK_SIZE              (1UL << 31)
+#define TASK_UNMAPPED_BASE     (1UL << 30)
 
 #else /* __s390x__ */
 
-# define TASK_SIZE_OF(tsk)     (test_tsk_thread_flag(tsk, TIF_31BIT) ? \
-                                       (0x80000000UL) : (0x40000000000UL))
-# define TASK_SIZE             TASK_SIZE_OF(current)
-# define TASK_UNMAPPED_BASE    (TASK_SIZE / 2)
-# define DEFAULT_TASK_SIZE     (0x40000000000UL)
+#define TASK_SIZE_OF(tsk)      (test_tsk_thread_flag(tsk,TIF_31BIT) ? \
+                                       (1UL << 31) : (1UL << 53))
+#define TASK_UNMAPPED_BASE     (test_thread_flag(TIF_31BIT) ? \
+                                       (1UL << 30) : (1UL << 41))
+#define TASK_SIZE              TASK_SIZE_OF(current)
 
 #endif /* __s390x__ */
 
 #ifdef __KERNEL__
 
-#define STACK_TOP              TASK_SIZE
-#define STACK_TOP_MAX          DEFAULT_TASK_SIZE
+#ifndef __s390x__
+#define STACK_TOP              (1UL << 31)
+#define STACK_TOP_MAX          (1UL << 31)
+#else /* __s390x__ */
+#define STACK_TOP              (1UL << (test_thread_flag(TIF_31BIT) ? 31:42))
+#define STACK_TOP_MAX          (1UL << 42)
+#endif /* __s390x__ */
+
 
 #endif
 
@@ -138,8 +143,6 @@ struct stack_frame {
 /*
  * Do necessary setup to start up a new thread.
  */
-#ifndef __s390x__
-
 #define start_thread(regs, new_psw, new_stackp) do {            \
        set_fs(USER_DS);                                        \
        regs->psw.mask  = psw_user_bits;                        \
@@ -147,24 +150,6 @@ struct stack_frame {
         regs->gprs[15]  = new_stackp ;                          \
 } while (0)
 
-#else /* __s390x__ */
-
-#define start_thread(regs, new_psw, new_stackp) do {            \
-       set_fs(USER_DS);                                        \
-       regs->psw.mask  = psw_user_bits;                        \
-        regs->psw.addr  = new_psw;                              \
-        regs->gprs[15]  = new_stackp;                           \
-} while (0)
-
-#define start_thread31(regs, new_psw, new_stackp) do {          \
-       set_fs(USER_DS);                                        \
-       regs->psw.mask  = psw_user32_bits;                      \
-        regs->psw.addr  = new_psw;                              \
-        regs->gprs[15]  = new_stackp;                           \
-} while (0)
-
-#endif /* __s390x__ */
-
 /* Forward declaration, a strange C thing */
 struct task_struct;
 struct mm_struct;
index 3c8177fa9e06e9b0b7800f14ce112917b9843dcc..3d8a96d39d9d6a9a999c0f493911af00e204b605 100644 (file)
@@ -38,7 +38,7 @@ struct mmu_gather {
        struct mm_struct *mm;
        unsigned int fullmm;
        unsigned int nr_ptes;
-       unsigned int nr_pmds;
+       unsigned int nr_pxds;
        void *array[TLB_NR_PTRS];
 };
 
@@ -53,7 +53,7 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm,
        tlb->fullmm = full_mm_flush || (num_online_cpus() == 1) ||
                (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm);
        tlb->nr_ptes = 0;
-       tlb->nr_pmds = TLB_NR_PTRS;
+       tlb->nr_pxds = TLB_NR_PTRS;
        if (tlb->fullmm)
                __tlb_flush_mm(mm);
        return tlb;
@@ -62,12 +62,13 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm,
 static inline void tlb_flush_mmu(struct mmu_gather *tlb,
                                 unsigned long start, unsigned long end)
 {
-       if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pmds < TLB_NR_PTRS))
+       if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < TLB_NR_PTRS))
                __tlb_flush_mm(tlb->mm);
        while (tlb->nr_ptes > 0)
                pte_free(tlb->mm, tlb->array[--tlb->nr_ptes]);
-       while (tlb->nr_pmds < TLB_NR_PTRS)
-               pmd_free(tlb->mm, (pmd_t *) tlb->array[tlb->nr_pmds++]);
+       while (tlb->nr_pxds < TLB_NR_PTRS)
+               /* pgd_free frees the pointer as region or segment table */
+               pgd_free(tlb->mm, tlb->array[tlb->nr_pxds++]);
 }
 
 static inline void tlb_finish_mmu(struct mmu_gather *tlb,
@@ -95,33 +96,57 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
  * pte_free_tlb frees a pte table and clears the CRSTE for the
  * page table from the tlb.
  */
-static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t page)
+static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte)
 {
        if (!tlb->fullmm) {
-               tlb->array[tlb->nr_ptes++] = page;
-               if (tlb->nr_ptes >= tlb->nr_pmds)
+               tlb->array[tlb->nr_ptes++] = pte;
+               if (tlb->nr_ptes >= tlb->nr_pxds)
                        tlb_flush_mmu(tlb, 0, 0);
        } else
-               pte_free(tlb->mm, page);
+               pte_free(tlb->mm, pte);
 }
 
 /*
  * pmd_free_tlb frees a pmd table and clears the CRSTE for the
  * segment table entry from the tlb.
+ * If the mm uses a two level page table the single pmd is freed
+ * as the pgd. pmd_free_tlb checks the asce_limit against 2GB
+ * to avoid the double free of the pmd in this case.
  */
 static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
 #ifdef __s390x__
+       if (tlb->mm->context.asce_limit <= (1UL << 31))
+               return;
        if (!tlb->fullmm) {
-               tlb->array[--tlb->nr_pmds] = (struct page *) pmd;
-               if (tlb->nr_ptes >= tlb->nr_pmds)
+               tlb->array[--tlb->nr_pxds] = pmd;
+               if (tlb->nr_ptes >= tlb->nr_pxds)
                        tlb_flush_mmu(tlb, 0, 0);
        } else
                pmd_free(tlb->mm, pmd);
 #endif
 }
 
-#define pud_free_tlb(tlb, pud)                 do { } while (0)
+/*
+ * pud_free_tlb frees a pud table and clears the CRSTE for the
+ * region third table entry from the tlb.
+ * If the mm uses a three level page table the single pud is freed
+ * as the pgd. pud_free_tlb checks the asce_limit against 4TB
+ * to avoid the double free of the pud in this case.
+ */
+static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+{
+#ifdef __s390x__
+       if (tlb->mm->context.asce_limit <= (1UL << 42))
+               return;
+       if (!tlb->fullmm) {
+               tlb->array[--tlb->nr_pxds] = pud;
+               if (tlb->nr_ptes >= tlb->nr_pxds)
+                       tlb_flush_mmu(tlb, 0, 0);
+       } else
+               pud_free(tlb->mm, pud);
+#endif
+}
 
 #define tlb_start_vma(tlb, vma)                        do { } while (0)
 #define tlb_end_vma(tlb, vma)                  do { } while (0)
index 70fa5ae581801b8a112edc0f71dfc9c9770ed83b..35fb4f9127b2ae41e35683eb0dccb245413cdcec 100644 (file)
@@ -61,11 +61,12 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
         * only ran on the local cpu.
         */
        if (MACHINE_HAS_IDTE) {
-               pgd_t *shadow = get_shadow_table(mm->pgd);
-
-               if (shadow)
-                       __tlb_flush_idte((unsigned long) shadow | mm->context);
-               __tlb_flush_idte((unsigned long) mm->pgd | mm->context);
+               if (mm->context.noexec)
+                       __tlb_flush_idte((unsigned long)
+                                        get_shadow_table(mm->pgd) |
+                                        mm->context.asce_bits);
+               __tlb_flush_idte((unsigned long) mm->pgd |
+                                mm->context.asce_bits);
                return;
        }
        preempt_disable();
index f04acb2670a8121e3d99121e65d00c285cbf34d1..583da807ea972fea3952571b53084bac82fbe702 100644 (file)
 #define __NR_signalfd          316
 #define __NR_timerfd           317
 #define __NR_eventfd           318
-#define NR_syscalls 319
+#define __NR_timerfd_create    319
+#define __NR_timerfd_settime   320
+#define __NR_timerfd_gettime   321
+#define NR_syscalls 322
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 744cfe6c0de8ffca0c3d61b06d7735df8488c89f..2f1c3748a068919329fd49f33147ce3a98b941d7 100644 (file)
@@ -1,24 +1,27 @@
-/* $Id: a.out.h,v 1.13 2000/01/09 10:46:53 anton Exp $ */
 #ifndef __SPARC_A_OUT_H__
 #define __SPARC_A_OUT_H__
 
 #define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
 #define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
 
+#ifndef __ASSEMBLY__
+
 struct exec {
        unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
        unsigned char a_toolversion:7;
        unsigned char a_machtype;
        unsigned short a_info;
-       unsigned long a_text;           /* length of text, in bytes */
-       unsigned long a_data;           /* length of data, in bytes */
-       unsigned long a_bss;            /* length of bss, in bytes */
-       unsigned long a_syms;           /* length of symbol table, in bytes */
-       unsigned long a_entry;          /* where program begins */
-       unsigned long a_trsize;
-       unsigned long a_drsize;
+       unsigned int a_text;            /* length of text, in bytes */
+       unsigned int a_data;            /* length of data, in bytes */
+       unsigned int a_bss;             /* length of bss, in bytes */
+       unsigned int a_syms;            /* length of symbol table, in bytes */
+       unsigned int a_entry;           /* where program begins */
+       unsigned int a_trsize;
+       unsigned int a_drsize;
 };
 
+#endif /* !__ASSEMBLY__ */
+
 /* Where in the file does the text information begin? */
 #define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
 
@@ -28,19 +31,21 @@ struct exec {
                          (x).a_drsize)
 
 /* Where does text segment go in memory after being loaded? */
-#define N_TXTADDR(x)    (((N_MAGIC(x) == ZMAGIC) &&        \
+#define N_TXTADDR(x)    (unsigned long)(((N_MAGIC(x) == ZMAGIC) && \
                         ((x).a_entry < SPARC_PGSIZE)) ?   \
                           0 : SPARC_PGSIZE)
 
 /* And same for the data segment.. */
 #define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
                       (N_TXTADDR(x) + (x).a_text)  \
-                       : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+                      : (unsigned long) (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
 
 #define N_TRSIZE(a)    ((a).a_trsize)
 #define N_DRSIZE(a)    ((a).a_drsize)
 #define N_SYMSIZE(a)   ((a).a_syms)
 
+#ifndef __ASSEMBLY__
+
 /*
  * Sparc relocation types
  */
@@ -77,14 +82,16 @@ enum reloc_type
  */
 struct relocation_info /* used when header.a_machtype == M_SPARC */
 {
-        unsigned long   r_address;  /* relocation addr */
+        unsigned int    r_address;  /* relocation addr */
         unsigned int    r_index:24; /* segment index or symbol index */
         unsigned int    r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
         unsigned int    r_pad:2;    /* <unused> */
         enum reloc_type r_type:5;   /* type of relocation to perform */
-        long            r_addend;   /* addend for relocation value */
+        int             r_addend;   /* addend for relocation value */
 };
 
 #define N_RELOCATION_INFO_DECLARED 1
 
+#endif /* !(__ASSEMBLY__) */
+
 #endif /* __SPARC_A_OUT_H__ */
index 3578ac113cf0ae74ce559f3901a62b2980ee3dde..31f515e499a753f31a224005f46253eb62537f97 100644 (file)
@@ -17,7 +17,7 @@
  * with compliant or compatible devices. It will use whatever features
  * the device supports, prefering those that are typically faster.
  *
- * When the device is opened, it is left in COMPATABILITY mode, and
+ * When the device is opened, it is left in COMPATIBILITY mode, and
  * writes work like any printer device. The driver only attempt to
  * negotiate 1284 modes when needed so that plugs can be pulled,
  * switch boxes switched, etc., without disrupting things. It will
diff --git a/include/asm-sparc/bsderrno.h b/include/asm-sparc/bsderrno.h
deleted file mode 100644 (file)
index 54a75be..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $Id: bsderrno.h,v 1.3 1996/04/25 06:12:47 davem Exp $
- * bsderrno.h: Error numbers for NetBSD binary compatibility
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_BSDERRNO_H
-#define _SPARC_BSDERRNO_H
-
-#define BSD_EPERM         1      /* Operation not permitted */
-#define BSD_ENOENT        2      /* No such file or directory */
-#define BSD_ESRCH         3      /* No such process */
-#define BSD_EINTR         4      /* Interrupted system call */
-#define BSD_EIO           5      /* Input/output error */
-#define BSD_ENXIO         6      /* Device not configured */
-#define BSD_E2BIG         7      /* Argument list too long */
-#define BSD_ENOEXEC       8      /* Exec format error */
-#define BSD_EBADF         9      /* Bad file descriptor */
-#define BSD_ECHILD        10     /* No child processes */
-#define BSD_EDEADLK       11     /* Resource deadlock avoided */
-#define BSD_ENOMEM        12     /* Cannot allocate memory */
-#define BSD_EACCES        13     /* Permission denied */
-#define BSD_EFAULT        14     /* Bad address */
-#define BSD_ENOTBLK       15     /* Block device required */
-#define BSD_EBUSY         16     /* Device busy */
-#define BSD_EEXIST        17     /* File exists */
-#define BSD_EXDEV         18     /* Cross-device link */
-#define BSD_ENODEV        19     /* Operation not supported by device */
-#define BSD_ENOTDIR       20     /* Not a directory */
-#define BSD_EISDIR        21     /* Is a directory */
-#define BSD_EINVAL        22     /* Invalid argument */
-#define BSD_ENFILE        23     /* Too many open files in system */
-#define BSD_EMFILE        24     /* Too many open files */
-#define BSD_ENOTTY        25     /* Inappropriate ioctl for device */
-#define BSD_ETXTBSY       26     /* Text file busy */
-#define BSD_EFBIG         27     /* File too large */
-#define BSD_ENOSPC        28     /* No space left on device */
-#define BSD_ESPIPE        29     /* Illegal seek */
-#define BSD_EROFS         30     /* Read-only file system */
-#define BSD_EMLINK        31     /* Too many links */
-#define BSD_EPIPE         32     /* Broken pipe */
-#define BSD_EDOM          33     /* Numerical argument out of domain */
-#define BSD_ERANGE        34     /* Result too large */
-#define BSD_EAGAIN        35     /* Resource temporarily unavailable */
-#define BSD_EWOULDBLOCK   EAGAIN /* Operation would block */
-#define BSD_EINPROGRESS   36     /* Operation now in progress */
-#define BSD_EALREADY      37     /* Operation already in progress */
-#define BSD_ENOTSOCK      38     /* Socket operation on non-socket */
-#define BSD_EDESTADDRREQ  39     /* Destination address required */
-#define BSD_EMSGSIZE      40     /* Message too long */
-#define BSD_EPROTOTYPE    41     /* Protocol wrong type for socket */
-#define BSD_ENOPROTOOPT   42     /* Protocol not available */
-#define BSD_EPROTONOSUPPORT  43  /* Protocol not supported */
-#define BSD_ESOCKTNOSUPPORT  44  /* Socket type not supported */
-#define BSD_EOPNOTSUPP    45     /* Operation not supported */
-#define BSD_EPFNOSUPPORT  46     /* Protocol family not supported */
-#define BSD_EAFNOSUPPORT  47     /* Address family not supported by protocol family */
-#define BSD_EADDRINUSE    48     /* Address already in use */
-#define BSD_EADDRNOTAVAIL 49     /* Can't assign requested address */
-#define BSD_ENETDOWN      50     /* Network is down */
-#define BSD_ENETUNREACH   51     /* Network is unreachable */
-#define BSD_ENETRESET     52     /* Network dropped connection on reset */
-#define BSD_ECONNABORTED  53     /* Software caused connection abort */
-#define BSD_ECONNRESET    54     /* Connection reset by peer */
-#define BSD_ENOBUFS       55     /* No buffer space available */
-#define BSD_EISCONN       56     /* Socket is already connected */
-#define BSD_ENOTCONN      57     /* Socket is not connected */
-#define BSD_ESHUTDOWN     58     /* Can't send after socket shutdown */
-#define BSD_ETOOMANYREFS  59     /* Too many references: can't splice */
-#define BSD_ETIMEDOUT     60     /* Operation timed out */
-#define BSD_ECONNREFUSED  61     /* Connection refused */
-#define BSD_ELOOP         62     /* Too many levels of symbolic links */
-#define BSD_ENAMETOOLONG  63     /* File name too long */
-#define BSD_EHOSTDOWN     64     /* Host is down */
-#define BSD_EHOSTUNREACH  65     /* No route to host */
-#define BSD_ENOTEMPTY     66     /* Directory not empty */
-#define BSD_EPROCLIM      67     /* Too many processes */
-#define BSD_EUSERS        68     /* Too many users */
-#define BSD_EDQUOT        69     /* Disc quota exceeded */
-#define BSD_ESTALE        70     /* Stale NFS file handle */
-#define BSD_EREMOTE       71     /* Too many levels of remote in path */
-#define BSD_EBADRPC       72     /* RPC struct is bad */
-#define BSD_ERPCMISMATCH  73     /* RPC version wrong */
-#define BSD_EPROGUNAVAIL  74     /* RPC prog. not avail */
-#define BSD_EPROGMISMATCH 75     /* Program version wrong */
-#define BSD_EPROCUNAVAIL  76     /* Bad procedure for program */
-#define BSD_ENOLCK        77     /* No locks available */
-#define BSD_ENOSYS        78     /* Function not implemented */
-#define BSD_EFTYPE        79     /* Inappropriate file type or format */
-#define BSD_EAUTH         80     /* Authentication error */
-#define BSD_ENEEDAUTH     81     /* Need authenticator */
-#define BSD_ELAST         81     /* Must be equal largest errno */
-
-#endif /* !(_SPARC_BSDERRNO_H) */
index 04151208189f6b3b00e29a9ad5071537170810f4..8a59e5a8c21727923f83e8090210a48c8e7d6ded 100644 (file)
@@ -2,28 +2,16 @@
 #define _SPARC_BUG_H
 
 #ifdef CONFIG_BUG
-/* Only use the inline asm until a gcc release that can handle __builtin_trap
- * -rob 2003-06-25
- *
- * gcc-3.3.1 and later will be OK -DaveM
- */
-#if (__GNUC__ > 3) || \
-    (__GNUC__ == 3 && __GNUC_MINOR__ > 3) || \
-    (__GNUC__ == 3 && __GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ >= 4)
-#define __bug_trap()           __builtin_trap()
-#else
-#define __bug_trap()                                   \
-       __asm__ __volatile__ ("t 0x5\n\t" : : )
-#endif
+#include <linux/compiler.h>
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern void do_BUG(const char *file, int line);
 #define BUG() do {                                     \
        do_BUG(__FILE__, __LINE__);                     \
-       __bug_trap();                           \
+       __builtin_trap();                               \
 } while (0)
 #else
-#define BUG()          __bug_trap()
+#define BUG()          __builtin_trap()
 #endif
 
 #define HAVE_ARCH_BUG
index a0f939beeea12de43ecafca6c626bc15a89f63d5..2dfc07bc8e5472ec9b319dd137a8c7a69535338e 100644 (file)
@@ -1,16 +1,24 @@
-/*  $Id: bugs.h,v 1.1 1996/12/26 13:25:20 davem Exp $
- *  include/asm-sparc/bugs.h:  Sparc probes for various bugs.
+/* include/asm-sparc/bugs.h:  Sparc probes for various bugs.
  *
- *  Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
  */
 
+#ifdef CONFIG_SPARC32
 #include <asm/cpudata.h>
+#endif
+
+#ifdef CONFIG_SPARC64
+#include <asm/sstate.h>
+#endif
 
 extern unsigned long loops_per_jiffy;
 
-static void check_bugs(void)
+static void __init check_bugs(void)
 {
-#ifndef CONFIG_SMP
+#if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP)
        cpu_data(0).udelay_val = loops_per_jiffy;
 #endif
+#ifdef CONFIG_SPARC64
+       sstate_running();
+#endif
 }
index a2949aea48ef63e77433ae062871177fa84c6f4b..bcd83aa351c595e12cbb8dfc008b4395d7006384 100644 (file)
@@ -1,12 +1,55 @@
-/* $Id: byteorder.h,v 1.15 1997/12/16 19:20:44 davem Exp $ */
 #ifndef _SPARC_BYTEORDER_H
 #define _SPARC_BYTEORDER_H
 
 #include <asm/types.h>
+#include <asm/asi.h>
+
+#ifdef __GNUC__
+
+#ifdef CONFIG_SPARC32
+#define __SWAB_64_THRU_32__
+#endif
+
+#ifdef CONFIG_SPARC64
+
+static inline __u16 ___arch__swab16p(const __u16 *addr)
+{
+       __u16 ret;
+
+       __asm__ __volatile__ ("lduha [%1] %2, %0"
+                             : "=r" (ret)
+                             : "r" (addr), "i" (ASI_PL));
+       return ret;
+}
+
+static inline __u32 ___arch__swab32p(const __u32 *addr)
+{
+       __u32 ret;
+
+       __asm__ __volatile__ ("lduwa [%1] %2, %0"
+                             : "=r" (ret)
+                             : "r" (addr), "i" (ASI_PL));
+       return ret;
+}
+
+static inline __u64 ___arch__swab64p(const __u64 *addr)
+{
+       __u64 ret;
+
+       __asm__ __volatile__ ("ldxa [%1] %2, %0"
+                             : "=r" (ret)
+                             : "r" (addr), "i" (ASI_PL));
+       return ret;
+}
+
+#define __arch__swab16p(x) ___arch__swab16p(x)
+#define __arch__swab32p(x) ___arch__swab32p(x)
+#define __arch__swab64p(x) ___arch__swab64p(x)
+
+#endif /* CONFIG_SPARC64 */
+
+#define __BYTEORDER_HAS_U64__
 
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#  define __BYTEORDER_HAS_U64__
-#  define __SWAB_64_THRU_32__
 #endif
 
 #include <linux/byteorder/big_endian.h>
index cb971e88aea4f7b3a355a1b2505df188d432fec2..41f85ae4bd4ad7de07ff2fab14804ad75bac3d80 100644 (file)
@@ -1,20 +1,28 @@
-/* $Id: cache.h,v 1.9 1999/08/14 03:51:58 anton Exp $
- * cache.h:  Cache specific code for the Sparc.  These include flushing
+/* cache.h:  Cache specific code for the Sparc.  These include flushing
  *           and direct tag/data line access.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #ifndef _SPARC_CACHE_H
 #define _SPARC_CACHE_H
 
-#include <asm/asi.h>
-
 #define L1_CACHE_SHIFT 5
 #define L1_CACHE_BYTES 32
 #define L1_CACHE_ALIGN(x) ((((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)))
 
-#define SMP_CACHE_BYTES 32
+#ifdef CONFIG_SPARC32
+#define SMP_CACHE_BYTES_SHIFT 5
+#else
+#define SMP_CACHE_BYTES_SHIFT 6
+#endif
+
+#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT)
+
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
+#ifdef CONFIG_SPARC32
+#include <asm/asi.h>
 
 /* Direct access to the instruction cache is provided through and
  * alternate address space.  The IDC bit must be off in the ICCR on
@@ -125,5 +133,6 @@ static inline void flush_ei_user(unsigned int addr)
                             "r" (addr), "i" (ASI_M_FLUSH_USER) :
                             "memory");
 }
+#endif /* CONFIG_SPARC32 */
 
 #endif /* !(_SPARC_CACHE_H) */
index 8fe7c82a5e211f1bc177f1e7ba155aa205ff343f..8a1d9d6643b059343919a615064fb0068246a2be 100644 (file)
@@ -1,31 +1,34 @@
-/*
- *  include/asm-sparc/current.h
+/* include/asm-sparc/current.h
  *
  * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  * Copyright (C) 2002 Pete Zaitcev (zaitcev@yahoo.com)
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  *
  *  Derived from "include/asm-s390/current.h" by
  *  Martin Schwidefsky (schwidefsky@de.ibm.com)
  *  Derived from "include/asm-i386/current.h"
- */
-#ifndef _ASM_CURRENT_H
-#define _ASM_CURRENT_H
-
-/*
- * At the sparc64 DaveM keeps current_thread_info in %g4.
- * We might want to consider doing the same to shave a few cycles.
- */
+*/
+#ifndef _SPARC_CURRENT_H
+#define _SPARC_CURRENT_H
 
 #include <linux/thread_info.h>
 
-struct task_struct;
+#ifdef CONFIG_SPARC64
+register struct task_struct *current asm("g4");
+#endif
 
-/* Two stage process (inline + #define) for type-checking. */
-/* We also obfuscate get_current() to check if anyone used that by mistake. */
+#ifdef CONFIG_SPARC32
+/* We might want to consider using %g4 like sparc64 to shave a few cycles.
+ *
+ * Two stage process (inline + #define) for type-checking.
+ * We also obfuscate get_current() to check if anyone used that by mistake.
+ */
+struct task_struct;
 static inline struct task_struct *__get_current(void)
 {
        return current_thread_info()->task;
 }
 #define current __get_current()
+#endif
 
-#endif /* !(_ASM_CURRENT_H) */
+#endif /* !(_SPARC_CURRENT_H) */
index c0a7786d65f7768403f10ab5ce93e93d31490e96..680e51d87374cde9ab41d3d88f8c7f6655f438e5 100644 (file)
@@ -19,5 +19,3 @@ struct dev_archdata {
 };
 
 #endif /* _ASM_SPARC_DEVICE_H */
-
-
index ed41c8bac1fa7e91036d1d3588133f63f960e9ca..a9ef172977de30856cc1f54dfa05363a99a0e383 100644 (file)
@@ -1,4 +1,3 @@
-/* $Id: errno.h,v 1.6 1997/04/15 09:03:38 davem Exp $ */
 #ifndef _SPARC_ERRNO_H
 #define _SPARC_ERRNO_H
 
index c73ca081e1f56721c6f3912dd60730b1de6ecc2b..b83e447296553d08b9fd04541e70c024dc6276a2 100644 (file)
@@ -1,9 +1,17 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
+#ifndef _SPARC_FB_H_
+#define _SPARC_FB_H_
 #include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
 #include <asm/prom.h>
 
-#define fb_pgprotect(...) do {} while (0)
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+                               unsigned long off)
+{
+#ifdef CONFIG_SPARC64
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+}
 
 static inline int fb_is_primary_device(struct fb_info *info)
 {
@@ -18,4 +26,4 @@ static inline int fb_is_primary_device(struct fb_info *info)
        return 0;
 }
 
-#endif /* _ASM_FB_H_ */
+#endif /* _SPARC_FB_H_ */
index d638737ff13c3097c97b80ec9b6469d95e431857..38334351c36b04685861015c7a997676bd224b3a 100644 (file)
@@ -21,9 +21,4 @@ extern struct bus_type sbus_bus_type;
 
 #define of_bus_type    of_platform_bus_type    /* for compatibility */
 
-extern struct of_device *of_platform_device_create(struct device_node *np,
-                                                  const char *bus_id,
-                                                  struct device *parent,
-                                                  struct bus_type *bus);
-
 #endif /* _ASM_SPARC_OF_PLATFORM_H */
index 71f2a1998324eb372b16580b81cf743e593d4846..df5dc442248322878f6d6831a56bfef54a3ceade 100644 (file)
@@ -9,7 +9,7 @@
  * Copyright (C) 1996-2005 Paul Mackerras.
  *
  * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
- * Updates for SPARC32 by David S. Miller
+ * Updates for SPARC by David S. Miller
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -39,6 +39,7 @@ struct property {
        unsigned int unique_id;
 };
 
+struct of_irq_controller;
 struct device_node {
        const char      *name;
        const char      *type;
@@ -58,11 +59,19 @@ struct device_node {
        unsigned long _flags;
        void    *data;
        unsigned int unique_id;
+
+       struct of_irq_controller *irq_trans;
+};
+
+struct of_irq_controller {
+       unsigned int    (*irq_build)(struct device_node *, unsigned int, void *);
+       void            *data;
 };
 
 #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
 #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
 
+extern struct device_node *of_find_node_by_cpuid(int cpuid);
 extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
 extern int of_getintprop_default(struct device_node *np,
                                 const char *name,
index 53c95bdfc66eb5e005442e0db26bc3c34d7524a5..44208c2a188ee2458360ad279747c8ce6853f3f8 100644 (file)
@@ -1,98 +1 @@
-/* $Id: a.out.h,v 1.8 2002/02/09 19:49:31 davem Exp $ */
-#ifndef __SPARC64_A_OUT_H__
-#define __SPARC64_A_OUT_H__
-
-#define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
-#define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
-
-#ifndef __ASSEMBLY__
-
-struct exec {
-       unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
-       unsigned char a_toolversion:7;
-       unsigned char a_machtype;
-       unsigned short a_info;
-       unsigned int a_text;            /* length of text, in bytes */
-       unsigned int a_data;            /* length of data, in bytes */
-       unsigned int a_bss;             /* length of bss, in bytes */
-       unsigned int a_syms;            /* length of symbol table, in bytes */
-       unsigned int a_entry;           /* where program begins */
-       unsigned int a_trsize;
-       unsigned int a_drsize;
-};
-
-#endif /* !__ASSEMBLY__ */
-
-/* Where in the file does the text information begin? */
-#define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
-
-/* Where do the Symbols start? */
-#define N_SYMOFF(x)     (N_TXTOFF(x) + (x).a_text +   \
-                         (x).a_data + (x).a_trsize +  \
-                         (x).a_drsize)
-
-/* Where does text segment go in memory after being loaded? */
-#define N_TXTADDR(x)    (unsigned long)(((N_MAGIC(x) == ZMAGIC) &&      \
-                        ((x).a_entry < SPARC_PGSIZE)) ?                \
-                          0 : SPARC_PGSIZE)
-
-/* And same for the data segment.. */
-#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
-                      (N_TXTADDR(x) + (x).a_text)  \
-                       : (unsigned long)(_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#ifndef __ASSEMBLY__
-
-/*
- * Sparc relocation types
- */
-enum reloc_type
-{
-       RELOC_8,
-       RELOC_16,
-       RELOC_32,       /* simplest relocs */
-       RELOC_DISP8,
-       RELOC_DISP16,
-       RELOC_DISP32,   /* Disp's (pc-rel) */
-       RELOC_WDISP30,
-       RELOC_WDISP22,  /* SR word disp's */
-       RELOC_HI22,
-       RELOC_22,       /* SR 22-bit relocs */
-       RELOC_13,
-       RELOC_LO10,     /* SR 13&10-bit relocs */
-       RELOC_SFA_BASE,
-       RELOC_SFA_OFF13, /* SR S.F.A. relocs */
-       RELOC_BASE10,
-       RELOC_BASE13,
-       RELOC_BASE22,   /* base_relative pic */
-       RELOC_PC10,
-       RELOC_PC22,     /* special pc-rel pic */
-       RELOC_JMP_TBL,  /* jmp_tbl_rel in pic */
-       RELOC_SEGOFF16, /* ShLib offset-in-seg */
-       RELOC_GLOB_DAT,
-       RELOC_JMP_SLOT,
-       RELOC_RELATIVE  /* rtld relocs */
-};
-
-/*
- * Format of a relocation datum.
- */
-struct relocation_info /* used when header.a_machtype == M_SPARC */
-{
-        unsigned int    r_address;  /* relocation addr */
-        unsigned int    r_index:24; /* segment index or symbol index */
-        unsigned int    r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
-        unsigned int    r_pad:2;    /* <unused> */
-        enum reloc_type r_type:5;   /* type of relocation to perform */
-        int             r_addend;   /* addend for relocation value */
-};
-
-#define N_RELOCATION_INFO_DECLARED 1
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_A_OUT_H__) */
+#include <asm-sparc/a.out.h>
index 436a29129828eb0ee650294ddffc80aae939ffe9..1f45c67d73165619fe1ee9634751cfa675d1958a 100644 (file)
@@ -1,4 +1 @@
-#ifndef __ASM_SPARC64_AUXVEC_H
-#define __ASM_SPARC64_AUXVEC_H
-
-#endif /* !(__ASM_SPARC64_AUXVEC_H) */
+#include <asm-sparc/auxvec.h>
index abe163a50382e58873d4dbdd6b48529ac5f498e5..514eee20272e83b854b13f8330be14950d0f48b7 100644 (file)
@@ -1,73 +1 @@
-#ifndef _SPARC64_BPP_H
-#define _SPARC64_BPP_H
-
-/*
- * Copyright (c) 1995 Picture Elements
- *     Stephen Williams
- *     Gus Baldauf
- *
- * Linux/SPARC port by Peter Zaitcev.
- * Integration into SPARC tree by Tom Dyas.
- */
-
-#include  <linux/ioctl.h>
-
-/*
- * This is a driver that supports IEEE Std 1284-1994 communications
- * with compliant or compatible devices. It will use whatever features
- * the device supports, prefering those that are typically faster.
- *
- * When the device is opened, it is left in COMPATIBILITY mode, and
- * writes work like any printer device. The driver only attempt to
- * negotiate 1284 modes when needed so that plugs can be pulled,
- * switch boxes switched, etc., without disrupting things. It will
- * also leave the device in compatibility mode when closed.
- */
-
-
-
-/*
- * This driver also supplies ioctls to manually manipulate the
- * pins. This is great for testing devices, or writing code to deal
- * with bizzarro-mode of the ACME Special TurboThingy Plus.
- *
- * NOTE: These ioctl currently do not interact well with
- * read/write. Caveat emptor.
- *
- * PUT_PINS allows us to assign the sense of all the pins, including
- * the data pins if being driven by the host. The GET_PINS returns the
- * pins that the peripheral drives, including data if appropriate.
- */
-
-# define BPP_PUT_PINS _IOW('B', 1, int)
-# define BPP_GET_PINS _IOR('B', 2, char) /* that's bogus - should've been _IO */
-# define BPP_PUT_DATA _IOW('B', 3, int)
-# define BPP_GET_DATA _IOR('B', 4, char) /* ditto */
-
-/*
- * Set the data bus to input mode. Disengage the data bin driver and
- * be prepared to read values from the peripheral. If the arg is 0,
- * then revert the bus to output mode.
- */
-# define BPP_SET_INPUT _IOW('B', 5, int)
-
-/*
- * These bits apply to the PUT operation...
- */
-# define BPP_PP_nStrobe   0x0001
-# define BPP_PP_nAutoFd   0x0002
-# define BPP_PP_nInit     0x0004
-# define BPP_PP_nSelectIn 0x0008
-
-/*
- * These apply to the GET operation, which also reads the current value
- * of the previously put values. A bit mask of these will be returned
- * as a bit mask in the return code of the ioctl().
- */
-# define BPP_GP_nAck   0x0100
-# define BPP_GP_Busy   0x0200
-# define BPP_GP_PError 0x0400
-# define BPP_GP_Select 0x0800
-# define BPP_GP_nFault 0x1000
-
-#endif
+#include <asm-sparc/bpp.h>
diff --git a/include/asm-sparc64/bsderrno.h b/include/asm-sparc64/bsderrno.h
deleted file mode 100644 (file)
index 52fe880..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $Id: bsderrno.h,v 1.1 1996/12/26 13:25:21 davem Exp $
- * bsderrno.h: Error numbers for NetBSD binary compatibility
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC64_BSDERRNO_H
-#define _SPARC64_BSDERRNO_H
-
-#define BSD_EPERM         1      /* Operation not permitted */
-#define BSD_ENOENT        2      /* No such file or directory */
-#define BSD_ESRCH         3      /* No such process */
-#define BSD_EINTR         4      /* Interrupted system call */
-#define BSD_EIO           5      /* Input/output error */
-#define BSD_ENXIO         6      /* Device not configured */
-#define BSD_E2BIG         7      /* Argument list too long */
-#define BSD_ENOEXEC       8      /* Exec format error */
-#define BSD_EBADF         9      /* Bad file descriptor */
-#define BSD_ECHILD        10     /* No child processes */
-#define BSD_EDEADLK       11     /* Resource deadlock avoided */
-#define BSD_ENOMEM        12     /* Cannot allocate memory */
-#define BSD_EACCES        13     /* Permission denied */
-#define BSD_EFAULT        14     /* Bad address */
-#define BSD_ENOTBLK       15     /* Block device required */
-#define BSD_EBUSY         16     /* Device busy */
-#define BSD_EEXIST        17     /* File exists */
-#define BSD_EXDEV         18     /* Cross-device link */
-#define BSD_ENODEV        19     /* Operation not supported by device */
-#define BSD_ENOTDIR       20     /* Not a directory */
-#define BSD_EISDIR        21     /* Is a directory */
-#define BSD_EINVAL        22     /* Invalid argument */
-#define BSD_ENFILE        23     /* Too many open files in system */
-#define BSD_EMFILE        24     /* Too many open files */
-#define BSD_ENOTTY        25     /* Inappropriate ioctl for device */
-#define BSD_ETXTBSY       26     /* Text file busy */
-#define BSD_EFBIG         27     /* File too large */
-#define BSD_ENOSPC        28     /* No space left on device */
-#define BSD_ESPIPE        29     /* Illegal seek */
-#define BSD_EROFS         30     /* Read-only file system */
-#define BSD_EMLINK        31     /* Too many links */
-#define BSD_EPIPE         32     /* Broken pipe */
-#define BSD_EDOM          33     /* Numerical argument out of domain */
-#define BSD_ERANGE        34     /* Result too large */
-#define BSD_EAGAIN        35     /* Resource temporarily unavailable */
-#define BSD_EWOULDBLOCK   EAGAIN /* Operation would block */
-#define BSD_EINPROGRESS   36     /* Operation now in progress */
-#define BSD_EALREADY      37     /* Operation already in progress */
-#define BSD_ENOTSOCK      38     /* Socket operation on non-socket */
-#define BSD_EDESTADDRREQ  39     /* Destination address required */
-#define BSD_EMSGSIZE      40     /* Message too long */
-#define BSD_EPROTOTYPE    41     /* Protocol wrong type for socket */
-#define BSD_ENOPROTOOPT   42     /* Protocol not available */
-#define BSD_EPROTONOSUPPORT  43  /* Protocol not supported */
-#define BSD_ESOCKTNOSUPPORT  44  /* Socket type not supported */
-#define BSD_EOPNOTSUPP    45     /* Operation not supported */
-#define BSD_EPFNOSUPPORT  46     /* Protocol family not supported */
-#define BSD_EAFNOSUPPORT  47     /* Address family not supported by protocol family */
-#define BSD_EADDRINUSE    48     /* Address already in use */
-#define BSD_EADDRNOTAVAIL 49     /* Can't assign requested address */
-#define BSD_ENETDOWN      50     /* Network is down */
-#define BSD_ENETUNREACH   51     /* Network is unreachable */
-#define BSD_ENETRESET     52     /* Network dropped connection on reset */
-#define BSD_ECONNABORTED  53     /* Software caused connection abort */
-#define BSD_ECONNRESET    54     /* Connection reset by peer */
-#define BSD_ENOBUFS       55     /* No buffer space available */
-#define BSD_EISCONN       56     /* Socket is already connected */
-#define BSD_ENOTCONN      57     /* Socket is not connected */
-#define BSD_ESHUTDOWN     58     /* Can't send after socket shutdown */
-#define BSD_ETOOMANYREFS  59     /* Too many references: can't splice */
-#define BSD_ETIMEDOUT     60     /* Operation timed out */
-#define BSD_ECONNREFUSED  61     /* Connection refused */
-#define BSD_ELOOP         62     /* Too many levels of symbolic links */
-#define BSD_ENAMETOOLONG  63     /* File name too long */
-#define BSD_EHOSTDOWN     64     /* Host is down */
-#define BSD_EHOSTUNREACH  65     /* No route to host */
-#define BSD_ENOTEMPTY     66     /* Directory not empty */
-#define BSD_EPROCLIM      67     /* Too many processes */
-#define BSD_EUSERS        68     /* Too many users */
-#define BSD_EDQUOT        69     /* Disc quota exceeded */
-#define BSD_ESTALE        70     /* Stale NFS file handle */
-#define BSD_EREMOTE       71     /* Too many levels of remote in path */
-#define BSD_EBADRPC       72     /* RPC struct is bad */
-#define BSD_ERPCMISMATCH  73     /* RPC version wrong */
-#define BSD_EPROGUNAVAIL  74     /* RPC prog. not avail */
-#define BSD_EPROGMISMATCH 75     /* Program version wrong */
-#define BSD_EPROCUNAVAIL  76     /* Bad procedure for program */
-#define BSD_ENOLCK        77     /* No locks available */
-#define BSD_ENOSYS        78     /* Function not implemented */
-#define BSD_EFTYPE        79     /* Inappropriate file type or format */
-#define BSD_EAUTH         80     /* Authentication error */
-#define BSD_ENEEDAUTH     81     /* Need authenticator */
-#define BSD_ELAST         81     /* Must be equal largest errno */
-
-#endif /* !(_SPARC64_BSDERRNO_H) */
index 516bb27f3fc4e5a0bb32f8581f37901d56f213f7..3433737c7a67cab5433ee8bbf75a5f9a9e7891e4 100644 (file)
@@ -1,22 +1 @@
-#ifndef _SPARC64_BUG_H
-#define _SPARC64_BUG_H
-
-#ifdef CONFIG_BUG
-#include <linux/compiler.h>
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void do_BUG(const char *file, int line);
-#define BUG() do {                                     \
-       do_BUG(__FILE__, __LINE__);                     \
-       __builtin_trap();                               \
-} while (0)
-#else
-#define BUG()          __builtin_trap()
-#endif
-
-#define HAVE_ARCH_BUG
-#endif
-
-#include <asm-generic/bug.h>
-
-#endif
+#include <asm-sparc/bug.h>
index 11ade6841971f22e671cd26578bb851eac6ba02c..04ae9e2818cf8a342e39a00e39c614b2f8b9ce3c 100644 (file)
@@ -1,10 +1 @@
-/* bugs.h: Sparc64 probes for various bugs.
- *
- * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
- */
-#include <asm/sstate.h>
-
-static void __init check_bugs(void)
-{
-       sstate_running();
-}
+#include <asm-sparc/bugs.h>
index 3943022906fd4e59be65c8b451fb5d54179fb456..f672855bee1757546497d31d12121ddde0ee2ac8 100644 (file)
@@ -1,49 +1 @@
-#ifndef _SPARC64_BYTEORDER_H
-#define _SPARC64_BYTEORDER_H
-
-#include <asm/types.h>
-#include <asm/asi.h>
-
-#ifdef __GNUC__
-
-static inline __u16 ___arch__swab16p(const __u16 *addr)
-{
-       __u16 ret;
-
-       __asm__ __volatile__ ("lduha [%1] %2, %0"
-                             : "=r" (ret)
-                             : "r" (addr), "i" (ASI_PL));
-       return ret;
-}
-
-static inline __u32 ___arch__swab32p(const __u32 *addr)
-{
-       __u32 ret;
-
-       __asm__ __volatile__ ("lduwa [%1] %2, %0"
-                             : "=r" (ret)
-                             : "r" (addr), "i" (ASI_PL));
-       return ret;
-}
-
-static inline __u64 ___arch__swab64p(const __u64 *addr)
-{
-       __u64 ret;
-
-       __asm__ __volatile__ ("ldxa [%1] %2, %0"
-                             : "=r" (ret)
-                             : "r" (addr), "i" (ASI_PL));
-       return ret;
-}
-
-#define __arch__swab16p(x) ___arch__swab16p(x)
-#define __arch__swab32p(x) ___arch__swab32p(x)
-#define __arch__swab64p(x) ___arch__swab64p(x)
-
-#define __BYTEORDER_HAS_U64__
-
-#endif /* __GNUC__ */
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _SPARC64_BYTEORDER_H */
+#include <asm-sparc/byteorder.h>
index e9df17acedde65d0dfcaddf2dffe1802f68354f1..fa9de5cadbf1422336604a1fae0895ae4a054b9c 100644 (file)
@@ -1,18 +1 @@
-/*
- * include/asm-sparc64/cache.h
- */
-#ifndef __ARCH_SPARC64_CACHE_H
-#define __ARCH_SPARC64_CACHE_H
-
-/* bytes per L1 cache line */
-#define        L1_CACHE_SHIFT  5
-#define        L1_CACHE_BYTES  32 /* Two 16-byte sub-blocks per line. */
-
-#define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
-
-#define        SMP_CACHE_BYTES_SHIFT   6
-#define        SMP_CACHE_BYTES         (1 << SMP_CACHE_BYTES_SHIFT) /* L2 cache line size. */
-
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
-#endif
+#include <asm-sparc/cache.h>
index dec2fc7a36f8dfa640b46a2dfe4ef167b9271ea6..435f37a92f7cd03a846fa8742d91c732d73df11c 100644 (file)
@@ -1,6 +1 @@
-#ifndef __SPARC64_CPUTIME_H
-#define __SPARC64_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __SPARC64_CPUTIME_H */
+#include <asm-sparc/cputime.h>
index 6c21e4ee24751e602a106691d4444ad6f67f8f5b..a7904a7f53a856f757f85683abe7fc7d41cfe554 100644 (file)
@@ -1,8 +1 @@
-#ifndef _SPARC64_CURRENT_H
-#define _SPARC64_CURRENT_H
-
-#include <linux/thread_info.h>
-
-register struct task_struct *current asm("g4");
-
-#endif /* !(_SPARC64_CURRENT_H) */
+#include <asm-sparc/current.h>
index 5111e8717be321e395ea8ebf76c8ff32f02ed9cf..4145c47097e284e01bfa10ea7612b8e950a2de4d 100644 (file)
@@ -1,21 +1 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#ifndef _ASM_SPARC64_DEVICE_H
-#define _ASM_SPARC64_DEVICE_H
-
-struct device_node;
-struct of_device;
-
-struct dev_archdata {
-       void                    *iommu;
-       void                    *stc;
-       void                    *host_controller;
-
-       struct device_node      *prom_node;
-       struct of_device        *op;
-};
-
-#endif /* _ASM_SPARC64_DEVICE_H */
+#include <asm-sparc/device.h>
index 6cd978cefb2850be383e462f77a05c23ff7adc33..928c94f99ecf74981a32ade289b8c3e9903fab50 100644 (file)
@@ -1 +1 @@
-#include <asm-generic/div64.h>
+#include <asm-sparc/div64.h>
index 108d8c48e42e86978077354f2fa1b151f25c41df..2cac7b644da8ac2f6fe148db7b29a2e7c7860e57 100644 (file)
@@ -1,6 +1 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
+#include <asm-sparc/emergency-restart.h>
index ea3509ee1b0bbc228b5eacf2887816ba6c9afc76..9701fe01cc533e9da025c2844bd222eceb0ec2d6 100644 (file)
@@ -1,114 +1 @@
-/* $Id: errno.h,v 1.2 1997/04/15 12:46:11 jj Exp $ */
-#ifndef _SPARC64_ERRNO_H
-#define _SPARC64_ERRNO_H
-
-/* These match the SunOS error numbering scheme. */
-
-#include <asm-generic/errno-base.h>
-
-#define        EWOULDBLOCK     EAGAIN  /* Operation would block */
-#define        EINPROGRESS     36      /* Operation now in progress */
-#define        EALREADY        37      /* Operation already in progress */
-#define        ENOTSOCK        38      /* Socket operation on non-socket */
-#define        EDESTADDRREQ    39      /* Destination address required */
-#define        EMSGSIZE        40      /* Message too long */
-#define        EPROTOTYPE      41      /* Protocol wrong type for socket */
-#define        ENOPROTOOPT     42      /* Protocol not available */
-#define        EPROTONOSUPPORT 43      /* Protocol not supported */
-#define        ESOCKTNOSUPPORT 44      /* Socket type not supported */
-#define        EOPNOTSUPP      45      /* Op not supported on transport endpoint */
-#define        EPFNOSUPPORT    46      /* Protocol family not supported */
-#define        EAFNOSUPPORT    47      /* Address family not supported by protocol */
-#define        EADDRINUSE      48      /* Address already in use */
-#define        EADDRNOTAVAIL   49      /* Cannot assign requested address */
-#define        ENETDOWN        50      /* Network is down */
-#define        ENETUNREACH     51      /* Network is unreachable */
-#define        ENETRESET       52      /* Net dropped connection because of reset */
-#define        ECONNABORTED    53      /* Software caused connection abort */
-#define        ECONNRESET      54      /* Connection reset by peer */
-#define        ENOBUFS         55      /* No buffer space available */
-#define        EISCONN         56      /* Transport endpoint is already connected */
-#define        ENOTCONN        57      /* Transport endpoint is not connected */
-#define        ESHUTDOWN       58      /* No send after transport endpoint shutdown */
-#define        ETOOMANYREFS    59      /* Too many references: cannot splice */
-#define        ETIMEDOUT       60      /* Connection timed out */
-#define        ECONNREFUSED    61      /* Connection refused */
-#define        ELOOP           62      /* Too many symbolic links encountered */
-#define        ENAMETOOLONG    63      /* File name too long */
-#define        EHOSTDOWN       64      /* Host is down */
-#define        EHOSTUNREACH    65      /* No route to host */
-#define        ENOTEMPTY       66      /* Directory not empty */
-#define EPROCLIM        67      /* SUNOS: Too many processes */
-#define        EUSERS          68      /* Too many users */
-#define        EDQUOT          69      /* Quota exceeded */
-#define        ESTALE          70      /* Stale NFS file handle */
-#define        EREMOTE         71      /* Object is remote */
-#define        ENOSTR          72      /* Device not a stream */
-#define        ETIME           73      /* Timer expired */
-#define        ENOSR           74      /* Out of streams resources */
-#define        ENOMSG          75      /* No message of desired type */
-#define        EBADMSG         76      /* Not a data message */
-#define        EIDRM           77      /* Identifier removed */
-#define        EDEADLK         78      /* Resource deadlock would occur */
-#define        ENOLCK          79      /* No record locks available */
-#define        ENONET          80      /* Machine is not on the network */
-#define ERREMOTE        81      /* SunOS: Too many lvls of remote in path */
-#define        ENOLINK         82      /* Link has been severed */
-#define        EADV            83      /* Advertise error */
-#define        ESRMNT          84      /* Srmount error */
-#define        ECOMM           85      /* Communication error on send */
-#define        EPROTO          86      /* Protocol error */
-#define        EMULTIHOP       87      /* Multihop attempted */
-#define        EDOTDOT         88      /* RFS specific error */
-#define        EREMCHG         89      /* Remote address changed */
-#define        ENOSYS          90      /* Function not implemented */
-
-/* The rest have no SunOS equivalent. */
-#define        ESTRPIPE        91      /* Streams pipe error */
-#define        EOVERFLOW       92      /* Value too large for defined data type */
-#define        EBADFD          93      /* File descriptor in bad state */
-#define        ECHRNG          94      /* Channel number out of range */
-#define        EL2NSYNC        95      /* Level 2 not synchronized */
-#define        EL3HLT          96      /* Level 3 halted */
-#define        EL3RST          97      /* Level 3 reset */
-#define        ELNRNG          98      /* Link number out of range */
-#define        EUNATCH         99      /* Protocol driver not attached */
-#define        ENOCSI          100     /* No CSI structure available */
-#define        EL2HLT          101     /* Level 2 halted */
-#define        EBADE           102     /* Invalid exchange */
-#define        EBADR           103     /* Invalid request descriptor */
-#define        EXFULL          104     /* Exchange full */
-#define        ENOANO          105     /* No anode */
-#define        EBADRQC         106     /* Invalid request code */
-#define        EBADSLT         107     /* Invalid slot */
-#define        EDEADLOCK       108     /* File locking deadlock error */
-#define        EBFONT          109     /* Bad font file format */
-#define        ELIBEXEC        110     /* Cannot exec a shared library directly */
-#define        ENODATA         111     /* No data available */
-#define        ELIBBAD         112     /* Accessing a corrupted shared library */
-#define        ENOPKG          113     /* Package not installed */
-#define        ELIBACC         114     /* Can not access a needed shared library */
-#define        ENOTUNIQ        115     /* Name not unique on network */
-#define        ERESTART        116     /* Interrupted syscall should be restarted */
-#define        EUCLEAN         117     /* Structure needs cleaning */
-#define        ENOTNAM         118     /* Not a XENIX named type file */
-#define        ENAVAIL         119     /* No XENIX semaphores available */
-#define        EISNAM          120     /* Is a named type file */
-#define        EREMOTEIO       121     /* Remote I/O error */
-#define        EILSEQ          122     /* Illegal byte sequence */
-#define        ELIBMAX         123     /* Atmpt to link in too many shared libs */
-#define        ELIBSCN         124     /* .lib section in a.out corrupted */
-
-#define ENOMEDIUM       125     /* No medium found */
-#define EMEDIUMTYPE     126     /* Wrong medium type */
-#define        ECANCELED       127     /* Operation Cancelled */
-#define        ENOKEY          128     /* Required key not available */
-#define        EKEYEXPIRED     129     /* Key has expired */
-#define        EKEYREVOKED     130     /* Key has been revoked */
-#define        EKEYREJECTED    131     /* Key was rejected by service */
-
-/* for robust mutexes */
-#define        EOWNERDEAD      132     /* Owner died */
-#define        ENOTRECOVERABLE 133     /* State not recoverable */
-
-#endif /* !(_SPARC64_ERRNO_H) */
+#include <asm-sparc/errno.h>
index 389012e5fbad874bcb2432f41472ad9d948ecd51..1c2ac5832f3998a060c74155e5e784415d5819f9 100644 (file)
@@ -1,27 +1 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-#include <linux/fs.h>
-#include <asm/page.h>
-#include <asm/prom.h>
-
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
-                               unsigned long off)
-{
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-}
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
-       struct device *dev = info->device;
-       struct device_node *node;
-
-       node = dev->archdata.prom_node;
-       if (node &&
-           node == of_console_device)
-               return 1;
-
-       return 0;
-}
-
-#endif /* _ASM_FB_H_ */
+#include <asm-sparc/fb.h>
index b6ece223562de86719dc403595eca551140be570..c299b853b5babae9520be2238620319cf490c149 100644 (file)
@@ -16,7 +16,7 @@
 /* BIO layer definitions. */
 extern unsigned long kern_base, kern_size;
 #define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
-#define BIO_VMERGE_BOUNDARY    0
+#define BIO_VMERGE_BOUNDARY    8192
 
 static inline u8 _inb(unsigned long addr)
 {
index 9eac6676caf10a5887a749c6a1811f21f6d45b48..46325ddee23b32f3677638e11d2b76ae7c8f4840 100644 (file)
@@ -26,6 +26,7 @@ struct iommu_arena {
 struct iommu {
        spinlock_t              lock;
        struct iommu_arena      arena;
+       void                    (*flush_all)(struct iommu *);
        iopte_t                 *page_table;
        u32                     page_table_map_base;
        unsigned long           iommu_control;
index 5020eaf67c292d10c34831cb71ce5ec421a6e8fd..7237dd87663ec4857f9ae957c54acad25831745e 100644 (file)
@@ -14,11 +14,15 @@ typedef u32 kprobe_opcode_t;
 
 #define arch_remove_kprobe(p)  do {} while (0)
 
+#define ARCH_SUPPORTS_KRETPROBES
+
 #define flush_insn_slot(p)             \
 do {   flushi(&(p)->ainsn.insn[0]);    \
        flushi(&(p)->ainsn.insn[1]);    \
 } while (0)
 
+void kretprobe_trampoline(void);
+
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
        /* copy of the original instruction */
index 46d69b3223c587cb64fd10729488dda8b44a553f..a769fdbe164a873023ff2a0a31c7293647e1aa71 100644 (file)
@@ -1,38 +1 @@
-#ifndef _ASM_SPARC64_OF_DEVICE_H
-#define _ASM_SPARC64_OF_DEVICE_H
-#ifdef __KERNEL__
-
-#include <linux/device.h>
-#include <linux/of.h>
-#include <linux/mod_devicetable.h>
-#include <asm/openprom.h>
-
-/*
- * The of_device is a kind of "base class" that is a superset of
- * struct device for use by devices attached to an OF node and
- * probed using OF properties.
- */
-struct of_device
-{
-       struct device_node              *node;
-       struct device                   dev;
-       struct resource                 resource[PROMREG_MAX];
-       unsigned int                    irqs[PROMINTR_MAX];
-       int                             num_irqs;
-
-       void                            *sysdata;
-
-       int                             slot;
-       int                             portid;
-       int                             clock_freq;
-};
-
-extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
-extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
-
-/* These are just here during the transition */
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_SPARC64_OF_DEVICE_H */
+#include <asm-sparc/of_device.h>
index f15cfa723916a3bac7180f6005a96f318b1e5d7f..78aa032b674c42bb7a4e1f02aaa6d243d298d13f 100644 (file)
@@ -22,9 +22,4 @@ extern struct bus_type sbus_bus_type;
 
 #define of_bus_type    of_platform_bus_type    /* for compatibility */
 
-extern struct of_device *of_platform_device_create(struct device_node *np,
-                                                  const char *bus_id,
-                                                  struct device *parent,
-                                                  struct bus_type *bus);
-
 #endif /* _ASM_SPARC64_OF_PLATFORM_H */
index 07843f9f05df5771928f8f53285e158f27a919fd..5fa166ee3ffa3c5103a97c9f6b6afcd964bfcdd7 100644 (file)
@@ -1,103 +1 @@
-#ifndef _SPARC64_PROM_H
-#define _SPARC64_PROM_H
-#ifdef __KERNEL__
-
-/*
- * Definitions for talking to the Open Firmware PROM on
- * Power Macintosh computers.
- *
- * Copyright (C) 1996-2005 Paul Mackerras.
- *
- * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
- * Updates for SPARC64 by David S. Miller
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <asm/atomic.h>
-
-#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT        2
-#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT        1
-
-#define of_compat_cmp(s1, s2, l)       strncmp((s1), (s2), (l))
-#define of_prop_cmp(s1, s2)            strcasecmp((s1), (s2))
-#define of_node_cmp(s1, s2)            strcmp((s1), (s2))
-
-typedef u32 phandle;
-typedef u32 ihandle;
-
-struct property {
-       char    *name;
-       int     length;
-       void    *value;
-       struct property *next;
-       unsigned long _flags;
-       unsigned int unique_id;
-};
-
-struct of_irq_controller;
-struct device_node {
-       const char      *name;
-       const char      *type;
-       phandle node;
-       char    *path_component_name;
-       char    *full_name;
-
-       struct  property *properties;
-       struct  property *deadprops; /* removed properties */
-       struct  device_node *parent;
-       struct  device_node *child;
-       struct  device_node *sibling;
-       struct  device_node *next;      /* next device of same type */
-       struct  device_node *allnext;   /* next in list of all nodes */
-       struct  proc_dir_entry *pde;    /* this node's proc directory */
-       struct  kref kref;
-       unsigned long _flags;
-       void    *data;
-       unsigned int unique_id;
-
-       struct of_irq_controller *irq_trans;
-};
-
-struct of_irq_controller {
-       unsigned int    (*irq_build)(struct device_node *, unsigned int, void *);
-       void            *data;
-};
-
-#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
-#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
-
-extern struct device_node *of_find_node_by_cpuid(int cpuid);
-extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
-extern int of_getintprop_default(struct device_node *np,
-                                const char *name,
-                                int def);
-extern int of_find_in_proplist(const char *list, const char *match, int len);
-
-extern void prom_build_devicetree(void);
-
-/* Dummy ref counting routines - to be implemented later */
-static inline struct device_node *of_node_get(struct device_node *node)
-{
-       return node;
-}
-static inline void of_node_put(struct device_node *node)
-{
-}
-
-/*
- * NB:  This is here while we transition from using asm/prom.h
- * to linux/of.h
- */
-#include <linux/of.h>
-
-extern struct device_node *of_console_device;
-extern char *of_console_path;
-extern char *of_console_options;
-
-#endif /* __KERNEL__ */
-#endif /* _SPARC64_PROM_H */
+#include <asm-sparc/prom.h>
index 661d8cd0883954cd0f0312586481bb915dee145e..74a539a9bd5952b246e4450cbb6136b22e59bb3c 100644 (file)
@@ -57,6 +57,7 @@ typedef struct { unsigned long pte; } pte_t;
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
 
 #define pte_val(x)      ((x).pte)
 #define pmd_val(x)      ((x).pmd)
index 98a9ca266531e5c823f125d72f5445f7474d4a5d..7a72d6aa50be85527b904fbbfe815c0701760d77 100644 (file)
@@ -89,6 +89,10 @@ extern int acpi_pci_disabled;
 extern int acpi_skip_timer_override;
 extern int acpi_use_timer_override;
 
+extern u8 acpi_sci_flags;
+extern int acpi_sci_override_gsi;
+void acpi_pic_sci_set_trigger(unsigned int, u16);
+
 static inline void disable_acpi(void)
 {
        acpi_disabled = 1;
index 8dd8c5e3cc7fca8dabc802662d1acd0263315366..6a22212b4b204b93570b84a600ec1e800e821aee 100644 (file)
@@ -44,6 +44,8 @@ int set_memory_np(unsigned long addr, int numpages);
 
 void clflush_cache_range(void *addr, unsigned int size);
 
+void cpa_init(void);
+
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void);
 #endif
index 811fe14f70b26f1e835657ce0b9a95f3a065b103..9e7280092a486ba33d31ef567f22349fc25e0810 100644 (file)
@@ -206,12 +206,17 @@ static inline u16 geode_mfgpt_read(int timer, u16 reg)
        return inw(base + reg + (timer * 8));
 }
 
-extern int __init geode_mfgpt_detect(void);
 extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable);
 extern int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable);
-extern int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner);
+extern int geode_mfgpt_alloc_timer(int timer, int domain);
 
 #define geode_mfgpt_setup_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 1)
 #define geode_mfgpt_release_irq(t, c, i) geode_mfgpt_set_irq((t), (c), (i), 0)
 
+#ifdef CONFIG_GEODE_MFGPT_TIMER
+extern int __init mfgpt_timer_setup(void);
+#else
+static inline int mfgpt_timer_setup(void) { return 0; }
+#endif
+
 #endif
index 984998a30741c0a604faaa36b217cbc957a04e55..5f7257fd589b9529c4c890709e58a97a8cef241a 100644 (file)
@@ -48,7 +48,6 @@ typedef unsigned long pgprotval_t;
 typedef unsigned long  phys_addr_t;
 
 typedef union { pteval_t pte, pte_low; } pte_t;
-typedef pte_t boot_pte_t;
 
 #endif /* __ASSEMBLY__ */
 #endif /* CONFIG_X86_PAE */
index 44c0a4f1b1eb64d10bd1e33013b7e52a3dcc55f1..174b87738714fe634d135c8738df8a6f5ba8a0c5 100644 (file)
@@ -255,7 +255,7 @@ enum {
  * NOTE: the return type is pte_t but if the pmd is PSE then we return it
  * as a pte too.
  */
-extern pte_t *lookup_address(unsigned long address, int *level);
+extern pte_t *lookup_address(unsigned long address, unsigned int *level);
 
 /* local pte updates need not use xchg for locking */
 static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
index 80dd438642f69b293e5aa090d9fb222d5f3c2db1..a842c7222b1eef0f598a8de4a4c5375506e0b2c5 100644 (file)
@@ -52,10 +52,6 @@ void paging_init(void);
 #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
 #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
 
-#define TWOLEVEL_PGDIR_SHIFT   22
-#define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
-#define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
-
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
  * physical memory until the kernel virtual memory starts.  That means that
index 0ab3a32323307d1445392ea571550698c0cd70d1..974f5b7bb205b749a0eb8b2e959b95e829244602 100644 (file)
@@ -5,15 +5,6 @@
 /* These definitions are for GCC v4.x.  */
 #include <linux/compiler-gcc.h>
 
-#ifdef CONFIG_FORCED_INLINING
-# undef inline
-# undef __inline__
-# undef __inline
-# define inline                        inline          __attribute__((always_inline))
-# define __inline__            __inline__      __attribute__((always_inline))
-# define __inline              __inline        __attribute__((always_inline))
-#endif
-
 #define __used                 __attribute__((__used__))
 #define __must_check           __attribute__((warn_unused_result))
 #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
index c4f635a4dd254ff3ce0a79a976dd3a960925bc81..25003254859773c657f510d0e2460c900d47a6c9 100644 (file)
@@ -489,6 +489,13 @@ do {                                                                              \
 #define        EXT4_ERROR_FS                   0x0002  /* Errors detected */
 #define        EXT4_ORPHAN_FS                  0x0004  /* Orphans being recovered */
 
+/*
+ * Misc. filesystem flags
+ */
+#define EXT2_FLAGS_SIGNED_HASH         0x0001  /* Signed dirhash in use */
+#define EXT2_FLAGS_UNSIGNED_HASH       0x0002  /* Unsigned dirhash in use */
+#define EXT2_FLAGS_TEST_FILESYS                0x0004  /* to test development code */
+
 /*
  * Mount flags
  */
index 600fc3bcf63ec2509f3e758a448083914d2c5b01..1ad56a7b2f744d3b78a201224303d8b71c6e8780 100644 (file)
@@ -316,7 +316,7 @@ static inline u64 hrtimer_forward_now(struct hrtimer *timer,
 
 /* Precise sleep: */
 extern long hrtimer_nanosleep(struct timespec *rqtp,
-                             struct timespec *rmtp,
+                             struct timespec __user *rmtp,
                              const enum hrtimer_mode mode,
                              const clockid_t clockid);
 extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
index 9815951ec995d43f02ad87ce78f1c0fbf5ecdb2b..925d57b236aad811344b7b6a787c31c32c45eb2b 100644 (file)
@@ -51,10 +51,8 @@ extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
                                        gfp_t gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
-static inline struct mem_cgroup *mm_cgroup(const struct mm_struct *mm)
-{
-       return rcu_dereference(mm->mem_cgroup);
-}
+#define vm_match_cgroup(mm, cgroup)    \
+       ((cgroup) == rcu_dereference((mm)->mem_cgroup))
 
 extern int mem_cgroup_prepare_migration(struct page *page);
 extern void mem_cgroup_end_migration(struct page *page);
@@ -123,9 +121,9 @@ static inline int mem_cgroup_cache_charge(struct page *page,
        return 0;
 }
 
-static inline struct mem_cgroup *mm_cgroup(const struct mm_struct *mm)
+static inline int vm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
 {
-       return NULL;
+       return 1;
 }
 
 static inline int task_in_mem_cgroup(struct task_struct *task,
diff --git a/include/linux/memstick.h b/include/linux/memstick.h
new file mode 100644 (file)
index 0000000..334d059
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ *  Sony MemoryStick support
+ *
+ *  Copyright (C) 2007 Alex Dubov <oakad@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef _MEMSTICK_H
+#define _MEMSTICK_H
+
+#include <linux/workqueue.h>
+#include <linux/scatterlist.h>
+#include <linux/device.h>
+
+/*** Hardware based structures ***/
+
+struct ms_status_register {
+       unsigned char reserved;
+       unsigned char interrupt;
+#define MEMSTICK_INT_CMDNAK             0x0001
+#define MEMSTICK_INT_BREQ               0x0020
+#define MEMSTICK_INT_ERR                0x0040
+#define MEMSTICK_INT_CED                0x0080
+
+       unsigned char status0;
+#define MEMSTICK_STATUS0_WP             0x0001
+#define MEMSTICK_STATUS0_SL             0x0002
+#define MEMSTICK_STATUS0_BF             0x0010
+#define MEMSTICK_STATUS0_BE             0x0020
+#define MEMSTICK_STATUS0_FB0            0x0040
+#define MEMSTICK_STATUS0_MB             0x0080
+
+       unsigned char status1;
+#define MEMSTICK_STATUS1_UCFG           0x0001
+#define MEMSTICK_STATUS1_FGER           0x0002
+#define MEMSTICK_STATUS1_UCEX           0x0004
+#define MEMSTICK_STATUS1_EXER           0x0008
+#define MEMSTICK_STATUS1_UCDT           0x0010
+#define MEMSTICK_STATUS1_DTER           0x0020
+#define MEMSTICK_STATUS1_FBI            0x0040
+#define MEMSTICK_STATUS1_MB             0x0080
+} __attribute__((packed));
+
+struct ms_id_register {
+       unsigned char type;
+       unsigned char reserved;
+       unsigned char category;
+       unsigned char class;
+} __attribute__((packed));
+
+struct ms_param_register {
+       unsigned char system;
+       unsigned char block_address_msb;
+       unsigned short block_address;
+       unsigned char cp;
+#define MEMSTICK_CP_BLOCK               0x0000
+#define MEMSTICK_CP_PAGE                0x0020
+#define MEMSTICK_CP_EXTRA               0x0040
+#define MEMSTICK_CP_OVERWRITE           0x0080
+
+       unsigned char page_address;
+} __attribute__((packed));
+
+struct ms_extra_data_register {
+       unsigned char  overwrite_flag;
+#define MEMSTICK_OVERWRITE_UPDATA       0x0010
+#define MEMSTICK_OVERWRITE_PAGE         0x0060
+#define MEMSTICK_OVERWRITE_BLOCK        0x0080
+
+       unsigned char  management_flag;
+#define MEMSTICK_MANAGEMENT_SYSTEM      0x0004
+#define MEMSTICK_MANAGEMENT_TRANS_TABLE 0x0008
+#define MEMSTICK_MANAGEMENT_COPY        0x0010
+#define MEMSTICK_MANAGEMENT_ACCESS      0x0020
+
+       unsigned short logical_address;
+} __attribute__((packed));
+
+struct ms_register {
+       struct ms_status_register     status;
+       struct ms_id_register         id;
+       unsigned char                 reserved[8];
+       struct ms_param_register      param;
+       struct ms_extra_data_register extra_data;
+} __attribute__((packed));
+
+struct mspro_param_register {
+       unsigned char  system;
+       unsigned short data_count;
+       unsigned int   data_address;
+       unsigned char  cmd_param;
+} __attribute__((packed));
+
+struct mspro_register {
+       struct ms_status_register    status;
+       struct ms_id_register        id;
+       unsigned char                reserved[8];
+       struct mspro_param_register  param;
+} __attribute__((packed));
+
+struct ms_register_addr {
+       unsigned char r_offset;
+       unsigned char r_length;
+       unsigned char w_offset;
+       unsigned char w_length;
+} __attribute__((packed));
+
+enum {
+       MS_TPC_READ_LONG_DATA   = 0x02,
+       MS_TPC_READ_SHORT_DATA  = 0x03,
+       MS_TPC_READ_REG         = 0x04,
+       MS_TPC_READ_IO_DATA     = 0x05, /* unverified */
+       MS_TPC_GET_INT          = 0x07,
+       MS_TPC_SET_RW_REG_ADRS  = 0x08,
+       MS_TPC_EX_SET_CMD       = 0x09,
+       MS_TPC_WRITE_IO_DATA    = 0x0a, /* unverified */
+       MS_TPC_WRITE_REG        = 0x0b,
+       MS_TPC_WRITE_SHORT_DATA = 0x0c,
+       MS_TPC_WRITE_LONG_DATA  = 0x0d,
+       MS_TPC_SET_CMD          = 0x0e
+};
+
+enum {
+       MS_CMD_BLOCK_END     = 0x33,
+       MS_CMD_RESET         = 0x3c,
+       MS_CMD_BLOCK_WRITE   = 0x55,
+       MS_CMD_SLEEP         = 0x5a,
+       MS_CMD_BLOCK_ERASE   = 0x99,
+       MS_CMD_BLOCK_READ    = 0xaa,
+       MS_CMD_CLEAR_BUF     = 0xc3,
+       MS_CMD_FLASH_STOP    = 0xcc,
+       MSPRO_CMD_FORMAT     = 0x10,
+       MSPRO_CMD_SLEEP      = 0x11,
+       MSPRO_CMD_READ_DATA  = 0x20,
+       MSPRO_CMD_WRITE_DATA = 0x21,
+       MSPRO_CMD_READ_ATRB  = 0x24,
+       MSPRO_CMD_STOP       = 0x25,
+       MSPRO_CMD_ERASE      = 0x26,
+       MSPRO_CMD_SET_IBA    = 0x46,
+       MSPRO_CMD_SET_IBD    = 0x47
+/*
+       MSPRO_CMD_RESET
+       MSPRO_CMD_WAKEUP
+       MSPRO_CMD_IN_IO_DATA
+       MSPRO_CMD_OUT_IO_DATA
+       MSPRO_CMD_READ_IO_ATRB
+       MSPRO_CMD_IN_IO_FIFO
+       MSPRO_CMD_OUT_IO_FIFO
+       MSPRO_CMD_IN_IOM
+       MSPRO_CMD_OUT_IOM
+*/
+};
+
+/*** Driver structures and functions ***/
+
+#define MEMSTICK_PART_SHIFT 3
+
+enum memstick_param { MEMSTICK_POWER = 1, MEMSTICK_INTERFACE };
+
+#define MEMSTICK_POWER_OFF 0
+#define MEMSTICK_POWER_ON  1
+
+#define MEMSTICK_SERIAL   0
+#define MEMSTICK_PARALLEL 1
+
+struct memstick_host;
+struct memstick_driver;
+
+#define MEMSTICK_MATCH_ALL            0x01
+
+#define MEMSTICK_TYPE_LEGACY          0xff
+#define MEMSTICK_TYPE_DUO             0x00
+#define MEMSTICK_TYPE_PRO             0x01
+
+#define MEMSTICK_CATEGORY_STORAGE     0xff
+#define MEMSTICK_CATEGORY_STORAGE_DUO 0x00
+
+#define MEMSTICK_CLASS_GENERIC        0xff
+#define MEMSTICK_CLASS_GENERIC_DUO    0x00
+
+
+struct memstick_device_id {
+       unsigned char match_flags;
+       unsigned char type;
+       unsigned char category;
+       unsigned char class;
+};
+
+struct memstick_request {
+       unsigned char tpc;
+       unsigned char data_dir:1,
+                     need_card_int:1,
+                     get_int_reg:1,
+                     io_type:2;
+#define               MEMSTICK_IO_NONE 0
+#define               MEMSTICK_IO_VAL  1
+#define               MEMSTICK_IO_SG   2
+
+       unsigned char int_reg;
+       int           error;
+       union {
+               struct scatterlist sg;
+               struct {
+                       unsigned char data_len;
+                       unsigned char data[15];
+               };
+       };
+};
+
+struct memstick_dev {
+       struct memstick_device_id id;
+       struct memstick_host     *host;
+       struct ms_register_addr  reg_addr;
+       struct completion        mrq_complete;
+       struct memstick_request  current_mrq;
+
+       /* Check that media driver is still willing to operate the device. */
+       int                      (*check)(struct memstick_dev *card);
+       /* Get next request from the media driver.                         */
+       int                      (*next_request)(struct memstick_dev *card,
+                                                struct memstick_request **mrq);
+
+       struct device            dev;
+};
+
+struct memstick_host {
+       struct mutex        lock;
+       unsigned int        id;
+       unsigned int        caps;
+#define MEMSTICK_CAP_PARALLEL      1
+#define MEMSTICK_CAP_AUTO_GET_INT  2
+
+       struct work_struct  media_checker;
+       struct class_device cdev;
+
+       struct memstick_dev *card;
+       unsigned int        retries;
+
+       /* Notify the host that some requests are pending. */
+       void                (*request)(struct memstick_host *host);
+       /* Set host IO parameters (power, clock, etc).     */
+       void                (*set_param)(struct memstick_host *host,
+                                        enum memstick_param param,
+                                        int value);
+       unsigned long       private[0] ____cacheline_aligned;
+};
+
+struct memstick_driver {
+       struct memstick_device_id *id_table;
+       int                       (*probe)(struct memstick_dev *card);
+       void                      (*remove)(struct memstick_dev *card);
+       int                       (*suspend)(struct memstick_dev *card,
+                                            pm_message_t state);
+       int                       (*resume)(struct memstick_dev *card);
+
+       struct device_driver      driver;
+};
+
+int memstick_register_driver(struct memstick_driver *drv);
+void memstick_unregister_driver(struct memstick_driver *drv);
+
+struct memstick_host *memstick_alloc_host(unsigned int extra,
+                                         struct device *dev);
+
+int memstick_add_host(struct memstick_host *host);
+void memstick_remove_host(struct memstick_host *host);
+void memstick_free_host(struct memstick_host *host);
+void memstick_detect_change(struct memstick_host *host);
+
+void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
+                         struct scatterlist *sg);
+void memstick_init_req(struct memstick_request *mrq, unsigned char tpc,
+                      void *buf, size_t length);
+int memstick_next_req(struct memstick_host *host,
+                     struct memstick_request **mrq);
+void memstick_new_req(struct memstick_host *host);
+
+int memstick_set_rw_addr(struct memstick_dev *card);
+
+static inline void *memstick_priv(struct memstick_host *host)
+{
+       return (void *)host->private;
+}
+
+static inline void *memstick_get_drvdata(struct memstick_dev *card)
+{
+       return dev_get_drvdata(&card->dev);
+}
+
+static inline void memstick_set_drvdata(struct memstick_dev *card, void *data)
+{
+       dev_set_drvdata(&card->dev, data);
+}
+
+#endif
index 7215d3b1f4af05d8731e6dc4989763be0aea6eb0..87195b62de5261cf0bc6dd31e171386de769ccdf 100644 (file)
@@ -301,14 +301,14 @@ struct pci_ops {
        int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
 };
 
-struct pci_raw_ops {
-       int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
-                   int reg, int len, u32 *val);
-       int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
-                    int reg, int len, u32 val);
-};
-
-extern struct pci_raw_ops *raw_pci_ops;
+/*
+ * ACPI needs to be able to access PCI config space before we've done a
+ * PCI bus scan and created pci_bus structures.
+ */
+extern int raw_pci_read(unsigned int domain, unsigned int bus,
+                       unsigned int devfn, int reg, int len, u32 *val);
+extern int raw_pci_write(unsigned int domain, unsigned int bus,
+                       unsigned int devfn, int reg, int len, u32 val);
 
 struct pci_bus_region {
        resource_size_t start;
index 5eb38cc0e5a41626a567267aca3809cb5ec114b4..8ba1c320f9759e5057ab656c83e2bf43a5236039 100644 (file)
  *
  * Various protocol defined structures.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 7bf2d149d209615be247da2dadc4385f37636be5..6ec39ab27b4b48aaf31b02a19bf5a164217abcce 100644 (file)
@@ -42,11 +42,13 @@ static inline pgoff_t swp_offset(swp_entry_t entry)
        return entry.val & SWP_OFFSET_MASK(entry);
 }
 
+#ifdef CONFIG_MMU
 /* check whether a pte points to a swap entry */
 static inline int is_swap_pte(pte_t pte)
 {
        return !pte_none(pte) && !pte_present(pte) && !pte_file(pte);
 }
+#endif
 
 /*
  * Convert the arch-dependent pte representation of a swp_entry_t into an
index bba7712cadc749cc63513c583cce475dce899888..818ca1cf0b6d81d4f74faebcbdb6eef9123d90a7 100644 (file)
@@ -79,7 +79,9 @@ struct thermal_zone_device {
 };
 
 struct thermal_zone_device *thermal_zone_device_register(char *, int, void *,
-                                       struct thermal_zone_device_ops *);
+                                                        struct
+                                                        thermal_zone_device_ops
+                                                        *);
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
@@ -87,8 +89,23 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int,
                                       struct thermal_cooling_device *);
 
+#ifdef CONFIG_THERMAL
 struct thermal_cooling_device *thermal_cooling_device_register(char *, void *,
-                                       struct thermal_cooling_device_ops *);
+                                                              struct
+                                                              thermal_cooling_device_ops
+                                                              *);
 void thermal_cooling_device_unregister(struct thermal_cooling_device *);
+#else
+static inline struct thermal_cooling_device
+*thermal_cooling_device_register(char *c, void *v,
+                                struct thermal_cooling_device_ops *t)
+{
+       return NULL;
+}
+static inline
+    void thermal_cooling_device_unregister(struct thermal_cooling_device *t)
+{
+};
+#endif
 
-#endif                         /* __THERMAL_H__ */
+#endif /* __THERMAL_H__ */
index 2096b76d0cee68efe8cd91571e69da3c36bffd2c..da76ed85f5958fb941cbb837a7f824b0981fd575 100644 (file)
@@ -72,6 +72,7 @@ enum {
 #define TIFM_FIFO_READY           0x00000001
 #define TIFM_FIFO_INT_SETALL      0x0000ffff
 #define TIFM_FIFO_INTMASK         0x00000005
+#define TIFM_FIFO_SIZE            0x00000200
 
 #define TIFM_DMA_RESET            0x00000002
 #define TIFM_DMA_TX               0x00008000
@@ -124,6 +125,8 @@ struct tifm_adapter {
 
        void                (*eject)(struct tifm_adapter *fm,
                                     struct tifm_dev *sock);
+       int                 (*has_ms_pif)(struct tifm_adapter *fm,
+                                         struct tifm_dev *sock);
 
        struct tifm_dev     *sockets[0];
 };
@@ -141,6 +144,7 @@ struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id,
 int tifm_register_driver(struct tifm_driver *drv);
 void tifm_unregister_driver(struct tifm_driver *drv);
 void tifm_eject(struct tifm_dev *sock);
+int tifm_has_ms_pif(struct tifm_dev *sock);
 int tifm_map_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
                int direction);
 void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents,
index 8ea3e71ba7fa8ff17d8de5587f482450c349ef36..c3f374786a4358e59eb6ce72e3b436e6a2556449 100644 (file)
@@ -232,7 +232,14 @@ static inline int ntp_synced(void)
 #else
 #define NTP_INTERVAL_FREQ  (HZ)
 #endif
-#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
+
+#define CLOCK_TICK_OVERFLOW    (LATCH * HZ - CLOCK_TICK_RATE)
+#define CLOCK_TICK_ADJUST      (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \
+                                       (s64)CLOCK_TICK_RATE)
+
+/* Because using NSEC_PER_SEC would be too easy */
+#define NTP_INTERVAL_LENGTH ((((s64)TICK_USEC * NSEC_PER_USEC * USER_HZ) + \
+                             CLOCK_TICK_ADJUST) / NTP_INTERVAL_FREQ)
 
 /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
 extern u64 current_tick_length(void);
index 5db261a1e85e671bcbf907325e68ab5b4e3aeddf..49bc9577c61efbfcb8caf37e686def5f3de17c81 100644 (file)
@@ -1,15 +1,15 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright 2007 Hewlett-Packard Development Company, L.P.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index c1f79767357196aecd1aff0235a0445605fe1edd..10ae2da6f93bec65b2659b368b1b3a9081b5f9ca 100644 (file)
@@ -1,18 +1,18 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel Implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (C) 1999-2001 Cisco, Motorola
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These are the definitions needed for the command object.
  *
- * The SCTP reference implementation  is free software;
+ * This SCTP implementation  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, or (at your option)
  * any later version.
  *
- * the SCTP reference implementation  is distributed in the hope that it
+ * This SCTP implementation  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.
index fefcba67bd1edc7b8c863472755afe95c925c8d2..c32ddf0279c83513430c841f8a5f31e4c969f7d3 100644 (file)
@@ -1,18 +1,18 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 4977b0a81535519508fa0f0f90b0bd44c6dd19d3..57df27f195888f09e0d73cfd12a68c4dee1304a3 100644 (file)
@@ -1,20 +1,20 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2003 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * The base lksctp header.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index bf2f5ed69c1507466dfb1e44926e2e94f4e9433c..ef9e7ed2c82e09aa49e3ca6c98c606ed0621e4ae 100644 (file)
@@ -1,20 +1,20 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These are definitions needed by the state machine.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 4d591bfce45246334a6062abe9d6816d47d9cf65..9c827a749b6f626b9a336e5f45b237e707b88de4 100644 (file)
@@ -1,18 +1,18 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 70a824df6f6007a65134bff615088056d81ba5cb..099211bf998dc1b9e740fa28508122133d94b85d 100644 (file)
@@ -1,21 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These are the definitions needed for the tsnmap type.  The tsnmap is used
  * to track out of order TSNs received.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 922a151eb93c1ea7e89b712f2db0ea031d7097ec..9bcfc12275e8cc6db10d312986f694748f5c6ba5 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * sctp_ulpevent type is used to carry information from the state machine
  * upwards to the ULP.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index cd33270e86dd61eb3b856cb6b0a61434d911f7bb..2e5ee0d8458d929b284bd1b510dcfbeac1ff4aa3 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * and the core SCTP state machine.  This is the component which handles
  * reassembly and ordering.
  *
- * The SCTP reference implementation  is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * the SCTP reference implementation  is distributed in the hope that it
+ * This SCTP implementation  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.
index 954090b1e354143bd851a384f9b858a844096634..9462d6ae2f372170594a1e7923fadb9a173f0094 100644 (file)
@@ -1,21 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2002 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * This header represents the structures and constants needed to support
  * the SCTP Extension to the Sockets API.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 455170e1c1e355d9e73348ac0467e24b10d67ed5..824d48cb67bfd49366ed7fdfa70346f7ac67e005 100644 (file)
@@ -587,7 +587,7 @@ config COMPAT_BRK
          disabled, and can be overriden runtime by setting
          /proc/sys/kernel/randomize_va_space to 2.
 
-         On non-ancient distros (post-2000 ones) Y is usually a safe choice.
+         On non-ancient distros (post-2000 ones) N is usually a safe choice.
 
 config BASE_FULL
        default y
index 633392f5cdeeb92e142db1f312e1e32d2a3a9176..c5f157ce293e7625c428b8e853732d1977add6bc 100644 (file)
@@ -27,7 +27,9 @@ $(obj)/version.o: include/linux/compile.h
 # mkcompile_h will make sure to only update the
 # actual file if its content has changed.
 
+ quiet_chk_compile.h = echo '  CHK     $@'
+silent_chk_compile.h = :
 include/linux/compile.h: FORCE
-       @echo '  CHK     $@'
+       @$($(quiet)chk_compile.h)
        $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \
        "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)"
index c59859b85db0d999f3e6cf1e8af1aead1fef39d6..8b1982082ad8ada65bbd1ff4a1c565c2a77feba6 100644 (file)
@@ -558,7 +558,6 @@ asmlinkage void __init start_kernel(void)
        preempt_disable();
        build_all_zonelists();
        page_alloc_init();
-       enable_debug_pagealloc();
        printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line);
        parse_early_param();
        parse_args("Booting kernel", static_command_line, __start___param,
@@ -614,6 +613,7 @@ asmlinkage void __init start_kernel(void)
        vfs_caches_init_early();
        cpuset_init_early();
        mem_init();
+       enable_debug_pagealloc();
        cpu_hotplug_init();
        kmem_cache_init();
        setup_per_cpu_pageset();
index f2ab70073bd40c5a437967a55da52d99d6a1794e..ab4f1090f437e0aaa0395e110169cdc6d37b50d9 100644 (file)
@@ -3,3 +3,4 @@
 #
 config_data.h
 config_data.gz
+timeconst.h
index 42a1ed4b61b172afe1693234a4c68e5cfb695610..5f0e201bcfd3b883418b16f04c32da51cf2353be 100644 (file)
@@ -40,10 +40,35 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
                        __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
 }
 
+static long compat_nanosleep_restart(struct restart_block *restart)
+{
+       struct compat_timespec __user *rmtp;
+       struct timespec rmt;
+       mm_segment_t oldfs;
+       long ret;
+
+       rmtp = (struct compat_timespec __user *)(restart->arg1);
+       restart->arg1 = (unsigned long)&rmt;
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = hrtimer_nanosleep_restart(restart);
+       set_fs(oldfs);
+
+       if (ret) {
+               restart->arg1 = (unsigned long)rmtp;
+
+               if (rmtp && put_compat_timespec(&rmt, rmtp))
+                       return -EFAULT;
+       }
+
+       return ret;
+}
+
 asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
                                     struct compat_timespec __user *rmtp)
 {
        struct timespec tu, rmt;
+       mm_segment_t oldfs;
        long ret;
 
        if (get_compat_timespec(&tu, rqtp))
@@ -52,11 +77,21 @@ asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
        if (!timespec_valid(&tu))
                return -EINVAL;
 
-       ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
-                               CLOCK_MONOTONIC);
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = hrtimer_nanosleep(&tu,
+                               rmtp ? (struct timespec __user *)&rmt : NULL,
+                               HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+       set_fs(oldfs);
+
+       if (ret) {
+               struct restart_block *restart
+                       = &current_thread_info()->restart_block;
+
+               restart->fn = compat_nanosleep_restart;
+               restart->arg1 = (unsigned long)rmtp;
 
-       if (ret && rmtp) {
-               if (put_compat_timespec(&rmt, rmtp))
+               if (rmtp && put_compat_timespec(&rmt, rmtp))
                        return -EFAULT;
        }
 
index 668f3967eb394e37fcecc65e47e6dce75173b5dc..3f4a57c7895d53b88a7eb23e2bb9be038baca988 100644 (file)
@@ -1319,13 +1319,26 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
        return t->task == NULL;
 }
 
+static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp)
+{
+       struct timespec rmt;
+       ktime_t rem;
+
+       rem = ktime_sub(timer->expires, timer->base->get_time());
+       if (rem.tv64 <= 0)
+               return 0;
+       rmt = ktime_to_timespec(rem);
+
+       if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
+               return -EFAULT;
+
+       return 1;
+}
+
 long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
 {
        struct hrtimer_sleeper t;
-       struct timespec *rmtp;
-       ktime_t time;
-
-       restart->fn = do_no_restart_syscall;
+       struct timespec __user  *rmtp;
 
        hrtimer_init(&t.timer, restart->arg0, HRTIMER_MODE_ABS);
        t.timer.expires.tv64 = ((u64)restart->arg3 << 32) | (u64) restart->arg2;
@@ -1333,26 +1346,22 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
        if (do_nanosleep(&t, HRTIMER_MODE_ABS))
                return 0;
 
-       rmtp = (struct timespec *)restart->arg1;
+       rmtp = (struct timespec __user *)restart->arg1;
        if (rmtp) {
-               time = ktime_sub(t.timer.expires, t.timer.base->get_time());
-               if (time.tv64 <= 0)
-                       return 0;
-               *rmtp = ktime_to_timespec(time);
+               int ret = update_rmtp(&t.timer, rmtp);
+               if (ret <= 0)
+                       return ret;
        }
 
-       restart->fn = hrtimer_nanosleep_restart;
-
        /* The other values in restart are already filled in */
        return -ERESTART_RESTARTBLOCK;
 }
 
-long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
+long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
                       const enum hrtimer_mode mode, const clockid_t clockid)
 {
        struct restart_block *restart;
        struct hrtimer_sleeper t;
-       ktime_t rem;
 
        hrtimer_init(&t.timer, clockid, mode);
        t.timer.expires = timespec_to_ktime(*rqtp);
@@ -1364,10 +1373,9 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
                return -ERESTARTNOHAND;
 
        if (rmtp) {
-               rem = ktime_sub(t.timer.expires, t.timer.base->get_time());
-               if (rem.tv64 <= 0)
-                       return 0;
-               *rmtp = ktime_to_timespec(rem);
+               int ret = update_rmtp(&t.timer, rmtp);
+               if (ret <= 0)
+                       return ret;
        }
 
        restart = &current_thread_info()->restart_block;
@@ -1383,8 +1391,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
 asmlinkage long
 sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
 {
-       struct timespec tu, rmt;
-       int ret;
+       struct timespec tu;
 
        if (copy_from_user(&tu, rqtp, sizeof(tu)))
                return -EFAULT;
@@ -1392,15 +1399,7 @@ sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
        if (!timespec_valid(&tu))
                return -EINVAL;
 
-       ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
-                               CLOCK_MONOTONIC);
-
-       if (ret && rmtp) {
-               if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
-                       return -EFAULT;
-       }
-
-       return ret;
+       return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 }
 
 /*
index ce268966007d6f71904cd8229939f6fb9a2324c5..022c9c3cee6f2f567568a4e3577563b1aa1f1ee4 100644 (file)
@@ -982,20 +982,9 @@ sys_clock_getres(const clockid_t which_clock, struct timespec __user *tp)
 static int common_nsleep(const clockid_t which_clock, int flags,
                         struct timespec *tsave, struct timespec __user *rmtp)
 {
-       struct timespec rmt;
-       int ret;
-
-       ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL,
-                               flags & TIMER_ABSTIME ?
-                               HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
-                               which_clock);
-
-       if (ret && rmtp) {
-               if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
-                       return -EFAULT;
-       }
-
-       return ret;
+       return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
+                                HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+                                which_clock);
 }
 
 asmlinkage long
index e64efaf957e8485b4d233412a69fdf45a1225691..c88b5910e7abb9c630106fcbf21b6b7a0d363faf 100644 (file)
@@ -43,10 +43,6 @@ long time_freq;                              /* frequency offset (scaled ppm)*/
 static long time_reftime;              /* time at last adjustment (s)  */
 long time_adjust;
 
-#define CLOCK_TICK_OVERFLOW    (LATCH * HZ - CLOCK_TICK_RATE)
-#define CLOCK_TICK_ADJUST      (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \
-                                       (s64)CLOCK_TICK_RATE)
-
 static void ntp_update_frequency(void)
 {
        u64 second_length = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ)
index ce0bb2600c25e9621b7b895b9457439e3f7ae5e1..a370fe828a7939a88f9f8c2a687d72ed780bd068 100644 (file)
@@ -465,20 +465,6 @@ config FRAME_POINTER
          some architectures or if you use external debuggers.
          If you don't debug the kernel, you can say N.
 
-config FORCED_INLINING
-       bool "Force gcc to inline functions marked 'inline'"
-       depends on DEBUG_KERNEL
-       default y
-       help
-         This option determines if the kernel forces gcc to inline the functions
-         developers have marked 'inline'. Doing so takes away freedom from gcc to
-         do what it thinks is best, which is desirable for the gcc 3.x series of
-         compilers. The gcc 4.x series have a rewritten inlining algorithm and
-         disabling this option will generate a smaller kernel there. Hopefully
-         this algorithm is so good that allowing gcc4 to make the decision can
-         become the default in the future, until then this option is there to
-         test gcc for this.
-
 config BOOT_PRINTK_DELAY
        bool "Delay each boot printk message by N milliseconds"
        depends on DEBUG_KERNEL && PRINTK && GENERIC_CALIBRATE_DELAY
index 419993f58c6b6d61c7f881b90508ade03312085e..fd987b17bda754b424cb0e9cd9d055056bd1c6f3 100644 (file)
@@ -26,6 +26,9 @@
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/div64.h>
 
+/* Works only for digits and letters, but small and fast */
+#define TOLOWER(x) ((x) | 0x20)
+
 /**
  * simple_strtoul - convert a string to an unsigned long
  * @cp: The start of the string
@@ -41,17 +44,17 @@ unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
                if (*cp == '0') {
                        base = 8;
                        cp++;
-                       if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+                       if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
                                cp++;
                                base = 16;
                        }
                }
        } else if (base == 16) {
-               if (cp[0] == '0' && toupper(cp[1]) == 'X')
+               if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
                        cp += 2;
        }
        while (isxdigit(*cp) &&
-              (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
+              (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
                result = result*base + value;
                cp++;
        }
@@ -92,17 +95,17 @@ unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base)
                if (*cp == '0') {
                        base = 8;
                        cp++;
-                       if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
+                       if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
                                cp++;
                                base = 16;
                        }
                }
        } else if (base == 16) {
-               if (cp[0] == '0' && toupper(cp[1]) == 'X')
+               if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
                        cp += 2;
        }
-       while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
-           ? toupper(*cp) : *cp)-'A'+10) < base) {
+       while (isxdigit(*cp)
+        && (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
                result = result*base + value;
                cp++;
        }
@@ -360,24 +363,25 @@ static noinline char* put_dec(char *buf, unsigned long long num)
 #define PLUS   4               /* show plus */
 #define SPACE  8               /* space if plus */
 #define LEFT   16              /* left justified */
-#define SPECIAL        32              /* 0x */
-#define LARGE  64              /* use 'ABCDEF' instead of 'abcdef' */
+#define SMALL  32              /* Must be 32 == 0x20 */
+#define SPECIAL        64              /* 0x */
 
 static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type)
 {
-       char sign,tmp[66];
-       const char *digits;
-       /* we are called with base 8, 10 or 16, only, thus don't need "g..."  */
-       static const char small_digits[] = "0123456789abcdefx"; /* "ghijklmnopqrstuvwxyz"; */
-       static const char large_digits[] = "0123456789ABCDEFX"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+       /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
+       static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
+
+       char tmp[66];
+       char sign;
+       char locase;
        int need_pfx = ((type & SPECIAL) && base != 10);
        int i;
 
-       digits = (type & LARGE) ? large_digits : small_digits;
+       /* locase = 0 or 0x20. ORing digits or letters with 'locase'
+        * produces same digits or (maybe lowercased) letters */
+       locase = (type & SMALL);
        if (type & LEFT)
                type &= ~ZEROPAD;
-       if (base < 2 || base > 36)
-               return NULL;
        sign = 0;
        if (type & SIGN) {
                if ((signed long long) num < 0) {
@@ -404,7 +408,7 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
                tmp[i++] = '0';
        /* Generic code, for any base:
        else do {
-               tmp[i++] = digits[do_div(num,base)];
+               tmp[i++] = (digits[do_div(num,base)] | locase);
        } while (num != 0);
        */
        else if (base != 10) { /* 8 or 16 */
@@ -412,7 +416,7 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
                int shift = 3;
                if (base == 16) shift = 4;
                do {
-                       tmp[i++] = digits[((unsigned char)num) & mask];
+                       tmp[i++] = (digits[((unsigned char)num) & mask] | locase);
                        num >>= shift;
                } while (num);
        } else { /* base 10 */
@@ -444,7 +448,7 @@ static char *number(char *buf, char *end, unsigned long long num, int base, int
                ++buf;
                if (base == 16) {
                        if (buf < end)
-                               *buf = digits[16]; /* for arbitrary base: digits[33]; */
+                               *buf = ('X' | locase);
                        ++buf;
                }
        }
@@ -644,6 +648,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                                continue;
 
                        case 'p':
+                               flags |= SMALL;
                                if (field_width == -1) {
                                        field_width = 2*sizeof(void *);
                                        flags |= ZEROPAD;
@@ -680,9 +685,9 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
                                base = 8;
                                break;
 
-                       case 'X':
-                               flags |= LARGE;
                        case 'x':
+                               flags |= SMALL;
+                       case 'X':
                                base = 16;
                                break;
 
index 5c2c702af6172e34bced06b2d5693ce2d461b000..6bded84c20c88b7b4687a2954f31509ef1527c0d 100644 (file)
@@ -399,7 +399,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
        int ret;
 
        task_lock(task);
-       ret = task->mm && mm_cgroup(task->mm) == mem;
+       ret = task->mm && vm_match_cgroup(task->mm, mem);
        task_unlock(task);
        return ret;
 }
index a0e92a263d12eb734e8a8171e9d575e35dc0d768..8fd527c4e2bff8e45c929c42f01c60834c573ef9 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -321,7 +321,7 @@ static int page_referenced_anon(struct page *page,
                 * counting on behalf of references from different
                 * cgroups
                 */
-               if (mem_cont && (mm_cgroup(vma->vm_mm) != mem_cont))
+               if (mem_cont && !vm_match_cgroup(vma->vm_mm, mem_cont))
                        continue;
                referenced += page_referenced_one(page, vma, &mapcount);
                if (!mapcount)
@@ -382,7 +382,7 @@ static int page_referenced_file(struct page *page,
                 * counting on behalf of references from different
                 * cgroups
                 */
-               if (mem_cont && (mm_cgroup(vma->vm_mm) != mem_cont))
+               if (mem_cont && !vm_match_cgroup(vma->vm_mm, mem_cont))
                        continue;
                if ((vma->vm_flags & (VM_LOCKED|VM_MAYSHARE))
                                  == (VM_LOCKED|VM_MAYSHARE)) {
index 994648be80ab7e3e4a60abdb3e1a28e4aae290ca..732cd07e6071bdc0aa9b514286bdd80ec934183d 100644 (file)
@@ -922,13 +922,11 @@ int igmp_rcv(struct sk_buff *skb)
        struct in_device *in_dev = in_dev_get(skb->dev);
        int len = skb->len;
 
-       if (in_dev==NULL) {
-               kfree_skb(skb);
-               return 0;
-       }
+       if (in_dev == NULL)
+               goto drop;
 
        if (!pskb_may_pull(skb, sizeof(struct igmphdr)))
-               goto drop;
+               goto drop_ref;
 
        switch (skb->ip_summed) {
        case CHECKSUM_COMPLETE:
@@ -938,7 +936,7 @@ int igmp_rcv(struct sk_buff *skb)
        case CHECKSUM_NONE:
                skb->csum = 0;
                if (__skb_checksum_complete(skb))
-                       goto drop;
+                       goto drop_ref;
        }
 
        ih = igmp_hdr(skb);
@@ -972,8 +970,9 @@ int igmp_rcv(struct sk_buff *skb)
                break;
        }
 
-drop:
+drop_ref:
        in_dev_put(in_dev);
+drop:
        kfree_skb(skb);
        return 0;
 }
index 513f72e3db0da00dc8f54bd9df7878054e92be33..6e7b56ef44499c0bf5bf48af941f8b77181131df 100644 (file)
@@ -1620,7 +1620,7 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle
 {
        struct fib6_config cfg = {
                .fc_table       = RT6_TABLE_INFO,
-               .fc_metric      = 1024,
+               .fc_metric      = IP6_RT_PRIO_USER,
                .fc_ifindex     = ifindex,
                .fc_dst_len     = prefixlen,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
@@ -1670,7 +1670,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
 {
        struct fib6_config cfg = {
                .fc_table       = RT6_TABLE_DFLT,
-               .fc_metric      = 1024,
+               .fc_metric      = IP6_RT_PRIO_USER,
                .fc_ifindex     = dev->ifindex,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
                                  RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
index 45c3c27d279ad9b66e92b0771b9342a4840ca4c1..b3ac85e808acf288dc91a1c12d7a9c92323cdf1d 100644 (file)
@@ -3734,21 +3734,15 @@ static struct net_proto_family pfkey_family_ops = {
 };
 
 #ifdef CONFIG_PROC_FS
-static int pfkey_read_proc(char *buffer, char **start, off_t offset,
-                          int length, int *eof, void *data)
+static int pfkey_seq_show(struct seq_file *f, void *v)
 {
-       off_t pos = 0;
-       off_t begin = 0;
-       int len = 0;
        struct sock *s;
-       struct hlist_node *node;
-
-       len += sprintf(buffer,"sk       RefCnt Rmem   Wmem   User   Inode\n");
-
-       read_lock(&pfkey_table_lock);
 
-       sk_for_each(s, node, &pfkey_table) {
-               len += sprintf(buffer+len,"%p %-6d %-6u %-6u %-6u %-6lu",
+       s = (struct sock *)v;
+       if (v == SEQ_START_TOKEN)
+               seq_printf(f ,"sk       RefCnt Rmem   Wmem   User   Inode\n");
+       else
+               seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n",
                               s,
                               atomic_read(&s->sk_refcnt),
                               atomic_read(&s->sk_rmem_alloc),
@@ -3756,31 +3750,82 @@ static int pfkey_read_proc(char *buffer, char **start, off_t offset,
                               sock_i_uid(s),
                               sock_i_ino(s)
                               );
+       return 0;
+}
 
-               buffer[len++] = '\n';
+static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
+{
+       struct sock *s;
+       struct hlist_node *node;
+       loff_t pos = *ppos;
 
-               pos = begin + len;
-               if (pos < offset) {
-                       len = 0;
-                       begin = pos;
-               }
-               if(pos > offset + length)
-                       goto done;
-       }
-       *eof = 1;
+       read_lock(&pfkey_table_lock);
+       if (pos == 0)
+               return SEQ_START_TOKEN;
 
-done:
+       sk_for_each(s, node, &pfkey_table)
+               if (pos-- == 1)
+                       return s;
+
+       return NULL;
+}
+
+static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
+{
+       ++*ppos;
+       return (v == SEQ_START_TOKEN) ?
+               sk_head(&pfkey_table) :
+                       sk_next((struct sock *)v);
+}
+
+static void pfkey_seq_stop(struct seq_file *f, void *v)
+{
        read_unlock(&pfkey_table_lock);
+}
+
+static struct seq_operations pfkey_seq_ops = {
+       .start  = pfkey_seq_start,
+       .next   = pfkey_seq_next,
+       .stop   = pfkey_seq_stop,
+       .show   = pfkey_seq_show,
+};
+
+static int pfkey_seq_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &pfkey_seq_ops);
+}
 
-       *start = buffer + (offset - begin);
-       len -= (offset - begin);
+static struct file_operations pfkey_proc_ops = {
+       .open    = pfkey_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release,
+};
 
-       if (len > length)
-               len = length;
-       if (len < 0)
-               len = 0;
+static int pfkey_init_proc(void)
+{
+       struct proc_dir_entry *e;
 
-       return len;
+       e = create_proc_entry("pfkey", 0, init_net.proc_net);
+       if (e == NULL)
+               return -ENOMEM;
+
+       e->proc_fops = &pfkey_proc_ops;
+       return 0;
+}
+
+static void pfkey_exit_proc(void)
+{
+       remove_proc_entry("net/pfkey", NULL);
+}
+#else
+static inline int pfkey_init_proc(void)
+{
+       return 0;
+}
+
+static inline void pfkey_exit_proc(void)
+{
 }
 #endif
 
@@ -3798,7 +3843,7 @@ static struct xfrm_mgr pfkeyv2_mgr =
 static void __exit ipsec_pfkey_exit(void)
 {
        xfrm_unregister_km(&pfkeyv2_mgr);
-       remove_proc_entry("pfkey", init_net.proc_net);
+       pfkey_exit_proc();
        sock_unregister(PF_KEY);
        proto_unregister(&key_proto);
 }
@@ -3813,21 +3858,17 @@ static int __init ipsec_pfkey_init(void)
        err = sock_register(&pfkey_family_ops);
        if (err != 0)
                goto out_unregister_key_proto;
-#ifdef CONFIG_PROC_FS
-       err = -ENOMEM;
-       if (create_proc_read_entry("pfkey", 0, init_net.proc_net, pfkey_read_proc, NULL) == NULL)
+       err = pfkey_init_proc();
+       if (err != 0)
                goto out_sock_unregister;
-#endif
        err = xfrm_register_km(&pfkeyv2_mgr);
        if (err != 0)
                goto out_remove_proc_entry;
 out:
        return err;
 out_remove_proc_entry:
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("net/pfkey", NULL);
+       pfkey_exit_proc();
 out_sock_unregister:
-#endif
        sock_unregister(PF_KEY);
 out_unregister_key_proto:
        proto_unregister(&key_proto);
index d417ec8e3ca3b1893150f98ced8b46bb3558a878..3da4129b89d1e179bf679ba108c943f97f602746 100644 (file)
@@ -687,8 +687,8 @@ static inline struct meta_type_ops * meta_type_ops(struct meta_value *v)
  * Core
  **************************************************************************/
 
-static inline int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,
-                          struct meta_value *v, struct meta_obj *dst)
+static int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,
+                   struct meta_value *v, struct meta_obj *dst)
 {
        int err = 0;
 
@@ -733,7 +733,7 @@ static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m,
        return 0;
 }
 
-static inline void meta_delete(struct meta_match *meta)
+static void meta_delete(struct meta_match *meta)
 {
        if (meta) {
                struct meta_type_ops *ops = meta_type_ops(&meta->lvalue);
index 74ff918455a2acc2885f5fce5e9da30db3d527fa..5e6f82e0e6f3ca7c092e3a1628d69b416604d0f5 100644 (file)
@@ -312,10 +312,9 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
        struct tcf_ematch_tree_hdr *tree_hdr;
        struct tcf_ematch *em;
 
-       if (!nla) {
-               memset(tree, 0, sizeof(*tree));
+       memset(tree, 0, sizeof(*tree));
+       if (!nla)
                return 0;
-       }
 
        err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, em_policy);
        if (err < 0)
@@ -410,7 +409,7 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree)
                if (em->ops) {
                        if (em->ops->destroy)
                                em->ops->destroy(tp, em);
-                       else if (!tcf_em_is_simple(em) && em->data)
+                       else if (!tcf_em_is_simple(em))
                                kfree((void *) em->data);
                        module_put(em->ops->owner);
                }
@@ -418,6 +417,7 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree)
 
        tree->hdr.nmatches = 0;
        kfree(tree->matches);
+       tree->matches = NULL;
 }
 EXPORT_SYMBOL(tcf_em_tree_destroy);
 
index e1a579efc215a930d3ece2d3f4938446550f57f0..795c761ad99fb4cc07d61f79a327061f895c69c8 100644 (file)
@@ -609,14 +609,14 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 /* TODO: requeuing packet charges it to policers again !! */
 static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
 {
+       int ret;
        struct htb_sched *q = qdisc_priv(sch);
-       int ret = NET_XMIT_SUCCESS;
        struct htb_class *cl = htb_classify(skb, sch, &ret);
        struct sk_buff *tskb;
 
-       if (cl == HTB_DIRECT || !cl) {
+       if (cl == HTB_DIRECT) {
                /* enqueue to helper queue */
-               if (q->direct_queue.qlen < q->direct_qlen && cl) {
+               if (q->direct_queue.qlen < q->direct_qlen) {
                        __skb_queue_head(&q->direct_queue, skb);
                } else {
                        __skb_queue_head(&q->direct_queue, skb);
@@ -625,6 +625,13 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
                        sch->qstats.drops++;
                        return NET_XMIT_CN;
                }
+#ifdef CONFIG_NET_CLS_ACT
+       } else if (!cl) {
+               if (ret == NET_XMIT_BYPASS)
+                       sch->qstats.drops++;
+               kfree_skb(skb);
+               return ret;
+#endif
        } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) !=
                   NET_XMIT_SUCCESS) {
                sch->qstats.drops++;
index a016e78061f4399cd4ce19f9276905de286baf89..d29f792e0529d78cebbd3a3ec55c8e8a95e63f4b 100644 (file)
@@ -1,21 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * This module provides the abstraction for an SCTP association.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
@@ -1525,7 +1525,7 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
                                        const struct sctp_association *asoc,
                                        __be32 serial)
 {
-       struct sctp_chunk *ack = NULL;
+       struct sctp_chunk *ack;
 
        /* Walk through the list of cached ASCONF-ACKs and find the
         * ack chunk whose serial number matches that of the request.
@@ -1533,9 +1533,9 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
        list_for_each_entry(ack, &asoc->asconf_ack_list, transmitted_list) {
                if (ack->subh.addip_hdr->serial == serial) {
                        sctp_chunk_hold(ack);
-                       break;
+                       return ack;
                }
        }
 
-       return ack;
+       return NULL;
 }
index ae367c82e51239101c915996643bd46638e3de73..8bb79f281774b690aec0f42973889de07e7d7fcd 100644 (file)
@@ -1,15 +1,15 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright 2007 Hewlett-Packard Development Company, L.P.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 13fbfb449a5544347d824a5d85408adc3d78b96d..a27511ebc4cb6ae80749a41c6b85239021749fee 100644 (file)
@@ -1,20 +1,20 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2003
  * Copyright (c) Cisco 1999,2000
  * Copyright (c) Motorola 1999,2000,2001
  * Copyright (c) La Monte H.P. Yarroll 2001
  *
- * This file is part of the SCTP kernel reference implementation.
+ * This file is part of the SCTP kernel implementation.
  *
  * A collection class to handle the storage of transport addresses.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 619d0f2dee5124ef5c2c31cb3f24aabb78b4e531..4d3128f5ccc3f304676c8022410c40b32c3cf6d9 100644 (file)
@@ -1,17 +1,17 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2003, 2004
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * This file contains the code relating the chunk abstraction.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 3ff804757f4a597dca9dcccf8e88b096d50bbb90..bb977330002ac56307cda341fff68b2bc828baeb 100644 (file)
@@ -1,18 +1,18 @@
-/* SCTP kernel reference Implementation Copyright (C) 1999-2001
+/* SCTP kernel implementation Copyright (C) 1999-2001
  * Cisco, Motorola, and IBM
  * Copyright 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions manipulate sctp command sequences.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 80f70aa533867317e5dcbdbadc7333d29c519901..67715f4eb8495e49fa3eb21fa33a96bf80c51514 100644 (file)
@@ -1,25 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
- *
- * This file is part of the implementation of the add-IP extension,
- * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
- * for the SCTP kernel reference Implementation.
+ * This file is part of the SCTP kernel implementation
  *
  * This file converts numerical ID value to alphabetical names for SCTP
  * terms such as chunk type, parameter time, event type, etc.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index de6f505d6ff8250291972d4e53c391dcf1548e57..e39a0cdef1841748d2957f581e7a90d76cd49359 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2002 International Business Machines, Corp.
@@ -6,21 +6,17 @@
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * This abstraction represents an SCTP endpoint.
  *
- * This file is part of the implementation of the add-IP extension,
- * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
- * for the SCTP kernel reference Implementation.
- *
- * The SCTP reference implementation is free software;
+ * The SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * The SCTP implementation 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.
index d695f710fc77d0e986f599674873c6e6975603bd..57fe2f81eca86e8298bfd3a373ded2b7e7c756e2 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2003 International Business Machines, Corp.
@@ -6,17 +6,17 @@
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions handle all input from the IP layer into SCTP.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index cf4b7eb023b3ba0819ce6d960128099c662360af..bbf5dd2a97c42d0ac49d7ad0f1e0fd6b0955f63a 100644 (file)
@@ -1,9 +1,9 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2002 International Business Machines, Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions are the methods for accessing the SCTP inqueue.
  *
  * (which might be bundles or fragments of chunks) and out of which you
  * pop SCTP whole chunks.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 74f106a7a7e9d2fc0be78c2c6c46cd50400e4808..4d7ec961ae1da98c919fdb1927be5b297f94627c 100644 (file)
@@ -1,20 +1,20 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2002, 2004
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  * Copyright (c) 2002-2003 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * SCTP over IPv6.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 2cf6ad6ff8ce01a51645681792e453e13c063b2f..14e294e3762665759c514846334551d82a1e9ddf 100644 (file)
@@ -1,19 +1,19 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * Support for memory object debugging.  This allows one to monitor the
  * object allocations/deallocations for types instrumented for this
  * via the proc fs.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
@@ -80,61 +80,64 @@ static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
 /* Callback from procfs to read out objcount information.
  * Walk through the entries in the sctp_dbg_objcnt array, dumping
  * the raw object counts for each monitored type.
- *
- * This code was modified from similar code in route.c
  */
-static int sctp_dbg_objcnt_read(char *buffer, char **start, off_t offset,
-                               int length, int *eof, void *data)
+static int sctp_objcnt_seq_show(struct seq_file *seq, void *v)
 {
-       int len = 0;
-       off_t pos = 0;
-       int entries;
        int i;
        char temp[128];
 
-       /* How many entries? */
-       entries = ARRAY_SIZE(sctp_dbg_objcnt);
-
-       /* Walk the entries and print out the debug information
-        * for proc fs.
-        */
-       for (i = 0; i < entries; i++) {
-               pos += 128;
-
-               /* Skip ahead. */
-               if (pos <= offset) {
-                       len = 0;
-                       continue;
-               }
-               /* Print out each entry. */
-               sprintf(temp, "%s: %d",
-                       sctp_dbg_objcnt[i].label,
-                       atomic_read(sctp_dbg_objcnt[i].counter));
-
-               sprintf(buffer + len, "%-127s\n", temp);
-               len += 128;
-               if (pos >= offset+length)
-                       goto done;
-       }
-
-done:
-       *start = buffer + len - (pos - offset);
-       len = pos - offset;
-       if (len > length)
-               len = length;
-
-       return len;
+       i = (int)*(loff_t *)v;
+       sprintf(temp, "%s: %d", sctp_dbg_objcnt[i].label,
+                               atomic_read(sctp_dbg_objcnt[i].counter));
+       seq_printf(seq, "%-127s\n", temp);
+       return 0;
+}
+
+static void *sctp_objcnt_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos;
+}
+
+static void sctp_objcnt_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static void * sctp_objcnt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       ++*pos;
+       return (*pos >= ARRAY_SIZE(sctp_dbg_objcnt)) ? NULL : (void *)pos;
 }
 
+static const struct seq_operations sctp_objcnt_seq_ops = {
+       .start = sctp_objcnt_seq_start,
+       .next  = sctp_objcnt_seq_next,
+       .stop  = sctp_objcnt_seq_stop,
+       .show  = sctp_objcnt_seq_show,
+};
+
+static int sctp_objcnt_seq_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &sctp_objcnt_seq_ops);
+}
+
+static const struct file_operations sctp_objcnt_ops = {
+       .open    = sctp_objcnt_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = seq_release,
+};
+
 /* Initialize the objcount in the proc filesystem.  */
 void sctp_dbg_objcnt_init(void)
 {
        struct proc_dir_entry *ent;
-       ent = create_proc_read_entry("sctp_dbg_objcnt", 0, proc_net_sctp,
-                              sctp_dbg_objcnt_read, NULL);
+
+       ent = create_proc_entry("sctp_dbg_objcnt", 0, proc_net_sctp);
        if (!ent)
                printk(KERN_WARNING
                        "sctp_dbg_objcnt: Unable to create /proc entry.\n");
+       else
+               ent->proc_fops = &sctp_objcnt_ops;
 }
 
 /* Cleanup the objcount entry in the proc filesystem.  */
index 5e811b91f21c8b6922fa37e7ca6fad3910c9e99c..aa700feea76c02dcb6cdd906574c7d68b37a67b4 100644 (file)
@@ -1,19 +1,19 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions handle output processing.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index a42af865c2ef21336761653337b8995644910697..1bb3c5c35d2ab5fc78f252d2edc9e1f2c70b6dab 100644 (file)
@@ -1,21 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2003 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions implement the sctp_outq class.   The outqueue handles
  * bundling and queueing of outgoing SCTP chunks.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
@@ -1179,8 +1179,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack)
                tchunk = list_entry(lchunk, struct sctp_chunk,
                                    transmitted_list);
                tsn = ntohl(tchunk->subh.data_hdr->tsn);
-               if (TSN_lte(tsn, ctsn))
+               if (TSN_lte(tsn, ctsn)) {
+                       list_del_init(&tchunk->transmitted_list);
                        sctp_chunk_free(tchunk);
+               }
        }
 
        /* ii) Set rwnd equal to the newly received a_rwnd minus the
index 1b2976d34ac759212a24d2aa1ee97cfcb1e2cd87..8cb4f060bce68298d2f3d59ff67bf97fab276dbc 100644 (file)
@@ -1,8 +1,8 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions implement the SCTP primitive functions from Section 10.
  *
  * functions--this file is the functions which populate the struct proto
  * for SCTP which is the BOTTOM of the sockets interface.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 249973204070bfb811085b3b2ce988b7dc093128..69bb5a63fd8bc3774817e67f2e80d3857f87768d 100644 (file)
@@ -1,15 +1,15 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * Copyright (c) 2003 International Business Machines, Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
@@ -38,6 +38,7 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <net/sctp/sctp.h>
+#include <net/ip.h> /* for snmp_fold_field */
 
 static struct snmp_mib sctp_snmp_list[] = {
        SNMP_MIB_ITEM("SctpCurrEstab", SCTP_MIB_CURRESTAB),
@@ -75,26 +76,6 @@ static struct snmp_mib sctp_snmp_list[] = {
        SNMP_MIB_SENTINEL
 };
 
-/* Return the current value of a particular entry in the mib by adding its
- * per cpu counters.
- */
-static unsigned long
-fold_field(void *mib[], int nr)
-{
-       unsigned long res = 0;
-       int i;
-
-       for_each_possible_cpu(i) {
-               res +=
-                   *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
-                                        sizeof (unsigned long) * nr));
-               res +=
-                   *((unsigned long *) (((void *) per_cpu_ptr(mib[1], i)) +
-                                        sizeof (unsigned long) * nr));
-       }
-       return res;
-}
-
 /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */
 static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
 {
@@ -102,7 +83,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v)
 
        for (i = 0; sctp_snmp_list[i].name != NULL; i++)
                seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name,
-                          fold_field((void **)sctp_statistics,
+                          snmp_fold_field((void **)sctp_statistics,
                                      sctp_snmp_list[i].entry));
 
        return 0;
index 1339742e49f177c714a578d51d1edb52026350b0..22a16571499c3bc82902941d96f2bdbdfb00eca7 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
@@ -6,17 +6,17 @@
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * Initialization/cleanup for SCTP protocol support.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 77383e9b398833e698ad3ab72597160250451443..e45be4e3f80d733c8f3eb27773651ad1a4d44add 100644 (file)
@@ -1,22 +1,22 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2002 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions work with the state functions in sctp_sm_statefuns.c
  * to implement the state operations.  These functions implement the
  * steps which require modifying existing data structures.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
@@ -3224,6 +3224,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
        }
 
        /* Free the cached last sent asconf chunk. */
+       list_del_init(&asconf->transmitted_list);
        sctp_chunk_free(asconf);
        asoc->addip_last_asconf = NULL;
 
index 78d1a8a49bd05bf53f4f58426d6ad4c7b0d498a0..28eb38eb60833a7e339f2eed56ef47c8545f1985 100644 (file)
@@ -1,21 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions work with the state functions in sctp_sm_statefuns.c
  * to implement that state operations.  These functions implement the
  * steps which require modifying existing data structures.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index f98658782d4fc6cf26759c3a55de11caa71b274a..f2ed6473feef5e60da676c2e36ae412220c0c52b 100644 (file)
@@ -1,23 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2002 Intel Corp.
  * Copyright (c) 2002      Nokia Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
- *
- * This is part of the SCTP Linux Kernel Reference Implementation.
+ * This is part of the SCTP Linux Kernel Implementation.
  *
  * These are the state functions for the state machine.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index e6016e41ffa0ac88db0f7bb2da6fdfb134f6b38f..d991237fb4003dd4a9cf9b2af454d5db1644ebe9 100644 (file)
@@ -1,21 +1,21 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 Nokia, Inc.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These are the state tables for the SCTP state machine.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 710df67a67857184c43060fce807f1809411db4e..d47d5787e2e5b8eba49dcb177c0d8b6549d993f2 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
@@ -6,7 +6,7 @@
  * Copyright (c) 2001-2002 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions interface with the sockets layer to implement the
  * SCTP Extensions for the Sockets API.
  * functions--this file is the functions which populate the struct proto
  * for SCTP which is the BOTTOM of the sockets interface.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
@@ -1911,7 +1911,8 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
                 * rwnd by that amount. If all the data in the skb is read,
                 * rwnd is updated when the event is freed.
                 */
-               sctp_assoc_rwnd_increase(event->asoc, copied);
+               if (!sctp_ulpevent_is_notification(event))
+                       sctp_assoc_rwnd_increase(event->asoc, copied);
                goto out;
        } else if ((event->msg_flags & MSG_NOTIFICATION) ||
                   (event->msg_flags & MSG_EOR))
@@ -4314,6 +4315,9 @@ static int sctp_copy_laddrs_old(struct sock *sk, __u16 port,
                    (AF_INET6 == addr->a.sa.sa_family))
                        continue;
                memcpy(&temp, &addr->a, sizeof(temp));
+               if (!temp.v4.sin_port)
+                       temp.v4.sin_port = htons(port);
+
                sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
                                                                &temp);
                addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
@@ -4346,6 +4350,9 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
                    (AF_INET6 == addr->a.sa.sa_family))
                        continue;
                memcpy(&temp, &addr->a, sizeof(temp));
+               if (!temp.v4.sin_port)
+                       temp.v4.sin_port = htons(port);
+
                sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
                                                                &temp);
                addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
index cbe2513d2822730ffe68853e66da1eca2d54d01b..737d330e5ffc6a4fdeb4d8b64cccc53e34b619f0 100644 (file)
@@ -1,17 +1,17 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * Copyright (c) 2003 International Business Machines, Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions manipulate sctp SSN tracker.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 5eb6ea829b5440b749199b08be6d15951b3eade0..52910697e104ceaadae120adcd1e5c8375b2c658 100644 (file)
@@ -1,18 +1,18 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2002, 2004
  * Copyright (c) 2002 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * Sysctl related interfaces for SCTP.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index dfa109341aeb1fb3c88d2abc0c47130478a06e3b..d9f8af852b5634d608c2ae6d36c42a2174e477b4 100644 (file)
@@ -1,23 +1,23 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001-2003 International Business Machines Corp.
  * Copyright (c) 2001 Intel Corp.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * This module provides the abstraction for an SCTP tranport representing
  * a remote transport address.  For local transport addresses, we just use
  * union sctp_addr.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 1ff0daade304ae68ddae5630f390faea8a979058..f3e58b2759050806f00f7e0c5269489997e8bdb6 100644 (file)
@@ -1,20 +1,20 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 Intel Corp.
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * These functions manipulate sctp tsn mapping array.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index 047c27df98f441aa8b8e3f33427a5436bfb41f74..e27b11f18b7f2a32935e9de3a24dd8a4030e7b91 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
@@ -8,13 +8,14 @@
  *
  * These functions manipulate an sctp event.   The struct ulpevent is used
  * to carry notifications and data to the ULP (sockets).
- * The SCTP reference implementation is free software;
+ *
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
index c25caefa3bcb4b3ddb0b0dc36bd96019d368427e..5061a26c5028d927bf40bb51d772fe91691432f4 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
@@ -8,13 +8,13 @@
  *
  * This abstraction carries sctp events to the ULP (sockets).
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation 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, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation 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.
@@ -283,7 +283,7 @@ out_free:
 /* 2nd Level Abstractions */
 
 /* Helper function to store chunks that need to be reassembled.  */
-static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
+static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
                                         struct sctp_ulpevent *event)
 {
        struct sk_buff *pos;
@@ -405,7 +405,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
 /* Helper function to check if an incoming chunk has filled up the last
  * missing fragment in a SCTP datagram and return the corresponding event.
  */
-static inline struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ulpq)
+static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ulpq)
 {
        struct sk_buff *pos;
        struct sctp_ulpevent *cevent;
@@ -512,7 +512,7 @@ found:
 }
 
 /* Retrieve the next set of fragments of a partial message. */
-static inline struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
+static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)
 {
        struct sk_buff *pos, *last_frag, *first_frag;
        struct sctp_ulpevent *cevent;
@@ -606,7 +606,7 @@ static struct sctp_ulpevent *sctp_ulpq_reasm(struct sctp_ulpq *ulpq,
 }
 
 /* Retrieve the first part (sequential fragments) for partial delivery.  */
-static inline struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
+static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)
 {
        struct sk_buff *pos, *last_frag, *first_frag;
        struct sctp_ulpevent *cevent;
@@ -735,7 +735,7 @@ static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq)
 /* Helper function to gather skbs that have possibly become
  * ordered by an an incoming chunk.
  */
-static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
+static void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
                                              struct sctp_ulpevent *event)
 {
        struct sk_buff_head *event_list;
@@ -779,7 +779,7 @@ static inline void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
 }
 
 /* Helper function to store chunks needing ordering.  */
-static inline void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
+static void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq,
                                           struct sctp_ulpevent *event)
 {
        struct sk_buff *pos;
@@ -867,13 +867,14 @@ static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq,
 /* Helper function to gather skbs that have possibly become
  * ordered by forward tsn skipping their dependencies.
  */
-static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
+static void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
 {
        struct sk_buff *pos, *tmp;
        struct sctp_ulpevent *cevent;
        struct sctp_ulpevent *event;
        struct sctp_stream *in;
        struct sk_buff_head temp;
+       struct sk_buff_head *lobby = &ulpq->lobby;
        __u16 csid, cssn;
 
        in  = &ulpq->asoc->ssnmap->in;
@@ -881,7 +882,7 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
        /* We are holding the chunks by stream, by SSN.  */
        skb_queue_head_init(&temp);
        event = NULL;
-       sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
+       sctp_skb_for_each(pos, lobby, tmp) {
                cevent = (struct sctp_ulpevent *) pos->cb;
                csid = cevent->stream;
                cssn = cevent->ssn;
@@ -895,10 +896,10 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
                        continue;
 
                /* see if this ssn has been marked by skipping */
-               if (!SSN_lte(cssn, sctp_ssn_peek(in, csid)))
+               if (!SSN_lt(cssn, sctp_ssn_peek(in, csid)))
                        break;
 
-               __skb_unlink(pos, &ulpq->lobby);
+               __skb_unlink(pos, lobby);
                if (!event)
                        /* Create a temporary list to collect chunks on.  */
                        event = sctp_skb2event(pos);
@@ -907,6 +908,22 @@ static inline void sctp_ulpq_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
                __skb_queue_tail(&temp, pos);
        }
 
+       /* If we didn't reap any data, see if the next expected SSN
+        * is next on the queue and if so, use that.
+        */
+       if (event == NULL && pos != (struct sk_buff *)lobby) {
+               cevent = (struct sctp_ulpevent *) pos->cb;
+               csid = cevent->stream;
+               cssn = cevent->ssn;
+
+               if (csid == sid && cssn == sctp_ssn_peek(in, csid)) {
+                       sctp_ssn_next(in, csid);
+                       __skb_unlink(pos, lobby);
+                       __skb_queue_tail(&temp, pos);
+                       event = sctp_skb2event(pos);
+               }
+       }
+
        /* Send event to the ULP.  'event' is the sctp_ulpevent for
         * very first SKB on the 'temp' list.
         */
index a1f52cb47200990d9da983c204319954ff4e0a18..b939fbd0119539f38b6c4f34e211223d9d8b4a45 100644 (file)
@@ -6,3 +6,4 @@ kallsyms
 pnmtologo
 bin2c
 unifdef
+binoffset
index b96ea8d6a5ed0eb375a4db068cdb2c564407cd42..da3559ea92e03759d6a2a6d32c1307a9e1dc5c3b 100644 (file)
@@ -39,15 +39,19 @@ escsq = $(subst $(squote),'\$(squote)',$1)
 # - If they are equal no change, and no timestamp update
 # - stdin is piped in from the first prerequisite ($<) so one has
 #   to specify a valid file as first prerequisite (often the kbuild file)
+ quiet_chk_filechk = echo '  CHK     $@'
+silent_chk_filechk = :
+ quiet_upd_filechk = echo '  UPD     $@'
+silent_upd_filechk = :
 define filechk
        $(Q)set -e;                             \
-       echo '  CHK     $@';                    \
+       $($(quiet)chk_filechk);                 \
        mkdir -p $(dir $@);                     \
        $(filechk_$(1)) < $< > $@.tmp;          \
        if [ -r $@ ] && cmp -s $@ $@.tmp; then  \
                rm -f $@.tmp;                   \
        else                                    \
-               echo '  UPD     $@';            \
+               $($(quiet)upd_filechk);         \
                mv -f $@.tmp $@;                \
        fi
 endef
index 5d546466e6b1f8d2e700fa0ef846ebe6a14569cd..dbe1fb5e8cc03f6dbeeea4f5c92173d2a4ce1e66 100644 (file)
@@ -613,7 +613,7 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
        if (sym)
                return elf->strtab + sym->st_name;
        else
-               return "";
+               return "(unknown)";
 }
 
 static const char *sec_name(struct elf_info *elf, int shndx)
@@ -1102,7 +1102,7 @@ static int is_function(Elf_Sym *sym)
        if (sym)
                return ELF_ST_TYPE(sym->st_info) == STT_FUNC;
        else
-               return 0;
+               return -1;
 }
 
 /*
@@ -1120,24 +1120,31 @@ static void report_sec_mismatch(const char *modname, enum mismatch mismatch,
 {
        const char *from, *from_p;
        const char *to, *to_p;
-       from = from_is_func ? "function" : "variable";
-       from_p = from_is_func ? "()" : "";
-       to = to_is_func ? "function" : "variable";
-       to_p = to_is_func ? "()" : "";
+
+       switch (from_is_func) {
+       case 0: from = "variable"; from_p = "";   break;
+       case 1: from = "function"; from_p = "()"; break;
+       default: from = "(unknown reference)"; from_p = ""; break;
+       }
+       switch (to_is_func) {
+       case 0: to = "variable"; to_p = "";   break;
+       case 1: to = "function"; to_p = "()"; break;
+       default: to = "(unknown reference)"; to_p = ""; break;
+       }
 
        sec_mismatch_count++;
        if (!sec_mismatch_verbose)
                return;
 
-       fprintf(stderr, "WARNING: %s(%s+0x%llx): Section mismatch in"
-                       " reference from the %s %s%s to the %s %s:%s%s\n",
-                        modname, fromsec, fromaddr, from, fromsym, from_p,
-                       to, tosec, tosym, to_p);
+       warn("%s(%s+0x%llx): Section mismatch in reference from the %s %s%s "
+            "to the %s %s:%s%s\n",
+            modname, fromsec, fromaddr, from, fromsym, from_p, to, tosec,
+            tosym, to_p);
 
        switch (mismatch) {
        case TEXT_TO_INIT:
                fprintf(stderr,
-               "The function %s %s() references\n"
+               "The function %s%s() references\n"
                "the %s %s%s%s.\n"
                "This is often because %s lacks a %s\n"
                "annotation or the annotation of %s is wrong.\n",
@@ -1938,10 +1945,10 @@ int main(int argc, char **argv)
        if (dump_write)
                write_dump(dump_write);
        if (sec_mismatch_count && !sec_mismatch_verbose)
-               fprintf(stderr, "modpost: Found %d section mismatch(es).\n"
-                       "To see full details build your kernel with:\n"
-                       "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
-                       sec_mismatch_count);
+               warn("modpost: Found %d section mismatch(es).\n"
+                    "To see full details build your kernel with:\n"
+                    "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
+                    sec_mismatch_count);
 
        return err;
 }
index 0f657b5f3bc860bf602680d3a22a312371a2a6a1..ba6bf5d5abf9189ea4dcb71c2af31ce9a9b4dfe5 100644 (file)
@@ -13,6 +13,7 @@ set -e
 
 # Some variables and settings used throughout the script
 version=$KERNELRELEASE
+revision=`cat .version`
 tmpdir="$objtree/debian/tmp"
 packagename=linux-$version
 
@@ -65,7 +66,7 @@ done
 name="Kernel Compiler <$(id -nu)@$(hostname -f)>"
 # Generate a simple changelog template
 cat <<EOF > debian/changelog
-linux ($version) unstable; urgency=low
+linux ($version-$revision) unstable; urgency=low
 
   * A standard release