summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/00-INDEX8
-rw-r--r--Documentation/feature-removal-schedule.txt20
-rw-r--r--Documentation/laptops/00-INDEX10
-rw-r--r--Documentation/laptops/acer-wmi.txt202
-rw-r--r--Documentation/laptops/sony-laptop.txt (renamed from Documentation/sony-laptop.txt)1
-rw-r--r--Documentation/laptops/sonypi.txt (renamed from Documentation/sonypi.txt)0
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt (renamed from Documentation/thinkpad-acpi.txt)0
-rw-r--r--Documentation/sysctl/kernel.txt29
-rw-r--r--MAINTAINERS10
-rw-r--r--arch/alpha/Kconfig1
-rw-r--r--arch/arm/Kconfig19
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/blackfin/Kconfig1
-rw-r--r--arch/cris/Kconfig1
-rw-r--r--arch/frv/Kconfig1
-rw-r--r--arch/h8300/Kconfig1
-rw-r--r--arch/ia64/Kconfig1
-rw-r--r--arch/ia64/pci/pci.c25
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c16
-rw-r--r--arch/m32r/Kconfig1
-rw-r--r--arch/m68k/Kconfig1
-rw-r--r--arch/m68knommu/Kconfig1
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/ppc/Kconfig1
-rw-r--r--arch/s390/defconfig87
-rw-r--r--arch/s390/kernel/binfmt_elf32.c11
-rw-r--r--arch/s390/kernel/compat_wrapper.S20
-rw-r--r--arch/s390/kernel/process.c1
-rw-r--r--arch/s390/kernel/setup.c1
-rw-r--r--arch/s390/kernel/syscalls.S3
-rw-r--r--arch/s390/kernel/traps.c3
-rw-r--r--arch/s390/mm/fault.c40
-rw-r--r--arch/s390/mm/init.c3
-rw-r--r--arch/s390/mm/mmap.c65
-rw-r--r--arch/s390/mm/pgtable.c176
-rw-r--r--arch/s390/mm/vmem.c28
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/sparc/kernel/errtbls.c144
-rw-r--r--arch/sparc/kernel/of_device.c27
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S4
-rw-r--r--arch/sparc64/Kconfig5
-rw-r--r--arch/sparc64/kernel/iommu.c352
-rw-r--r--arch/sparc64/kernel/iommu_common.h33
-rw-r--r--arch/sparc64/kernel/kprobes.c113
-rw-r--r--arch/sparc64/kernel/of_device.c26
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c278
-rw-r--r--arch/v850/Kconfig1
-rw-r--r--arch/x86/Kconfig4
-rw-r--r--arch/x86/Kconfig.debug6
-rw-r--r--arch/x86/Makefile4
-rw-r--r--arch/x86/boot/.gitignore2
-rw-r--r--arch/x86/boot/printf.c24
-rw-r--r--arch/x86/configs/i386_defconfig1
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/cpu/mcheck/therm_throt.c2
-rw-r--r--arch/x86/kernel/entry_32.S15
-rw-r--r--arch/x86/kernel/entry_64.S18
-rw-r--r--arch/x86/kernel/geode_32.c5
-rw-r--r--arch/x86/kernel/head_32.S151
-rw-r--r--arch/x86/kernel/mfgpt_32.c123
-rw-r--r--arch/x86/kernel/quirks.c2
-rw-r--r--arch/x86/kernel/setup_32.c4
-rw-r--r--arch/x86/kernel/topology.c2
-rw-r--r--arch/x86/mm/init_32.c74
-rw-r--r--arch/x86/mm/init_64.c8
-rw-r--r--arch/x86/mm/ioremap.c55
-rw-r--r--arch/x86/mm/pageattr.c140
-rw-r--r--arch/x86/pci/common.c25
-rw-r--r--arch/x86/pci/direct.c4
-rw-r--r--arch/x86/pci/fixup.c6
-rw-r--r--arch/x86/pci/legacy.c2
-rw-r--r--arch/x86/pci/mmconfig-shared.c41
-rw-r--r--arch/x86/pci/mmconfig_32.c20
-rw-r--r--arch/x86/pci/mmconfig_64.c18
-rw-r--r--arch/x86/pci/pci.h22
-rw-r--r--arch/x86/pci/visws.c3
-rw-r--r--arch/x86/power/Makefile4
-rw-r--r--arch/x86/power/cpu_32.c (renamed from arch/x86/power/cpu.c)2
-rw-r--r--arch/x86/power/cpu_64.c (renamed from arch/x86/kernel/suspend_64.c)160
-rw-r--r--arch/x86/power/hibernate_32.c (renamed from arch/x86/power/suspend.c)6
-rw-r--r--arch/x86/power/hibernate_64.c169
-rw-r--r--arch/x86/power/hibernate_asm_32.S (renamed from arch/x86/power/swsusp.S)3
-rw-r--r--arch/x86/power/hibernate_asm_64.S (renamed from arch/x86/kernel/suspend_asm_64.S)9
-rw-r--r--arch/x86/xen/mmu.c6
-rw-r--r--arch/x86/xen/time.c10
-rw-r--r--arch/xtensa/Kconfig1
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/bus.c7
-rw-r--r--drivers/acpi/osl.c25
-rw-r--r--drivers/acpi/sbs.c2
-rw-r--r--drivers/acpi/sbshc.c6
-rw-r--r--drivers/block/ub.c2
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/cpuidle/cpuidle.c13
-rw-r--r--drivers/ide/Kconfig6
-rw-r--r--drivers/isdn/hisax/avm_a1p.c3
-rw-r--r--drivers/isdn/hisax/config.c7
-rw-r--r--drivers/isdn/hisax/hfc_sx.c3
-rw-r--r--drivers/isdn/hisax/isac.c9
-rw-r--r--drivers/isdn/hisax/isar.c3
-rw-r--r--drivers/lguest/page_tables.c4
-rw-r--r--drivers/media/video/em28xx/Kconfig3
-rw-r--r--drivers/memstick/Kconfig26
-rw-r--r--drivers/memstick/Makefile11
-rw-r--r--drivers/memstick/core/Kconfig26
-rw-r--r--drivers/memstick/core/Makefile11
-rw-r--r--drivers/memstick/core/memstick.c614
-rw-r--r--drivers/memstick/core/mspro_block.c1351
-rw-r--r--drivers/memstick/host/Kconfig22
-rw-r--r--drivers/memstick/host/Makefile10
-rw-r--r--drivers/memstick/host/tifm_ms.c685
-rw-r--r--drivers/misc/Kconfig13
-rw-r--r--drivers/misc/acer-wmi.c6
-rw-r--r--drivers/misc/tifm_7xx1.c17
-rw-r--r--drivers/misc/tifm_core.c7
-rw-r--r--drivers/mmc/host/Kconfig8
-rw-r--r--drivers/mmc/host/at91_mci.c114
-rw-r--r--drivers/mmc/host/ricoh_mmc.c162
-rw-r--r--drivers/mmc/host/sdhci.c13
-rw-r--r--drivers/mmc/host/sdhci.h1
-rw-r--r--drivers/mtd/nand/cs553x_nand.c31
-rw-r--r--drivers/net/bnx2.c4
-rw-r--r--drivers/net/bnx2x.c4
-rw-r--r--drivers/net/natsemi.c6
-rw-r--r--drivers/net/pppol2tp.c22
-rw-r--r--drivers/net/starfire.c2
-rw-r--r--drivers/net/typhoon.c4
-rw-r--r--drivers/net/via-velocity.c2
-rw-r--r--drivers/net/wan/x25_asy.c1
-rw-r--r--drivers/pcmcia/Kconfig1
-rw-r--r--drivers/rtc/rtc-r9701.c1
-rw-r--r--drivers/s390/char/sclp_vt220.c31
-rw-r--r--drivers/s390/cio/qdio.c18
-rw-r--r--drivers/s390/crypto/ap_bus.c4
-rw-r--r--drivers/scsi/aic7xxx/Makefile4
-rw-r--r--fs/ext4/inode.c115
-rw-r--r--fs/ext4/mballoc.c164
-rw-r--r--fs/ext4/migrate.c123
-rw-r--r--fs/ext4/namei.c1
-rw-r--r--fs/ext4/super.c11
-rw-r--r--fs/hostfs/hostfs_kern.c1
-rw-r--r--fs/ioctl.c8
-rw-r--r--fs/jbd/commit.c14
-rw-r--r--fs/jbd2/commit.c10
-rw-r--r--fs/jbd2/recovery.c2
-rw-r--r--fs/splice.c2
-rw-r--r--include/asm-blackfin/page.h1
-rw-r--r--include/asm-h8300/page.h1
-rw-r--r--include/asm-m68knommu/page.h1
-rw-r--r--include/asm-s390/a.out.h32
-rw-r--r--include/asm-s390/bitops.h4
-rw-r--r--include/asm-s390/elf.h22
-rw-r--r--include/asm-s390/mmu.h9
-rw-r--r--include/asm-s390/mmu_context.h20
-rw-r--r--include/asm-s390/page.h36
-rw-r--r--include/asm-s390/pgalloc.h116
-rw-r--r--include/asm-s390/pgtable.h191
-rw-r--r--include/asm-s390/processor.h45
-rw-r--r--include/asm-s390/tlb.h49
-rw-r--r--include/asm-s390/tlbflush.h11
-rw-r--r--include/asm-s390/unistd.h5
-rw-r--r--include/asm-sparc/a.out.h31
-rw-r--r--include/asm-sparc/bpp.h2
-rw-r--r--include/asm-sparc/bsderrno.h94
-rw-r--r--include/asm-sparc/bug.h18
-rw-r--r--include/asm-sparc/bugs.h18
-rw-r--r--include/asm-sparc/byteorder.h51
-rw-r--r--include/asm-sparc/cache.h21
-rw-r--r--include/asm-sparc/current.h31
-rw-r--r--include/asm-sparc/device.h2
-rw-r--r--include/asm-sparc/errno.h1
-rw-r--r--include/asm-sparc/fb.h16
-rw-r--r--include/asm-sparc/of_platform.h5
-rw-r--r--include/asm-sparc/prom.h11
-rw-r--r--include/asm-sparc64/a.out.h99
-rw-r--r--include/asm-sparc64/auxvec.h5
-rw-r--r--include/asm-sparc64/bpp.h74
-rw-r--r--include/asm-sparc64/bsderrno.h94
-rw-r--r--include/asm-sparc64/bug.h23
-rw-r--r--include/asm-sparc64/bugs.h11
-rw-r--r--include/asm-sparc64/byteorder.h50
-rw-r--r--include/asm-sparc64/cache.h19
-rw-r--r--include/asm-sparc64/cputime.h7
-rw-r--r--include/asm-sparc64/current.h9
-rw-r--r--include/asm-sparc64/device.h22
-rw-r--r--include/asm-sparc64/div64.h2
-rw-r--r--include/asm-sparc64/emergency-restart.h7
-rw-r--r--include/asm-sparc64/errno.h115
-rw-r--r--include/asm-sparc64/fb.h28
-rw-r--r--include/asm-sparc64/io.h2
-rw-r--r--include/asm-sparc64/iommu.h1
-rw-r--r--include/asm-sparc64/kprobes.h4
-rw-r--r--include/asm-sparc64/of_device.h39
-rw-r--r--include/asm-sparc64/of_platform.h5
-rw-r--r--include/asm-sparc64/prom.h104
-rw-r--r--include/asm-v850/page.h1
-rw-r--r--include/asm-x86/acpi.h4
-rw-r--r--include/asm-x86/cacheflush.h2
-rw-r--r--include/asm-x86/geode.h9
-rw-r--r--include/asm-x86/page_32.h1
-rw-r--r--include/asm-x86/pgtable.h2
-rw-r--r--include/asm-x86/pgtable_32.h4
-rw-r--r--include/linux/compiler-gcc4.h9
-rw-r--r--include/linux/ext4_fs.h7
-rw-r--r--include/linux/hrtimer.h2
-rw-r--r--include/linux/memcontrol.h10
-rw-r--r--include/linux/memstick.h299
-rw-r--r--include/linux/pci.h16
-rw-r--r--include/linux/sctp.h4
-rw-r--r--include/linux/swapops.h2
-rw-r--r--include/linux/thermal.h23
-rw-r--r--include/linux/tifm.h4
-rw-r--r--include/linux/timex.h9
-rw-r--r--include/net/sctp/auth.h8
-rw-r--r--include/net/sctp/command.h8
-rw-r--r--include/net/sctp/constants.h8
-rw-r--r--include/net/sctp/sctp.h8
-rw-r--r--include/net/sctp/sm.h8
-rw-r--r--include/net/sctp/structs.h8
-rw-r--r--include/net/sctp/tsnmap.h8
-rw-r--r--include/net/sctp/ulpevent.h8
-rw-r--r--include/net/sctp/ulpqueue.h6
-rw-r--r--include/net/sctp/user.h8
-rw-r--r--init/Kconfig2
-rw-r--r--init/Makefile4
-rw-r--r--init/main.c2
-rw-r--r--kernel/.gitignore1
-rw-r--r--kernel/compat.c43
-rw-r--r--kernel/hrtimer.c55
-rw-r--r--kernel/posix-timers.c17
-rw-r--r--kernel/time/ntp.c4
-rw-r--r--lib/Kconfig.debug14
-rw-r--r--lib/vsprintf.c49
-rw-r--r--mm/memcontrol.c2
-rw-r--r--mm/rmap.c4
-rw-r--r--net/ipv4/igmp.c13
-rw-r--r--net/ipv6/route.c4
-rw-r--r--net/key/af_key.c117
-rw-r--r--net/sched/em_meta.c6
-rw-r--r--net/sched/ematch.c8
-rw-r--r--net/sched/sch_htb.c13
-rw-r--r--net/sctp/associola.c14
-rw-r--r--net/sctp/auth.c8
-rw-r--r--net/sctp/bind_addr.c8
-rw-r--r--net/sctp/chunk.c8
-rw-r--r--net/sctp/command.c8
-rw-r--r--net/sctp/debug.c12
-rw-r--r--net/sctp/endpointola.c12
-rw-r--r--net/sctp/input.c8
-rw-r--r--net/sctp/inqueue.c8
-rw-r--r--net/sctp/ipv6.c8
-rw-r--r--net/sctp/objcnt.c93
-rw-r--r--net/sctp/output.c8
-rw-r--r--net/sctp/outqueue.c12
-rw-r--r--net/sctp/primitive.c8
-rw-r--r--net/sctp/proc.c31
-rw-r--r--net/sctp/protocol.c8
-rw-r--r--net/sctp/sm_make_chunk.c9
-rw-r--r--net/sctp/sm_sideeffect.c8
-rw-r--r--net/sctp/sm_statefuns.c10
-rw-r--r--net/sctp/sm_statetable.c8
-rw-r--r--net/sctp/socket.c17
-rw-r--r--net/sctp/ssnmap.c8
-rw-r--r--net/sctp/sysctl.c8
-rw-r--r--net/sctp/transport.c8
-rw-r--r--net/sctp/tsnmap.c8
-rw-r--r--net/sctp/ulpevent.c7
-rw-r--r--net/sctp/ulpqueue.c43
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Kbuild.include8
-rw-r--r--scripts/mod/modpost.c37
-rw-r--r--scripts/package/builddeb3
278 files changed, 6591 insertions, 2968 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 6e9c4050a41b..8d556707bb68 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -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
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index ce9503c892b5..4d3aa519eadf 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -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
index 000000000000..729c2c062e10
--- /dev/null
+++ b/Documentation/laptops/00-INDEX
@@ -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
index 000000000000..b06696329cff
--- /dev/null
+++ b/Documentation/laptops/acer-wmi.txt
@@ -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.
diff --git a/Documentation/sony-laptop.txt b/Documentation/laptops/sony-laptop.txt
index 7a5c1a81905c..8b2bc1572d98 100644
--- a/Documentation/sony-laptop.txt
+++ b/Documentation/laptops/sony-laptop.txt
@@ -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.
-
diff --git a/Documentation/sonypi.txt b/Documentation/laptops/sonypi.txt
index 4857acfc50f1..4857acfc50f1 100644
--- a/Documentation/sonypi.txt
+++ b/Documentation/laptops/sonypi.txt
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 6c2477754a2a..6c2477754a2a 100644
--- a/Documentation/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 8984a5396271..dc8801d4e944 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -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
diff --git a/MAINTAINERS b/MAINTAINERS
index 0d6f5119a6da..c40f0ae96552 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 5b7dcd5a0e75..002703b8c0b0 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -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
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4127af93c5f3..9619c43783ff 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -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"
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 28e0caf4156c..c75d7089f982 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -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
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index 368bc7fe167e..589c6aca4803 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -24,6 +24,7 @@ config RWSEM_XCHGADD_ALGORITHM
config BLACKFIN
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
config ZONE_DMA
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 8456bc8efb7c..9389d38f222f 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -54,6 +54,7 @@ config FORCE_MAX_ZONEORDER
config CRIS
bool
default y
+ select HAVE_IDE
config HZ
int
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 9e561ede0925..a5aac1b07562 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -5,6 +5,7 @@
config FRV
bool
default y
+ select HAVE_IDE
config ZONE_DMA
bool
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index f69e5ea38558..085dc6ec152b 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -8,6 +8,7 @@ mainmenu "uClinux/h8300 (w/o MMU) Kernel Configuration"
config H8300
bool
default y
+ select HAVE_IDE
config MMU
bool
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index b0de1132dfc0..2d4fcd01bc91 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -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
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 488e48a5deea..8fd7e825192b 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -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);
}
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index e1a3e19d3d9c..999f14f986e2 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -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;
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index d4679ab55b96..de153de2ea9f 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -8,6 +8,7 @@ mainmenu "Linux/M32R Kernel Configuration"
config M32R
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
config SBUS
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 2b0ed89cd173..65db2261b9ea 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -5,6 +5,7 @@
config M68K
bool
default y
+ select HAVE_IDE
config MMU
bool
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 548a7b321633..07eb4c4bab82 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -8,6 +8,7 @@ mainmenu "uClinux/68k (w/o MMU) Kernel Configuration"
config M68K
bool
default y
+ select HAVE_IDE
config MMU
bool
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ec78a5762e9e..ade230d445d9 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1,6 +1,7 @@
config MIPS
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
# Horrible source of confusion. Die, die, die ...
select EMBEDDED
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index d929ac84f25a..bc7a19da6245 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -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
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 26b963c33c88..485513c9f1af 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -87,6 +87,7 @@ config ARCH_NO_VIRT_TO_BUS
config PPC
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 531156f8919c..abc877faf123 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -42,6 +42,7 @@ config GENERIC_CALIBRATE_DELAY
config PPC
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
select HAVE_KPROBES
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index ece7b99da895..39921f3a9685 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -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
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
index f1e40ca00d8d..3e1c315b736d 100644
--- a/arch/s390/kernel/binfmt_elf32.c
+++ b/arch/s390/kernel/binfmt_elf32.c
@@ -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>");
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 062c3d4c0394..743d54f0b8db 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -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
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 0e7aca039307..a6a4729e0e94 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -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>
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index f9f8779022a0..290e504061a3 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -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>
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 25eac7802fc4..c87ec687d4c6 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -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)
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index a4d29025ddbd..60f728aeaf12 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -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;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2456b52ed068..ed13d429a487 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -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.
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 983ec6ec0e7c..8053245fe259 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -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));
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index 356257c171de..5932a824547a 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -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
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 019f518cd5a0..fd072013f88c 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -23,11 +23,18 @@
#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);
}
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 7c1287ccf788..35d90a4720fd 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -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);
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 6e035d1cf789..d87d4bf88803 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -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
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 7c674a3503b6..c40343c54920 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -69,6 +69,7 @@ config NR_CPUS
config SPARC
bool
default y
+ select HAVE_IDE
select HAVE_OPROFILE
# Identify this as a Sparc32 build
diff --git a/arch/sparc/kernel/errtbls.c b/arch/sparc/kernel/errtbls.c
index bb36f6eadfee..ed14df7116e9 100644
--- a/arch/sparc/kernel/errtbls.c
+++ b/arch/sparc/kernel/errtbls.c
@@ -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,
-};
-
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 3ea000d15e3a..cc4c235c4f59 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -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);
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 216147d6e61f..b1002c607196 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -89,6 +89,10 @@ SECTIONS
.data.cacheline_aligned : {
*(.data.cacheline_aligned)
}
+ . = ALIGN(32);
+ .data.read_mostly : {
+ *(.data.read_mostly)
+ }
__bss_start = .;
.sbss : {
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index b810f2b7526a..3af378ddb6ae 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -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
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 5623a4d59dff..d3276ebcfb47 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -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);
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 4b5cafa2877a..0713bd58499c 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -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 */
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index d94f901d321e..34fc3ddd5002 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -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;
}
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index fc5c0cc793b8..0fd9db95b896 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -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);
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 61baf8dc095e..ddca6c6c0b49 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -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);
}
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index 7b6d3716efca..4379f43505ef 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -78,6 +78,7 @@ config MCA
config V850
bool
default y
+ select HAVE_IDE
menu "Processor type and features"
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 65a70b777c12..aaed1a3b92d6 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -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
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index fa555148823d..864affc9a7b0 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -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
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 364865b1b08d..204af43535c5 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -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
diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore
index 18465143cfa2..b1bdc4c6f9f2 100644
--- a/arch/x86/boot/.gitignore
+++ b/arch/x86/boot/.gitignore
@@ -3,3 +3,5 @@ bzImage
setup
setup.bin
setup.elf
+cpustr.h
+mkcpustr
diff --git a/arch/x86/boot/printf.c b/arch/x86/boot/printf.c
index 1a09f9309d3c..7e7e890699be 100644
--- a/arch/x86/boot/printf.c
+++ b/arch/x86/boot/printf.c
@@ -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;
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 77562e7cdab6..3df340b54e57 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -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
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 9e2b0ef851de..eef98cb00c62 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -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
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 21dc1a061bf1..76ec0f8f138a 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -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
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 24885be5c48c..9b7e01daa1ca 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -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 */
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index be5c31d04884..824e21b80aad 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -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)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index c7341e81941c..6be39a387c5a 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -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 */
diff --git a/arch/x86/kernel/geode_32.c b/arch/x86/kernel/geode_32.c
index 9c7f7d395968..9dad6ca6cd70 100644
--- a/arch/x86/kernel/geode_32.c
+++ b/arch/x86/kernel/geode_32.c
@@ -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;
}
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 5d8c5730686b..74ef4a41f224 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -19,6 +19,10 @@
#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
diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c
index 219f86eb6123..027fc067b399 100644
--- a/arch/x86/kernel/mfgpt_32.c
+++ b/arch/x86/kernel/mfgpt_32.c
@@ -12,48 +12,37 @@
*/
/*
- * 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;
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 6ba33ca8715a..1941482d4ca3 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -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; "
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index d1d8c347cc0b..691ab4cb167b 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -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;
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index e6757aaa202b..a40051b71d9b 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -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
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index d1bc04006d16..8106bba41ecb 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -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
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 5fe880fc305d..b59fc238151f 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -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)),
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index ee6648fe6b15..a4897a85268a 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -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);
}
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 8493c855582b..440210a2277d 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -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);
/*
@@ -302,6 +304,19 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
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
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 52deabc72a6f..b7c67a187b6b 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -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);
}
diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c
index 431c9a51b157..42f3e4cad179 100644
--- a/arch/x86/pci/direct.c
+++ b/arch/x86/pci/direct.c
@@ -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;
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index 74d30ff33c49..a5ef5f551373 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -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 = {
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 5565d7016b75..e041ced0ce13 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -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);
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 4df637e34f81..8d54df4dfaad 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -22,46 +22,13 @@
#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;
diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c
index 1bf5816d34c8..081816ada057 100644
--- a/arch/x86/pci/mmconfig_32.c
+++ b/arch/x86/pci/mmconfig_32.c
@@ -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;
}
diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c
index 4095e4d66a1d..9207fd49233c 100644
--- a/arch/x86/pci/mmconfig_64.c
+++ b/arch/x86/pci/mmconfig_64.c
@@ -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;
}
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index ac56d3916c50..3431518d921a 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -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);
/*
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index 8ecb1c722594..c2df4e97eed6 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -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) { }
diff --git a/arch/x86/power/Makefile b/arch/x86/power/Makefile
index d764ec950065..9ff4d5b55ad1 100644
--- a/arch/x86/power/Makefile
+++ b/arch/x86/power/Makefile
@@ -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
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu_32.c
index efcf620d1439..7f9c6da04a4c 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu_32.c
@@ -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();
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/power/cpu_64.c
index 7ac7130022f1..66bdfb591fd8 100644
--- a/arch/x86/kernel/suspend_64.c
+++ b/arch/x86/power/cpu_64.c
@@ -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 */
diff --git a/arch/x86/power/suspend.c b/arch/x86/power/hibernate_32.c
index a0020b913f31..f2b6e3f11bfc 100644
--- a/arch/x86/power/suspend.c
+++ b/arch/x86/power/hibernate_32.c
@@ -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
index 000000000000..b542355e0e34
--- /dev/null
+++ b/arch/x86/power/hibernate_64.c
@@ -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;
+}
diff --git a/arch/x86/power/swsusp.S b/arch/x86/power/hibernate_asm_32.S
index 53662e05b393..b95aa6cfe3cb 100644
--- a/arch/x86/power/swsusp.S
+++ b/arch/x86/power/hibernate_asm_32.S
@@ -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"
diff --git a/arch/x86/kernel/suspend_asm_64.S b/arch/x86/power/hibernate_asm_64.S
index aeb9a4d7681e..1deb3244b99b 100644
--- a/arch/x86/kernel/suspend_asm_64.S
+++ b/arch/x86/power/hibernate_asm_64.S
@@ -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>
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 45aa771e73a9..0144395448ae 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -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);
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index b3721fd6877b..c39e1a5aa241 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -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;
}
/*
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index fd36764d7fb7..9fc8551a1cf6 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -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
diff --git a/drivers/Kconfig b/drivers/Kconfig
index b86877bdc7ac..3a0e3549739f 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -80,6 +80,8 @@ source "drivers/usb/Kconfig"
source "drivers/mmc/Kconfig"
+source "drivers/memstick/Kconfig"
+
source "drivers/leds/Kconfig"
source "drivers/infiniband/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 30ba97ec5eb5..e5e394a7e6c0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -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/
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index f29812a86533..40b0fcae4c78 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -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
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 8b0d4b7d188a..ce3c0a2cbac4 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -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
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index a14501c98f40..34b3386dedca 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -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);
}
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 1194105cc3ca..585ae3c9c8ea 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -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;
}
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index ae9a90438e2f..a2cf3008ce6c 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -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;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index a70c1c29a7aa..c452e2d355ee 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -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. */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index f01ac9a07bf5..47c6be84fc84 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -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.
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 2c4b2d47973e..60f71e6345e3 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -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();
}
}
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index ab8fb257528e..043c34ad0a05 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -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
diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c
index c87fa3f9b298..3039c6d68fc4 100644
--- a/drivers/isdn/hisax/avm_a1p.c
+++ b/drivers/isdn/hisax/avm_a1p.c
@@ -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;
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 97097ef3491e..a0ee43c04dd5 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -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;
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index 4fd09d21a27f..05482d2688e3 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -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;
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 4e9f23803dae..07b1673122b8 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -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;
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index c547a6665052..bfeb9b6aa043 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -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;
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index 74b4cf2a6c41..275f23c2deb4 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -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");
}
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
index abbd38c1ebba..0f7a0bd86ff4 100644
--- a/drivers/media/video/em28xx/Kconfig
+++ b/drivers/media/video/em28xx/Kconfig
@@ -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
index 000000000000..1093fdb07297
--- /dev/null
+++ b/drivers/memstick/Kconfig
@@ -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
index 000000000000..dc160fb43515
--- /dev/null
+++ b/drivers/memstick/Makefile
@@ -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
index 000000000000..95f1814b5368
--- /dev/null
+++ b/drivers/memstick/core/Kconfig
@@ -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
index 000000000000..8b2b5293877e
--- /dev/null
+++ b/drivers/memstick/core/Makefile
@@ -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
index 000000000000..bba467fe4bce
--- /dev/null
+++ b/drivers/memstick/core/memstick.c
@@ -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
index 000000000000..423ad8cf4bb9
--- /dev/null
+++ b/drivers/memstick/core/mspro_block.c
@@ -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
index 000000000000..c002fcc3c879
--- /dev/null
+++ b/drivers/memstick/host/Kconfig
@@ -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
index 000000000000..ee666380efa1
--- /dev/null
+++ b/drivers/memstick/host/Makefile
@@ -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
index 000000000000..f55b71a4337d
--- /dev/null
+++ b/drivers/memstick/host/tifm_ms.c
@@ -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);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c143a86c2ea6..1abc95ca9dfa 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -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.
diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c
index a4d677504250..d7aea93081f2 100644
--- a/drivers/misc/acer-wmi.c
+++ b/drivers/misc/acer-wmi.c
@@ -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;
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 54380da343a5..63a089b29545 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -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);
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c
index 97544052e768..82dc72a1484f 100644
--- a/drivers/misc/tifm_core.c
+++ b/drivers/misc/tifm_core.c
@@ -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)
{
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 5fef6783c716..3b3cd0e74715 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -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
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index b1edcefdd4f9..21acecc9fe3a 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -70,10 +70,11 @@
#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);
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c
index 1e8704533bc5..a16d7609e4ee 100644
--- a/drivers/mmc/host/ricoh_mmc.c
+++ b/drivers/mmc/host/ricoh_mmc.c
@@ -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,
};
/*****************************************************************************\
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 785bbdcf4a58..4b673aa2dc3c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -30,6 +30,10 @@
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);
}
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index e4d77b038bfa..d5a38f1b755a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -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 */
};
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index 19e1594421a4..8dab69657b19 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -13,9 +13,12 @@
* 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 */
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8b552c6dd2e7..471c7f3e8a4a 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -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" },
diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c
index 4a73c884d0c4..afc7f34b1dcf 100644
--- a/drivers/net/bnx2x.c
+++ b/drivers/net/bnx2x.c
@@ -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" }
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 0a3e60418e53..385f69c14387 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -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 */
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 5aa0a8089694..e0b072d9fdb7 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -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)
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 6e00dc857afa..c49214feae91 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -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";
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index f50cb520dffb..333961bb7873 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -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)",
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 8c9fb824cbd4..cc0addb5640c 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -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},
{ }
};
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 5e2d763c6b5f..0f8aca8a4d43 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -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. */
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 519b4ff79f7f..8b22281b087f 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -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
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
index a64626a82d0b..b35f9bfa2af4 100644
--- a/drivers/rtc/rtc-r9701.c
+++ b/drivers/rtc/rtc-r9701.c
@@ -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 };
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 68071622d4bb..f47f4a768be5 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -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;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index e2a781b6b21d..097fc0967e9d 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -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;
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 67aaff3e668d..d0c6fd3b1c19 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -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);
diff --git a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile
index 4c549540a35d..741d81861d17 100644
--- a/drivers/scsi/aic7xxx/Makefile
+++ b/drivers/scsi/aic7xxx/Makefile
@@ -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
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index f4e387452246..7dd9b50d5ebc 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -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)) {
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 76e5fedc0a0b..dd0fcfcb35ce 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -420,6 +420,7 @@
#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;
}
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index 3ebc2332f52e..8c6c685b9d22 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -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);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index d153bb5922fc..a9347fb43bcc 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -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);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 93beb865c20d..0072da75221f 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -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,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index d0549cb4fb23..5222345ddccf 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -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"
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 683002fefa55..f32fbde2175e 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -18,12 +18,12 @@
/**
* 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.
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 8e08efcaede2..a38c7186c570 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -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);
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 4f302d279279..a8173081f831 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -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);
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index d36356f7d222..146411387ada 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -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 "
diff --git a/fs/splice.c b/fs/splice.c
index 14e2262c0a04..9b559ee711a8 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -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;
/*
diff --git a/include/asm-blackfin/page.h b/include/asm-blackfin/page.h
index d5c9d1433781..c7db0220fbd6 100644
--- a/include/asm-blackfin/page.h
+++ b/include/asm-blackfin/page.h
@@ -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])
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index a83492449130..d6a3eaf3b27e 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -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-m68knommu/page.h b/include/asm-m68knommu/page.h
index 6af480c7f291..1e82ebb7d644 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -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
index 8d6bd9c2952e..000000000000
--- a/include/asm-s390/a.out.h
+++ /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__ */
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index 882db054110c..ab83c844d04c 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -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;
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index b73a424d0f97..b3ac262c4582 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -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
diff --git a/include/asm-s390/mmu.h b/include/asm-s390/mmu.h
index ccd36d26615a..1698e29c5b20 100644
--- a/include/asm-s390/mmu.h
+++ b/include/asm-s390/mmu.h
@@ -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
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
index a77d4ba3c8eb..b5a34c6f91a9 100644
--- a/include/asm-s390/mmu_context.h
+++ b/include/asm-s390/mmu_context.h
@@ -10,15 +10,19 @@
#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 */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 7f29a981f48c..fe7f92b6ae6d 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -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>
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index 900d44807e10..f5b2bf3d7c1d 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -20,10 +20,11 @@
#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 */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 3f520754e71c..65154dc9a9e5 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -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);
}
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index e8785634cbdb..51d88912aa20 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -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;
diff --git a/include/asm-s390/tlb.h b/include/asm-s390/tlb.h
index 3c8177fa9e06..3d8a96d39d9d 100644
--- a/include/asm-s390/tlb.h
+++ b/include/asm-s390/tlb.h
@@ -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)
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index 70fa5ae58180..35fb4f9127b2 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -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();
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index f04acb2670a8..583da807ea97 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -256,7 +256,10 @@
#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
diff --git a/include/asm-sparc/a.out.h b/include/asm-sparc/a.out.h
index 744cfe6c0de8..2f1c3748a068 100644
--- a/include/asm-sparc/a.out.h
+++ b/include/asm-sparc/a.out.h
@@ -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__ */
diff --git a/include/asm-sparc/bpp.h b/include/asm-sparc/bpp.h
index 3578ac113cf0..31f515e499a7 100644
--- a/include/asm-sparc/bpp.h
+++ b/include/asm-sparc/bpp.h
@@ -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
index 54a75be43abb..000000000000
--- a/include/asm-sparc/bsderrno.h
+++ /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) */
diff --git a/include/asm-sparc/bug.h b/include/asm-sparc/bug.h
index 04151208189f..8a59e5a8c217 100644
--- a/include/asm-sparc/bug.h
+++ b/include/asm-sparc/bug.h
@@ -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
diff --git a/include/asm-sparc/bugs.h b/include/asm-sparc/bugs.h
index a0f939beeea1..2dfc07bc8e54 100644
--- a/include/asm-sparc/bugs.h
+++ b/include/asm-sparc/bugs.h
@@ -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
}
diff --git a/include/asm-sparc/byteorder.h b/include/asm-sparc/byteorder.h
index a2949aea48ef..bcd83aa351c5 100644
--- a/include/asm-sparc/byteorder.h
+++ b/include/asm-sparc/byteorder.h
@@ -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>
diff --git a/include/asm-sparc/cache.h b/include/asm-sparc/cache.h
index cb971e88aea4..41f85ae4bd4a 100644
--- a/include/asm-sparc/cache.h
+++ b/include/asm-sparc/cache.h
@@ -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) */
diff --git a/include/asm-sparc/current.h b/include/asm-sparc/current.h
index 8fe7c82a5e21..8a1d9d6643b0 100644
--- a/include/asm-sparc/current.h
+++ b/include/asm-sparc/current.h
@@ -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) */
diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h
index c0a7786d65f7..680e51d87374 100644
--- a/include/asm-sparc/device.h
+++ b/include/asm-sparc/device.h
@@ -19,5 +19,3 @@ struct dev_archdata {
};
#endif /* _ASM_SPARC_DEVICE_H */
-
-
diff --git a/include/asm-sparc/errno.h b/include/asm-sparc/errno.h
index ed41c8bac1fa..a9ef172977de 100644
--- a/include/asm-sparc/errno.h
+++ b/include/asm-sparc/errno.h
@@ -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
diff --git a/include/asm-sparc/fb.h b/include/asm-sparc/fb.h
index c73ca081e1f5..b83e44729655 100644
--- a/include/asm-sparc/fb.h
+++ b/include/asm-sparc/fb.h
@@ -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_ */
diff --git a/include/asm-sparc/of_platform.h b/include/asm-sparc/of_platform.h
index d638737ff13c..38334351c36b 100644
--- a/include/asm-sparc/of_platform.h
+++ b/include/asm-sparc/of_platform.h
@@ -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 */
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
index 71f2a1998324..df5dc4422483 100644
--- a/include/asm-sparc/prom.h
+++ b/include/asm-sparc/prom.h
@@ -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,
diff --git a/include/asm-sparc64/a.out.h b/include/asm-sparc64/a.out.h
index 53c95bdfc66e..44208c2a188e 100644
--- a/include/asm-sparc64/a.out.h
+++ b/include/asm-sparc64/a.out.h
@@ -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>
diff --git a/include/asm-sparc64/auxvec.h b/include/asm-sparc64/auxvec.h
index 436a29129828..1f45c67d7316 100644
--- a/include/asm-sparc64/auxvec.h
+++ b/include/asm-sparc64/auxvec.h
@@ -1,4 +1 @@
-#ifndef __ASM_SPARC64_AUXVEC_H
-#define __ASM_SPARC64_AUXVEC_H
-
-#endif /* !(__ASM_SPARC64_AUXVEC_H) */
+#include <asm-sparc/auxvec.h>
diff --git a/include/asm-sparc64/bpp.h b/include/asm-sparc64/bpp.h
index abe163a50382..514eee20272e 100644
--- a/include/asm-sparc64/bpp.h
+++ b/include/asm-sparc64/bpp.h
@@ -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
index 52fe880d2af8..000000000000
--- a/include/asm-sparc64/bsderrno.h
+++ /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) */
diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h
index 516bb27f3fc4..3433737c7a67 100644
--- a/include/asm-sparc64/bug.h
+++ b/include/asm-sparc64/bug.h
@@ -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>
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
index 11ade6841971..04ae9e2818cf 100644
--- a/include/asm-sparc64/bugs.h
+++ b/include/asm-sparc64/bugs.h
@@ -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>
diff --git a/include/asm-sparc64/byteorder.h b/include/asm-sparc64/byteorder.h
index 3943022906fd..f672855bee17 100644
--- a/include/asm-sparc64/byteorder.h
+++ b/include/asm-sparc64/byteorder.h
@@ -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>
diff --git a/include/asm-sparc64/cache.h b/include/asm-sparc64/cache.h
index e9df17acedde..fa9de5cadbf1 100644
--- a/include/asm-sparc64/cache.h
+++ b/include/asm-sparc64/cache.h
@@ -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>
diff --git a/include/asm-sparc64/cputime.h b/include/asm-sparc64/cputime.h
index dec2fc7a36f8..435f37a92f7c 100644
--- a/include/asm-sparc64/cputime.h
+++ b/include/asm-sparc64/cputime.h
@@ -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>
diff --git a/include/asm-sparc64/current.h b/include/asm-sparc64/current.h
index 6c21e4ee2475..a7904a7f53a8 100644
--- a/include/asm-sparc64/current.h
+++ b/include/asm-sparc64/current.h
@@ -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>
diff --git a/include/asm-sparc64/device.h b/include/asm-sparc64/device.h
index 5111e8717be3..4145c47097e2 100644
--- a/include/asm-sparc64/device.h
+++ b/include/asm-sparc64/device.h
@@ -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>
diff --git a/include/asm-sparc64/div64.h b/include/asm-sparc64/div64.h
index 6cd978cefb28..928c94f99ecf 100644
--- a/include/asm-sparc64/div64.h
+++ b/include/asm-sparc64/div64.h
@@ -1 +1 @@
-#include <asm-generic/div64.h>
+#include <asm-sparc/div64.h>
diff --git a/include/asm-sparc64/emergency-restart.h b/include/asm-sparc64/emergency-restart.h
index 108d8c48e42e..2cac7b644da8 100644
--- a/include/asm-sparc64/emergency-restart.h
+++ b/include/asm-sparc64/emergency-restart.h
@@ -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>
diff --git a/include/asm-sparc64/errno.h b/include/asm-sparc64/errno.h
index ea3509ee1b0b..9701fe01cc53 100644
--- a/include/asm-sparc64/errno.h
+++ b/include/asm-sparc64/errno.h
@@ -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>
diff --git a/include/asm-sparc64/fb.h b/include/asm-sparc64/fb.h
index 389012e5fbad..1c2ac5832f39 100644
--- a/include/asm-sparc64/fb.h
+++ b/include/asm-sparc64/fb.h
@@ -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>
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index b6ece223562d..c299b853b5ba 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -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)
{
diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h
index 9eac6676caf1..46325ddee23b 100644
--- a/include/asm-sparc64/iommu.h
+++ b/include/asm-sparc64/iommu.h
@@ -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;
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 5020eaf67c29..7237dd87663e 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -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 */
diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h
index 46d69b3223c5..a769fdbe164a 100644
--- a/include/asm-sparc64/of_device.h
+++ b/include/asm-sparc64/of_device.h
@@ -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>
diff --git a/include/asm-sparc64/of_platform.h b/include/asm-sparc64/of_platform.h
index f15cfa723916..78aa032b674c 100644
--- a/include/asm-sparc64/of_platform.h
+++ b/include/asm-sparc64/of_platform.h
@@ -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 */
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
index 07843f9f05df..5fa166ee3ffa 100644
--- a/include/asm-sparc64/prom.h
+++ b/include/asm-sparc64/prom.h
@@ -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>
diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h
index 661d8cd08839..74a539a9bd59 100644
--- a/include/asm-v850/page.h
+++ b/include/asm-v850/page.h
@@ -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)
diff --git a/include/asm-x86/acpi.h b/include/asm-x86/acpi.h
index 98a9ca266531..7a72d6aa50be 100644
--- a/include/asm-x86/acpi.h
+++ b/include/asm-x86/acpi.h
@@ -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;
diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
index 8dd8c5e3cc7f..6a22212b4b20 100644
--- a/include/asm-x86/cacheflush.h
+++ b/include/asm-x86/cacheflush.h
@@ -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
diff --git a/include/asm-x86/geode.h b/include/asm-x86/geode.h
index 811fe14f70b2..9e7280092a48 100644
--- a/include/asm-x86/geode.h
+++ b/include/asm-x86/geode.h
@@ -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
diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h
index 984998a30741..5f7257fd589b 100644
--- a/include/asm-x86/page_32.h
+++ b/include/asm-x86/page_32.h
@@ -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 */
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
index 44c0a4f1b1eb..174b87738714 100644
--- a/include/asm-x86/pgtable.h
+++ b/include/asm-x86/pgtable.h
@@ -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)
diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
index 80dd438642f6..a842c7222b1e 100644
--- a/include/asm-x86/pgtable_32.h
+++ b/include/asm-x86/pgtable_32.h
@@ -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
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index 0ab3a3232330..974f5b7bb205 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -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)
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index c4f635a4dd25..250032548597 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -490,6 +490,13 @@ do { \
#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
*/
#define EXT4_MOUNT_CHECK 0x00001 /* Do mount-time checks */
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 600fc3bcf63e..1ad56a7b2f74 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -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);
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 9815951ec995..925d57b236aa 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -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
index 000000000000..334d059d6794
--- /dev/null
+++ b/include/linux/memstick.h
@@ -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
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 7215d3b1f4af..87195b62de52 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -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;
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index 5eb38cc0e5a4..8ba1c320f975 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -10,13 +10,13 @@
*
* 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.
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index 7bf2d149d209..6ec39ab27b4b 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -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
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index bba7712cadc7..818ca1cf0b6d 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -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__ */
diff --git a/include/linux/tifm.h b/include/linux/tifm.h
index 2096b76d0cee..da76ed85f595 100644
--- a/include/linux/tifm.h
+++ b/include/linux/tifm.h
@@ -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,
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 8ea3e71ba7fa..c3f374786a43 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -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);
diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 5db261a1e85e..49bc9577c61e 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -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.
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index c1f797673571..10ae2da6f93b 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -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.
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index fefcba67bd1e..c32ddf0279c8 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -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.
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 4977b0a81535..57df27f19588 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -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.
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index bf2f5ed69c15..ef9e7ed2c82e 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -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.
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 4d591bfce452..9c827a749b6f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -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.
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h
index 70a824df6f60..099211bf998d 100644
--- a/include/net/sctp/tsnmap.h
+++ b/include/net/sctp/tsnmap.h
@@ -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.
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index 922a151eb93c..9bcfc12275e8 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -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.
@@ -10,15 +10,15 @@
* 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.
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
index cd33270e86dd..2e5ee0d8458d 100644
--- a/include/net/sctp/ulpqueue.h
+++ b/include/net/sctp/ulpqueue.h
@@ -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.
@@ -11,13 +11,13 @@
* 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.
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 954090b1e354..9462d6ae2f37 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -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.
diff --git a/init/Kconfig b/init/Kconfig
index 455170e1c1e3..824d48cb67bf 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -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
diff --git a/init/Makefile b/init/Makefile
index 633392f5cdee..c5f157ce293e 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -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)"
diff --git a/init/main.c b/init/main.c
index c59859b85db0..8b1982082ad8 100644
--- a/init/main.c
+++ b/init/main.c
@@ -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();
diff --git a/kernel/.gitignore b/kernel/.gitignore
index f2ab70073bd4..ab4f1090f437 100644
--- a/kernel/.gitignore
+++ b/kernel/.gitignore
@@ -3,3 +3,4 @@
#
config_data.h
config_data.gz
+timeconst.h
diff --git a/kernel/compat.c b/kernel/compat.c
index 42a1ed4b61b1..5f0e201bcfd3 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -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;
}
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 668f3967eb39..3f4a57c7895d 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -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);
}
/*
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index ce268966007d..022c9c3cee6f 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -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
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index e64efaf957e8..c88b5910e7ab 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -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)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ce0bb2600c25..a370fe828a79 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -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
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 419993f58c6b..fd987b17bda7 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -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;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 5c2c702af617..6bded84c20c8 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -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;
}
diff --git a/mm/rmap.c b/mm/rmap.c
index a0e92a263d12..8fd527c4e2bf 100644
--- 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)) {
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 994648be80ab..732cd07e6071 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -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;
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 513f72e3db0d..6e7b56ef4449 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -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),
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 45c3c27d279a..b3ac85e808ac 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -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);
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index d417ec8e3ca3..3da4129b89d1 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -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);
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 74ff918455a2..5e6f82e0e6f3 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -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);
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index e1a579efc215..795c761ad99f 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -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++;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index a016e78061f4..d29f792e0529 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -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;
}
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index ae367c82e512..8bb79f281774 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -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.
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 13fbfb449a55..a27511ebc4cb 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -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.
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index 619d0f2dee51..4d3128f5ccc3 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -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.
diff --git a/net/sctp/command.c b/net/sctp/command.c
index 3ff804757f4a..bb977330002a 100644
--- a/net/sctp/command.c
+++ b/net/sctp/command.c
@@ -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.
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index 80f70aa53386..67715f4eb849 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -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.
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index de6f505d6ff8..e39a0cdef184 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -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.
diff --git a/net/sctp/input.c b/net/sctp/input.c
index d695f710fc77..57fe2f81eca8 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -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.
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index cf4b7eb023b3..bbf5dd2a97c4 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -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.
*
@@ -11,13 +11,13 @@
* (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.
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 74f106a7a7e9..4d7ec961ae1d 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -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.
diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c
index 2cf6ad6ff8ce..14e294e37626 100644
--- a/net/sctp/objcnt.c
+++ b/net/sctp/objcnt.c
@@ -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. */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 5e811b91f21c..aa700feea76c 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -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.
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index a42af865c2ef..1bb3c5c35d2a 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -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
diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c
index 1b2976d34ac7..8cb4f060bce6 100644
--- a/net/sctp/primitive.c
+++ b/net/sctp/primitive.c
@@ -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.
*
@@ -10,13 +10,13 @@
* 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.
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 249973204070..69bb5a63fd8b 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -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;
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 1339742e49f1..22a16571499c 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -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.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 77383e9b3988..e45be4e3f80d 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -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;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 78d1a8a49bd0..28eb38eb6083 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -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.
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index f98658782d4f..f2ed6473feef 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -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.
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index e6016e41ffa0..d991237fb400 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -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.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 710df67a6785..d47d5787e2e5 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -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.
@@ -15,13 +15,13 @@
* 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;
diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c
index cbe2513d2822..737d330e5ffc 100644
--- a/net/sctp/ssnmap.c
+++ b/net/sctp/ssnmap.c
@@ -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.
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 5eb6ea829b54..52910697e104 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -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.
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index dfa109341aeb..d9f8af852b56 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -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.
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index 1ff0daade304..f3e58b275905 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -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.
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 047c27df98f4..e27b11f18b7f 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -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.
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index c25caefa3bcb..5061a26c5028 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -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.
*/
diff --git a/scripts/.gitignore b/scripts/.gitignore
index a1f52cb47200..b939fbd01195 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -6,3 +6,4 @@ kallsyms
pnmtologo
bin2c
unifdef
+binoffset
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index b96ea8d6a5ed..da3559ea92e0 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -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
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 5d546466e6b1..dbe1fb5e8cc0 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -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;
}
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 0f657b5f3bc8..ba6bf5d5abf9 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -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