aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS10
-rw-r--r--Documentation/sound/alsa/Audiophile-Usb.txt81
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl4
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/boot/compressed/misc.c4
-rw-r--r--arch/arm/kernel/asm-offsets.c6
-rw-r--r--arch/arm/kernel/head-nommu.S4
-rw-r--r--arch/arm/kernel/head.S8
-rw-r--r--arch/arm/mach-aaec2000/aaed2000.c7
-rw-r--r--arch/arm/mach-aaec2000/core.c5
-rw-r--r--arch/arm/mach-aaec2000/core.h1
-rw-r--r--arch/arm/mach-imx/generic.c52
-rw-r--r--arch/arm/mach-imx/mx1ads.c76
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig15
-rw-r--r--arch/arm/mach-ixp4xx/Makefile3
-rw-r--r--arch/arm/mach-pxa/dma.c17
-rw-r--r--arch/arm/mach-sa1100/irq.c16
-rw-r--r--arch/arm/vfp/vfpmodule.c2
-rw-r--r--arch/i386/kernel/acpi/boot.c5
-rw-r--r--arch/i386/kernel/apic.c4
-rw-r--r--arch/i386/kernel/ptrace.c7
-rw-r--r--arch/i386/kernel/setup.c4
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c4
-rw-r--r--arch/i386/kernel/vm86.c2
-rw-r--r--arch/ia64/kernel/ptrace.c4
-rw-r--r--arch/mips/kernel/ptrace.c4
-rw-r--r--arch/powerpc/configs/cell_defconfig40
-rw-r--r--arch/powerpc/kernel/cputable.c16
-rw-r--r--arch/powerpc/kernel/kprobes.c14
-rw-r--r--arch/powerpc/kernel/module_64.c16
-rw-r--r--arch/powerpc/kernel/prom.c70
-rw-r--r--arch/powerpc/kernel/prom_init.c112
-rw-r--r--arch/powerpc/kernel/ptrace.c5
-rw-r--r--arch/powerpc/kernel/setup-common.c8
-rw-r--r--arch/powerpc/kernel/setup_64.c8
-rw-r--r--arch/powerpc/kernel/sysfs.c18
-rw-r--r--arch/powerpc/kernel/systbl.S13
-rw-r--r--arch/powerpc/mm/hugetlbpage.c295
-rw-r--r--arch/powerpc/mm/init_64.c7
-rw-r--r--arch/powerpc/mm/numa.c32
-rw-r--r--arch/powerpc/platforms/cell/Kconfig3
-rw-r--r--arch/powerpc/platforms/cell/setup.c78
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c101
-rw-r--r--arch/powerpc/platforms/cell/spu_callbacks.c13
-rw-r--r--arch/powerpc/platforms/pseries/eeh_event.c8
-rw-r--r--arch/ppc/platforms/4xx/ocotea.c2
-rw-r--r--arch/ppc/platforms/mpc8272ads_setup.c114
-rw-r--r--arch/ppc/platforms/mpc866ads_setup.c140
-rw-r--r--arch/ppc/platforms/mpc885ads_setup.c131
-rw-r--r--arch/ppc/platforms/pq2ads.c31
-rw-r--r--arch/ppc/syslib/ibm440gx_common.c13
-rw-r--r--arch/ppc/syslib/ibm440gx_common.h4
-rw-r--r--arch/ppc/syslib/mpc8xx_devices.c25
-rw-r--r--arch/ppc/syslib/ppc_sys.c4
-rw-r--r--arch/ppc/syslib/pq2_sys.c8
-rw-r--r--arch/s390/kernel/ptrace.c5
-rw-r--r--arch/s390/kernel/signal.c5
-rw-r--r--arch/sparc/kernel/systbls.S2
-rw-r--r--arch/sparc64/kernel/ptrace.c5
-rw-r--r--arch/sparc64/kernel/sys32.S1
-rw-r--r--arch/sparc64/kernel/systbls.S4
-rw-r--r--arch/sparc64/mm/tlb.c5
-rw-r--r--arch/um/Kconfig14
-rw-r--r--arch/um/Kconfig.i38619
-rw-r--r--arch/um/Makefile19
-rw-r--r--arch/um/defconfig240
-rw-r--r--arch/um/drivers/cow_user.c2
-rw-r--r--arch/um/kernel/irq.c93
-rw-r--r--arch/um/kernel/physmem.c2
-rw-r--r--arch/um/kernel/ptrace.c6
-rw-r--r--arch/um/kernel/skas/Makefile10
-rw-r--r--arch/um/kernel/time_kern.c2
-rw-r--r--arch/um/os-Linux/file.c2
-rw-r--r--arch/um/os-Linux/irq.c47
-rw-r--r--arch/um/os-Linux/main.c30
-rw-r--r--arch/um/os-Linux/process.c17
-rw-r--r--arch/um/os-Linux/skas/process.c6
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c4
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c4
-rw-r--r--arch/um/os-Linux/umid.c4
-rw-r--r--arch/um/os-Linux/user_syms.c7
-rw-r--r--arch/um/scripts/Makefile.rules12
-rw-r--r--arch/um/sys-i386/Makefile13
-rw-r--r--arch/um/sys-x86_64/Makefile13
-rw-r--r--arch/x86_64/ia32/ia32entry.S1
-rw-r--r--arch/x86_64/kernel/ptrace.c6
-rw-r--r--arch/x86_64/kernel/setup.c19
-rw-r--r--block/genhd.c2
-rw-r--r--drivers/block/floppy.c2
-rw-r--r--drivers/char/genrtc.c8
-rw-r--r--drivers/char/keyboard.c38
-rw-r--r--drivers/edac/e752x_edac.c17
-rw-r--r--drivers/infiniband/hw/ipath/ipath_debug.h15
-rw-r--r--drivers/infiniband/hw/ipath/ipath_diag.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c18
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c36
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c21
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h10
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.c6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_pe800.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_registers.h31
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c15
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sysfs.c14
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ud.c6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c39
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.h3
-rw-r--r--drivers/infiniband/hw/ipath/ips_common.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c2
-rw-r--r--drivers/input/evdev.c21
-rw-r--r--drivers/input/input.c11
-rw-r--r--drivers/input/keyboard/spitzkbd.c4
-rw-r--r--drivers/input/misc/wistron_btns.c30
-rw-r--r--drivers/input/mouse/psmouse-base.c4
-rw-r--r--drivers/input/serio/i8042-io.h4
-rw-r--r--drivers/input/touchscreen/ads7846.c414
-rw-r--r--drivers/input/touchscreen/corgi_ts.c2
-rw-r--r--drivers/md/raid1.c29
-rw-r--r--drivers/md/raid10.c46
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c2
-rw-r--r--drivers/mmc/at91_mci.c3
-rw-r--r--drivers/mmc/au1xmmc.c4
-rw-r--r--drivers/mmc/imxmmc.c60
-rw-r--r--drivers/mmc/mmc.c62
-rw-r--r--drivers/mmc/mmc_block.c6
-rw-r--r--drivers/mmc/mmci.c3
-rw-r--r--drivers/mmc/pxamci.c13
-rw-r--r--drivers/mmc/sdhci.c4
-rw-r--r--drivers/mmc/wbsd.c4
-rw-r--r--drivers/net/forcedeth.c312
-rw-r--r--drivers/net/hamradio/dmascc.c1
-rw-r--r--drivers/net/hamradio/scc.c1
-rw-r--r--drivers/net/hamradio/yam.c1
-rw-r--r--drivers/net/mv643xx_eth.c2
-rw-r--r--drivers/net/tg3.c82
-rw-r--r--drivers/net/tg3.h1
-rw-r--r--drivers/net/via-rhine.c6
-rw-r--r--drivers/rtc/rtc-dev.c17
-rw-r--r--drivers/rtc/rtc-sa1100.c6
-rw-r--r--drivers/s390/net/qeth_main.c1
-rw-r--r--drivers/s390/s390mach.c3
-rw-r--r--drivers/scsi/Kconfig4
-rw-r--r--drivers/scsi/advansys.c2
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h58
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c307
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c56
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c16
-rw-r--r--drivers/serial/imx.c40
-rw-r--r--drivers/sn/ioc3.c2
-rw-r--r--drivers/sn/ioc4.c2
-rw-r--r--drivers/video/au1200fb.c1922
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/compat.c20
-rw-r--r--fs/ext3/inode.c13
-rw-r--r--fs/locks.c21
-rw-r--r--fs/pipe.c190
-rw-r--r--fs/splice.c207
-rw-r--r--fs/stat.c2
-rw-r--r--include/asm-arm/arch-aaec2000/debug-macro.S1
-rw-r--r--include/asm-arm/arch-aaec2000/entry-macro.S1
-rw-r--r--include/asm-arm/arch-imx/debug-macro.S2
-rw-r--r--include/asm-arm/arch-imx/imx-uart.h10
-rw-r--r--include/asm-arm/arch-ixp4xx/io.h7
-rw-r--r--include/asm-arm/arch-ixp4xx/memory.h2
-rw-r--r--include/asm-arm/arch-pxa/dma.h26
-rw-r--r--include/asm-arm/bug.h1
-rw-r--r--include/asm-arm/unistd.h23
-rw-r--r--include/asm-powerpc/cputable.h14
-rw-r--r--include/asm-powerpc/io.h6
-rw-r--r--include/asm-powerpc/page_64.h1
-rw-r--r--include/asm-powerpc/pgalloc.h2
-rw-r--r--include/asm-powerpc/spu.h1
-rw-r--r--include/asm-powerpc/topology.h24
-rw-r--r--include/asm-powerpc/uaccess.h19
-rw-r--r--include/asm-powerpc/unistd.h20
-rw-r--r--include/asm-ppc/commproc.h1
-rw-r--r--include/asm-ppc/cpm2.h2
-rw-r--r--include/asm-ppc/ppc_sys.h2
-rw-r--r--include/asm-ppc/reg_booke.h1
-rw-r--r--include/asm-sparc/unistd.h2
-rw-r--r--include/asm-sparc64/tlbflush.h2
-rw-r--r--include/asm-sparc64/unistd.h2
-rw-r--r--include/linux/audit.h22
-rw-r--r--include/linux/fs_uart_pd.h60
-rw-r--r--include/linux/input.h109
-rw-r--r--include/linux/list.h2
-rw-r--r--include/linux/mmc/card.h1
-rw-r--r--include/linux/mod_devicetable.h48
-rw-r--r--include/linux/netfilter/x_tables.h8
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h2
-rw-r--r--include/linux/netlink.h1
-rw-r--r--include/linux/pipe_fs_i.h30
-rw-r--r--include/linux/security.h16
-rw-r--r--include/linux/selinux.h177
-rw-r--r--include/linux/spi/ads7846.h7
-rw-r--r--include/net/ax25.h10
-rw-r--r--include/net/inet_timewait_sock.h2
-rw-r--r--include/net/netrom.h8
-rw-r--r--include/net/rose.h14
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--include/net/sock.h2
-rw-r--r--include/sound/pcm.h6
-rw-r--r--include/sound/pcm_oss.h2
-rw-r--r--init/main.c2
-rw-r--r--ipc/msg.c11
-rw-r--r--ipc/sem.c11
-rw-r--r--ipc/shm.c19
-rw-r--r--ipc/util.c7
-rw-r--r--kernel/audit.c160
-rw-r--r--kernel/audit.h10
-rw-r--r--kernel/auditfilter.c289
-rw-r--r--kernel/auditsc.c269
-rw-r--r--kernel/exit.c3
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/ptrace.c39
-rw-r--r--mm/memory_hotplug.c6
-rw-r--r--mm/migrate.c11
-rw-r--r--mm/sparse.c9
-rw-r--r--net/ax25/af_ax25.c93
-rw-r--r--net/ax25/ax25_addr.c9
-rw-r--r--net/ax25/ax25_ds_timer.c3
-rw-r--r--net/ax25/ax25_iface.c13
-rw-r--r--net/ax25/ax25_ip.c3
-rw-r--r--net/ax25/ax25_out.c3
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/ax25/ax25_timer.c3
-rw-r--r--net/ax25/ax25_uid.c4
-rw-r--r--net/ax25/sysctl_net_ax25.c10
-rw-r--r--net/bridge/br_input.c1
-rw-r--r--net/dccp/proto.c13
-rw-r--r--net/decnet/dn_neigh.c5
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c10
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c11
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c39
-rw-r--r--net/ipv4/tcp.c13
-rw-r--r--net/ipv4/tcp_highspeed.c2
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/ipv4/xfrm4_output.c2
-rw-r--r--net/ipv6/route.c5
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c11
-rw-r--r--net/netfilter/x_tables.c4
-rw-r--r--net/netlink/af_netlink.c3
-rw-r--r--net/netrom/af_netrom.c18
-rw-r--r--net/netrom/nr_dev.c1
-rw-r--r--net/rose/af_rose.c13
-rw-r--r--net/rose/rose_dev.c1
-rw-r--r--net/rose/rose_link.c6
-rw-r--r--net/rose/rose_route.c7
-rw-r--r--net/sched/sch_netem.c2
-rw-r--r--net/sctp/inqueue.c1
-rw-r--r--net/sctp/sm_statefuns.c59
-rw-r--r--net/sctp/sm_statetable.c10
-rw-r--r--net/sctp/ulpqueue.c27
-rw-r--r--net/socket.c2
-rw-r--r--net/x25/x25_timer.c4
-rw-r--r--net/xfrm/xfrm_policy.c16
-rw-r--r--net/xfrm/xfrm_state.c8
-rw-r--r--scripts/mod/file2alias.c36
-rw-r--r--security/dummy.c6
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/avc.c13
-rw-r--r--security/selinux/exports.c74
-rw-r--r--security/selinux/hooks.c11
-rw-r--r--security/selinux/include/security.h5
-rw-r--r--security/selinux/ss/mls.c30
-rw-r--r--security/selinux/ss/mls.h4
-rw-r--r--security/selinux/ss/services.c235
-rw-r--r--sound/core/Kconfig12
-rw-r--r--sound/core/oss/pcm_oss.c8
-rw-r--r--sound/core/pcm.c12
-rw-r--r--sound/core/pcm_lib.c6
-rw-r--r--sound/core/pcm_memory.c8
-rw-r--r--sound/drivers/dummy.c14
-rw-r--r--sound/drivers/mpu401/mpu401.c14
-rw-r--r--sound/drivers/serial-u16550.c14
-rw-r--r--sound/drivers/virmidi.c14
-rw-r--r--sound/isa/opti9xx/miro.c3
-rw-r--r--sound/pci/ad1889.c3
-rw-r--r--sound/pci/ali5451/ali5451.c2
-rw-r--r--sound/pci/als300.c2
-rw-r--r--sound/pci/als4000.c2
-rw-r--r--sound/pci/atiixp.c2
-rw-r--r--sound/pci/atiixp_modem.c2
-rw-r--r--sound/pci/au88x0/au8810.c2
-rw-r--r--sound/pci/au88x0/au8820.c2
-rw-r--r--sound/pci/au88x0/au8830.c2
-rw-r--r--sound/pci/azt3328.c2
-rw-r--r--sound/pci/bt87x.c4
-rw-r--r--sound/pci/ca0106/ca0106_main.c2
-rw-r--r--sound/pci/cmipci.c2
-rw-r--r--sound/pci/cs4281.c2
-rw-r--r--sound/pci/cs46xx/cs46xx.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c2
-rw-r--r--sound/pci/emu10k1/emu10k1.c2
-rw-r--r--sound/pci/emu10k1/emu10k1x.c3
-rw-r--r--sound/pci/ens1370.c2
-rw-r--r--sound/pci/es1938.c2
-rw-r--r--sound/pci/es1968.c3
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/hda_intel.c2
-rw-r--r--sound/pci/hda/patch_analog.c13
-rw-r--r--sound/pci/hda/patch_realtek.c1
-rw-r--r--sound/pci/hda/patch_sigmatel.c4
-rw-r--r--sound/pci/ice1712/ice1712.c3
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/intel8x0.c8
-rw-r--r--sound/pci/intel8x0m.c2
-rw-r--r--sound/pci/korg1212/korg1212.c2
-rw-r--r--sound/pci/maestro3.c3
-rw-r--r--sound/pci/mixart/mixart.c3
-rw-r--r--sound/pci/nm256/nm256.c2
-rw-r--r--sound/pci/pcxhr/pcxhr.c3
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c4
-rw-r--r--sound/pci/riptide/riptide.c4
-rw-r--r--sound/pci/rme32.c2
-rw-r--r--sound/pci/rme96.c2
-rw-r--r--sound/pci/rme9652/hdsp.c2
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/pci/rme9652/rme9652.c2
-rw-r--r--sound/pci/sonicvibes.c2
-rw-r--r--sound/pci/trident/trident.c2
-rw-r--r--sound/pci/via82xx.c18
-rw-r--r--sound/pci/via82xx_modem.c2
-rw-r--r--sound/pci/vx222/vx222.c2
-rw-r--r--sound/pci/ymfpci/ymfpci.c2
-rw-r--r--sound/pcmcia/Kconfig4
-rw-r--r--sound/ppc/toonie.c2
-rw-r--r--sound/usb/usbquirks.h9
330 files changed, 5336 insertions, 3946 deletions
diff --git a/CREDITS b/CREDITS
index 787564bc248..6f50be37fa0 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1194,15 +1194,9 @@ S: Brecksville, OH 44141-1334
S: USA
N: Tristan Greaves
-E: Tristan.Greaves@icl.com
-E: tmg296@ecs.soton.ac.uk
-W: http://www.ecs.soton.ac.uk/~tmg296
+E: tristan@extricate.org
+W: http://www.extricate.org/
D: Miscellaneous ipv4 sysctl patches
-S: 15 Little Mead
-S: Denmead
-S: Hampshire
-S: PO7 6HS
-S: United Kingdom
N: Michael A. Griffith
E: grif@cs.ucr.edu
diff --git a/Documentation/sound/alsa/Audiophile-Usb.txt b/Documentation/sound/alsa/Audiophile-Usb.txt
index 4692c8e77dc..b535c2a198f 100644
--- a/Documentation/sound/alsa/Audiophile-Usb.txt
+++ b/Documentation/sound/alsa/Audiophile-Usb.txt
@@ -1,4 +1,4 @@
- Guide to using M-Audio Audiophile USB with ALSA and Jack v1.2
+ Guide to using M-Audio Audiophile USB with ALSA and Jack v1.3
========================================================
Thibault Le Meur <Thibault.LeMeur@supelec.fr>
@@ -22,16 +22,16 @@ The device has 4 audio interfaces, and 2 MIDI ports:
* Midi In (Mi)
* Midi Out (Mo)
-The internal DAC/ADC has the following caracteristics:
+The internal DAC/ADC has the following characteristics:
* sample depth of 16 or 24 bits
* sample rate from 8kHz to 96kHz
-* Two ports can't use different sample depths at the same time.Moreover, the
+* Two ports can't use different sample depths at the same time. Moreover, the
Audiophile USB documentation gives the following Warning: "Please exit any
audio application running before switching between bit depths"
Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be
activated at the same time depending on the audio mode selected:
- * 16-bit/48kHz ==> 4 channels in/ 4 channels out
+ * 16-bit/48kHz ==> 4 channels in/4 channels out
- Ai+Ao+Di+Do
* 24-bit/48kHz ==> 4 channels in/2 channels out,
or 2 channels in/4 channels out
@@ -41,8 +41,8 @@ activated at the same time depending on the audio mode selected:
Important facts about the Digital interface:
--------------------------------------------
- * The Do port additionnaly supports surround-encoded AC-3 and DTS passthrough,
-though I haven't tested it under linux
+ * The Do port additionally supports surround-encoded AC-3 and DTS passthrough,
+though I haven't tested it under Linux
- Note that in this setup only the Do interface can be enabled
* Apart from recording an audio digital stream, enabling the Di port is a way
to synchronize the device to an external sample clock
@@ -60,24 +60,23 @@ synchronization error (for instance sound played at an odd sample rate)
The Audiophile USB MIDI ports will be automatically supported once the
following modules have been loaded:
* snd-usb-audio
- * snd-seq
* snd-seq-midi
-No additionnal setting is required.
+No additional setting is required.
2.2 - Audio ports
-----------------
Audio functions of the Audiophile USB device are handled by the snd-usb-audio
module. This module can work in a default mode (without any device-specific
-parameter), or in an advanced mode with the device-specific parameter called
+parameter), or in an "advanced" mode with the device-specific parameter called
"device_setup".
2.2.1 - Default Alsa driver mode
-The default behaviour of the snd-usb-audio driver is to parse the device
+The default behavior of the snd-usb-audio driver is to parse the device
capabilities at startup and enable all functions inside the device (including
-all ports at any sample rates and any sample depths supported). This approach
+all ports at any supported sample rates and sample depths). This approach
has the advantage to let the driver easily switch from sample rates/depths
automatically according to the need of the application claiming the device.
@@ -114,9 +113,9 @@ gain).
For people having this problem, the snd-usb-audio module has a new module
parameter called "device_setup".
-2.2.2.1 - Initializing the working mode of the Audiohile USB
+2.2.2.1 - Initializing the working mode of the Audiophile USB
-As far as the Audiohile USB device is concerned, this value let the user
+As far as the Audiophile USB device is concerned, this value let the user
specify:
* the sample depth
* the sample rate
@@ -174,20 +173,20 @@ The parameter can be given:
IMPORTANT NOTE WHEN SWITCHING CONFIGURATION:
-------------------------------------------
- * You may need to _first_ intialize the module with the correct device_setup
+ * You may need to _first_ initialize the module with the correct device_setup
parameter and _only_after_ turn on the Audiophile USB device
* This is especially true when switching the sample depth:
- - first trun off the device
- - de-register the snd-usb-audio module
- - change the device_setup parameter (by either manually reprobing the module
- or changing modprobe.conf)
+ - first turn off the device
+ - de-register the snd-usb-audio module (modprobe -r)
+ - change the device_setup parameter by changing the device_setup
+ option in /etc/modprobe.conf
- turn on the device
2.2.2.3 - Audiophile USB's device_setup structure
If you want to understand the device_setup magic numbers for the Audiophile
USB, you need some very basic understanding of binary computation. However,
-this is not required to use the parameter and you may skip thi section.
+this is not required to use the parameter and you may skip this section.
The device_setup is one byte long and its structure is the following:
@@ -231,11 +230,11 @@ Caution:
2.2.3 - USB implementation details for this device
-You may safely skip this section if you're not interrested in driver
+You may safely skip this section if you're not interested in driver
development.
-This section describes some internals aspect of the device and summarize the
-data I got by usb-snooping the windows and linux drivers.
+This section describes some internal aspects of the device and summarize the
+data I got by usb-snooping the windows and Linux drivers.
The M-Audio Audiophile USB has 7 USB Interfaces:
a "USB interface":
@@ -277,9 +276,9 @@ Here is a short description of the AltSettings capabilities:
- 16-bit depth, 8-48kHz sample mode
- Synch playback (Do), audio format type III IEC1937_AC-3
-In order to ensure a correct intialization of the device, the driver
+In order to ensure a correct initialization of the device, the driver
_must_know_ how the device will be used:
- * if DTS is choosen, only Interface 2 with AltSet nb.6 must be
+ * if DTS is chosen, only Interface 2 with AltSet nb.6 must be
registered
* if 96KHz only AltSets nb.1 of each interface must be selected
* if samples are using 24bits/48KHz then AltSet 2 must me used if
@@ -290,7 +289,7 @@ _must_know_ how the device will be used:
is not connected
When device_setup is given as a parameter to the snd-usb-audio module, the
-parse_audio_enpoint function uses a quirk called
+parse_audio_endpoints function uses a quirk called
"audiophile_skip_setting_quirk" in order to prevent AltSettings not
corresponding to device_setup from being registered in the driver.
@@ -317,9 +316,8 @@ However you may see the following warning message:
using the "default" ALSA device. This is less efficient than it could be.
Consider using a hardware device instead rather than using the plug layer."
-
3.2 - Patching alsa to use direct pcm device
--------------------------------------------
+--------------------------------------------
A patch for Jack by Andreas Steinmetz adds support for Big Endian devices.
However it has not been included in the CVS tree.
@@ -331,3 +329,32 @@ After having applied the patch you can run jackd with the following command
line:
% jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
+3.2 - Getting 2 input and/or output interfaces in Jack
+------------------------------------------------------
+
+As you can see, starting the Jack server this way will only enable 1 stereo
+input (Di or Ai) and 1 stereo output (Ao or Do).
+
+This is due to the following restrictions:
+* Jack can only open one capture device and one playback device at a time
+* The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1
+ (and optionally hw:1,2)
+If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to
+combine the Alsa devices into one logical "complex" device.
+
+If you want to give it a try, I recommend reading the information from
+this page: http://www.sound-man.co.uk/linuxaudio/ice1712multi.html
+It is related to another device (ice1712) but can be adapted to suit
+the Audiophile USB.
+
+Enabling multiple Audiophile USB interfaces for Jackd will certainly require:
+* patching Jack with the previously mentioned "Big Endian" patch
+* patching Jackd with the MMAP_COMPLEX patch (see the ice1712 page)
+* patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
+* define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc
+ file
+* start jackd with this device
+
+I had no success in testing this for now, but this may be due to my OS
+configuration. If you have any success with this kind of setup, please
+drop me an email.
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 68eeebc17ff..1faf76383ba 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -1172,7 +1172,7 @@
}
/* PCI IDs */
- static struct pci_device_id snd_mychip_ids[] = {
+ static struct pci_device_id snd_mychip_ids[] __devinitdata = {
{ PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
....
@@ -1565,7 +1565,7 @@
<informalexample>
<programlisting>
<![CDATA[
- static struct pci_device_id snd_mychip_ids[] = {
+ static struct pci_device_id snd_mychip_ids[] __devinitdata = {
{ PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
....
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1dbf6ddb300..08b7cc900ca 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -150,8 +150,6 @@ config ARCH_IOP3XX
config ARCH_IXP4XX
bool "IXP4xx-based"
- select DMABOUNCE
- select PCI
help
Support for Intel's IXP4XX (XScale) family of processors.
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 0af3772efcb..ace3fb5835d 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -38,10 +38,10 @@ static void icedcc_putc(int ch)
if (--i < 0)
return;
- asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
+ asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
} while (status & 2);
- asm("mcr p15, 0, %0, c1, c0, 0" : : "r" (ch));
+ asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
}
#define putc(ch) icedcc_putc(ch)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index b324dcac1c5..45fdf4a51a2 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -95,5 +95,11 @@ int main(void)
DEFINE(SYS_ERROR0, 0x9f0000);
BLANK();
DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
+ DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
+ DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
+ DEFINE(MACHINFO_PHYSIO, offsetof(struct machine_desc, phys_io));
+ DEFINE(MACHINFO_PGOFFIO, offsetof(struct machine_desc, io_pg_offst));
+ DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
+ DEFINE(PROCINFO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mmu_flags));
return 0;
}
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 0bea6586405..adf62e5eaad 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -20,12 +20,10 @@
#include <asm/mach-types.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
+#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/system.h>
-#define PROCINFO_INITFUNC 12
-#define MACHINFO_TYPE 0
-
/*
* Kernel startup entry point.
* ---------------------------
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 04b66a9328e..04f7344e356 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -24,14 +24,6 @@
#include <asm/thread_info.h>
#include <asm/system.h>
-#define PROCINFO_MMUFLAGS 8
-#define PROCINFO_INITFUNC 12
-
-#define MACHINFO_TYPE 0
-#define MACHINFO_PHYSIO 4
-#define MACHINFO_PGOFFIO 8
-#define MACHINFO_NAME 12
-
#define KERNEL_RAM_ADDR (PAGE_OFFSET + TEXT_OFFSET)
/*
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
index dc5fa8e5ebe..83f57da3184 100644
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -79,7 +79,12 @@ static void __init aaed2000_init(void)
}
static struct map_desc aaed2000_io_desc[] __initdata = {
- { EXT_GPIO_VBASE, EXT_GPIO_PBASE, EXT_GPIO_LENGTH, MT_DEVICE }, /* Ext GPIO */
+ {
+ .virtual = EXT_GPIO_VBASE,
+ .pfn = __phys_to_pfn(EXT_GPIO_PBASE),
+ .length = EXT_GPIO_LENGTH,
+ .type = MT_DEVICE
+ },
};
static void __init aaed2000_map_io(void)
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
index dce4815cf53..65be5efd633 100644
--- a/arch/arm/mach-aaec2000/core.c
+++ b/arch/arm/mach-aaec2000/core.c
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/signal.h>
-#include <linux/amba/bus.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -50,12 +49,12 @@
static struct map_desc standard_io_desc[] __initdata = {
{
.virtual = VIO_APB_BASE,
- .physical = __phys_to_pfn(PIO_APB_BASE),
+ .pfn = __phys_to_pfn(PIO_APB_BASE),
.length = IO_APB_LENGTH,
.type = MT_DEVICE
}, {
.virtual = VIO_AHB_BASE,
- .physical = __phys_to_pfn(PIO_AHB_BASE),
+ .pfn = __phys_to_pfn(PIO_AHB_BASE),
.length = IO_AHB_LENGTH,
.type = MT_DEVICE
}
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
index b6029a95f19..59501b57316 100644
--- a/arch/arm/mach-aaec2000/core.h
+++ b/arch/arm/mach-aaec2000/core.h
@@ -9,6 +9,7 @@
*
*/
+#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
struct sys_timer;
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 9d8331be2b5..12ea58a3b84 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -195,56 +195,6 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
}
EXPORT_SYMBOL(imx_set_mmc_info);
-static struct resource imx_uart1_resources[] = {
- [0] = {
- .start = 0x00206000,
- .end = 0x002060FF,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (UART1_MINT_RX),
- .end = (UART1_MINT_RX),
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = (UART1_MINT_TX),
- .end = (UART1_MINT_TX),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device imx_uart1_device = {
- .name = "imx-uart",
- .id = 0,
- .num_resources = ARRAY_SIZE(imx_uart1_resources),
- .resource = imx_uart1_resources,
-};
-
-static struct resource imx_uart2_resources[] = {
- [0] = {
- .start = 0x00207000,
- .end = 0x002070FF,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = (UART2_MINT_RX),
- .end = (UART2_MINT_RX),
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = (UART2_MINT_TX),
- .end = (UART2_MINT_TX),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device imx_uart2_device = {
- .name = "imx-uart",
- .id = 1,
- .num_resources = ARRAY_SIZE(imx_uart2_resources),
- .resource = imx_uart2_resources,
-};
-
static struct imxfb_mach_info imx_fb_info;
void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
@@ -283,8 +233,6 @@ static struct platform_device imxfb_device = {
static struct platform_device *devices[] __initdata = {
&imx_mmc_device,
&imxfb_device,
- &imx_uart1_device,
- &imx_uart2_device,
};
static struct map_desc imx_io_desc[] __initdata = {
diff --git a/arch/arm/mach-imx/mx1ads.c b/arch/arm/mach-imx/mx1ads.c
index e34d0df90ae..da893c80d47 100644
--- a/arch/arm/mach-imx/mx1ads.c
+++ b/arch/arm/mach-imx/mx1ads.c
@@ -26,6 +26,7 @@
#include <asm/mach/arch.h>
#include <asm/arch/mmc.h>
+#include <asm/arch/imx-uart.h>
#include <linux/interrupt.h>
#include "generic.h"
@@ -48,8 +49,70 @@ static struct platform_device cs89x0_device = {
.resource = cs89x0_resources,
};
+static struct imxuart_platform_data uart_pdata = {
+ .flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct resource imx_uart1_resources[] = {
+ [0] = {
+ .start = 0x00206000,
+ .end = 0x002060FF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = (UART1_MINT_RX),
+ .end = (UART1_MINT_RX),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = (UART1_MINT_TX),
+ .end = (UART1_MINT_TX),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device imx_uart1_device = {
+ .name = "imx-uart",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(imx_uart1_resources),
+ .resource = imx_uart1_resources,
+ .dev = {
+ .platform_data = &uart_pdata,
+ }
+};
+
+static struct resource imx_uart2_resources[] = {
+ [0] = {
+ .start = 0x00207000,
+ .end = 0x002070FF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = (UART2_MINT_RX),
+ .end = (UART2_MINT_RX),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = (UART2_MINT_TX),
+ .end = (UART2_MINT_TX),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device imx_uart2_device = {
+ .name = "imx-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(imx_uart2_resources),
+ .resource = imx_uart2_resources,
+ .dev = {
+ .platform_data = &uart_pdata,
+ }
+};
+
static struct platform_device *devices[] __initdata = {
&cs89x0_device,
+ &imx_uart1_device,
+ &imx_uart2_device,
};
#ifdef CONFIG_MMC_IMX
@@ -75,6 +138,17 @@ mx1ads_init(void)
imx_gpio_mode(GPIO_PORTB | GPIO_GIUS | GPIO_IN | 20);
imx_set_mmc_info(&mx1ads_mmc_info);
#endif
+
+ imx_gpio_mode(PC9_PF_UART1_CTS);
+ imx_gpio_mode(PC10_PF_UART1_RTS);
+ imx_gpio_mode(PC11_PF_UART1_TXD);
+ imx_gpio_mode(PC12_PF_UART1_RXD);
+
+ imx_gpio_mode(PB28_PF_UART2_CTS);
+ imx_gpio_mode(PB29_PF_UART2_RTS);
+ imx_gpio_mode(PB30_PF_UART2_TXD);
+ imx_gpio_mode(PB31_PF_UART2_RXD);
+
platform_add_devices(devices, ARRAY_SIZE(devices));
}
@@ -87,7 +161,7 @@ mx1ads_map_io(void)
MACHINE_START(MX1ADS, "Motorola MX1ADS")
/* Maintainer: Sascha Hauer, Pengutronix */
.phys_io = 0x00200000,
- .io_pg_offst = ((0xe0200000) >> 18) & 0xfffc,
+ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
.boot_params = 0x08000100,
.map_io = mx1ads_map_io,
.init_irq = imx_init_irq,
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 5bf50a2a737..2a39f9e481a 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -11,6 +11,7 @@ comment "IXP4xx Platforms"
config MACH_NSLU2
bool
prompt "Linksys NSLU2"
+ select PCI
help
Say 'Y' here if you want your kernel to support Linksys's
NSLU2 NAS device. For more information on this platform,
@@ -18,6 +19,7 @@ config MACH_NSLU2
config ARCH_AVILA
bool "Avila"
+ select PCI
help
Say 'Y' here if you want your kernel to support the Gateworks
Avila Network Platform. For more information on this platform,
@@ -25,6 +27,7 @@ config ARCH_AVILA
config ARCH_ADI_COYOTE
bool "Coyote"
+ select PCI
help
Say 'Y' here if you want your kernel to support the ADI
Engineering Coyote Gateway Reference Platform. For more
@@ -32,6 +35,7 @@ config ARCH_ADI_COYOTE
config ARCH_IXDP425
bool "IXDP425"
+ select PCI
help
Say 'Y' here if you want your kernel to support Intel's
IXDP425 Development Platform (Also known as Richfield).
@@ -39,6 +43,7 @@ config ARCH_IXDP425
config MACH_IXDPG425
bool "IXDPG425"
+ select PCI
help
Say 'Y' here if you want your kernel to support Intel's
IXDPG425 Development Platform (Also known as Montajade).
@@ -46,6 +51,7 @@ config MACH_IXDPG425
config MACH_IXDP465
bool "IXDP465"
+ select PCI
help
Say 'Y' here if you want your kernel to support Intel's
IXDP465 Development Platform (Also known as BMP).
@@ -72,6 +78,7 @@ config ARCH_PRPMC1100
config MACH_NAS100D
bool
prompt "NAS100D"
+ select PCI
help
Say 'Y' here if you want your kernel to support Iomega's
NAS 100d device. For more information on this platform,
@@ -96,6 +103,7 @@ config CPU_IXP46X
config MACH_GTWX5715
bool "Gemtek WX5715 (Linksys WRV54G)"
depends on ARCH_IXP4XX
+ select PCI
help
This board is currently inside the Linksys WRV54G Gateways.
@@ -110,11 +118,16 @@ config MACH_GTWX5715
"High Speed" UART is n/c (as far as I can tell)
20 Pin ARM/Xscale JTAG interface on J2
-
comment "IXP4xx Options"
+config DMABOUNCE
+ bool
+ default y
+ depends on PCI
+
config IXP4XX_INDIRECT_PCI
bool "Use indirect PCI memory access"
+ depends on PCI
help
IXP4xx provides two methods of accessing PCI memory space:
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 0471044fa17..5a4aaa0e0a0 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -2,8 +2,9 @@
# Makefile for the linux kernel.
#
-obj-y += common.o common-pci.o
+obj-y += common.o
+obj-$(CONFIG_PCI) += common-pci.o
obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o ixdp425-setup.o
obj-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o coyote-setup.o
obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o coyote-setup.o
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 458112b21e2..7d8c85486c6 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -45,23 +45,16 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
local_irq_save(flags);
- /* try grabbing a DMA channel with the requested priority */
- for (i = prio; i < prio + PXA_DMA_NBCH(prio); i++) {
- if (!dma_channels[i].name) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- /* requested prio group is full, try hier priorities */
- for (i = prio-1; i >= 0; i--) {
+ do {
+ /* try grabbing a DMA channel with the requested priority */
+ pxa_for_each_dma_prio (i, prio) {
if (!dma_channels[i].name) {
found = 1;
break;
}
}
- }
+ /* if requested prio group is full, try a hier priority */
+ } while (!found && prio--);
if (found) {
DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index c131a5201b5..b3a56024182 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -199,10 +199,26 @@ static void sa1100_unmask_irq(unsigned int irq)
ICMR |= (1 << irq);
}
+/*
+ * Apart form GPIOs, only the RTC alarm can be a wakeup event.
+ */
+static int sa1100_set_wake(unsigned int irq, unsigned int on)
+{
+ if (irq == IRQ_RTCAlrm) {
+ if (on)
+ PWER |= PWER_RTC;
+ else
+ PWER &= ~PWER_RTC;
+ return 0;
+ }
+ return -EINVAL;
+}
+
static struct irqchip sa1100_normal_chip = {
.ack = sa1100_mask_irq,
.mask = sa1100_mask_irq,
.unmask = sa1100_unmask_irq,
+ .set_wake = sa1100_set_wake,
};
static struct resource irq_resource = {
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 37ff8145b5b..03486be0419 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -245,7 +245,7 @@ void VFP9_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
*/
barrier();
trigger = fmrx(FPINST2);
- fpscr = fmrx(FPSCR);
+ orig_fpscr = fpscr = fmrx(FPSCR);
emulate:
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 049a2558379..40e5aba3ad3 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -215,7 +215,7 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
{
struct acpi_table_madt *madt = NULL;
- if (!phys_addr || !size || !cpu_has_apic)
+ if (!phys_addr || !size)
return -EINVAL;
madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
@@ -1102,9 +1102,6 @@ int __init acpi_boot_table_init(void)
dmi_check_system(acpi_dmi_table);
#endif
- if (!cpu_has_apic)
- return -ENODEV;
-
/*
* If acpi_disabled, bail out
* One exception: acpi=ht continues far enough to enumerate LAPICs
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 254cee9f0b7..013b85df18c 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -757,10 +757,6 @@ static int __init apic_set_verbosity(char *str)
apic_verbosity = APIC_DEBUG;
else if (strcmp("verbose", str) == 0)
apic_verbosity = APIC_VERBOSE;
- else
- printk(KERN_WARNING "APIC Verbosity level %s not recognised"
- " use apic=verbose or apic=debug\n", str);
-
return 1;
}
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 506462ef36a..fd7eaf7866e 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -671,7 +671,7 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
if (unlikely(current->audit_context)) {
if (entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
+ audit_syscall_exit(AUDITSC_RESULT(regs->eax),
regs->eax);
/* Debug traps, when using PTRACE_SINGLESTEP, must be sent only
* on the syscall exit path. Normally, when TIF_SYSCALL_AUDIT is
@@ -720,14 +720,13 @@ int do_syscall_trace(struct pt_regs *regs, int entryexit)
ret = is_sysemu;
out:
if (unlikely(current->audit_context) && !entryexit)
- audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
+ audit_syscall_entry(AUDIT_ARCH_I386, regs->orig_eax,
regs->ebx, regs->ecx, regs->edx, regs->esi);
if (ret == 0)
return 0;
regs->orig_eax = -1; /* force skip of syscall restarting */
if (unlikely(current->audit_context))
- audit_syscall_exit(current, AUDITSC_RESULT(regs->eax),
- regs->eax);
+ audit_syscall_exit(AUDITSC_RESULT(regs->eax), regs->eax);
return 1;
}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 80cb3b2d099..d77e89ac0d5 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -970,8 +970,10 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
* not-overlapping, which is the case
*/
int __init
-e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
+e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
{
+ u64 start = s;
+ u64 end = e;
int i;
for (i = 0; i < e820.nr_map; i++) {
struct e820entry *ei = &e820.map[i];
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 5e41ee29c8c..f1187ddb0d0 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -279,7 +279,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{
struct cpufreq_freqs *freq = data;
- if (val != CPUFREQ_RESUMECHANGE)
+ if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
write_seqlock_irq(&xtime_lock);
if (!ref_freq) {
if (!freq->old){
@@ -312,7 +312,7 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
}
end:
- if (val != CPUFREQ_RESUMECHANGE)
+ if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
write_sequnlock_irq(&xtime_lock);
return 0;
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index aee14fafd13..00e0118e717 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -312,7 +312,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
/*call audit_syscall_exit since we do not exit via the normal paths */
if (unlikely(current->audit_context))
- audit_syscall_exit(current, AUDITSC_RESULT(eax), eax);
+ audit_syscall_exit(AUDITSC_RESULT(eax), eax);
__asm__ __volatile__(
"movl %0,%%esp\n\t"
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 9887c8787e7..e61e15e28d8 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1644,7 +1644,7 @@ syscall_trace_enter (long arg0, long arg1, long arg2, long arg3,
arch = AUDIT_ARCH_IA64;
}
- audit_syscall_entry(current, arch, syscall, arg0, arg1, arg2, arg3);
+ audit_syscall_entry(arch, syscall, arg0, arg1, arg2, arg3);
}
}
@@ -1662,7 +1662,7 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
if (success != AUDITSC_SUCCESS)
result = -result;
- audit_syscall_exit(current, success, result);
+ audit_syscall_exit(success, result);
}
if (test_thread_flag(TIF_SYSCALL_TRACE)
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f3106d0771b..9b4733c1239 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -483,7 +483,7 @@ static inline int audit_arch(void)
asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
{
if (unlikely(current->audit_context) && entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->regs[2]),
+ audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
regs->regs[2]);
if (!(current->ptrace & PT_PTRACED))
@@ -507,7 +507,7 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit)
}
out:
if (unlikely(current->audit_context) && !entryexit)
- audit_syscall_entry(current, audit_arch(), regs->regs[2],
+ audit_syscall_entry(audit_arch(), regs->regs[2],
regs->regs[4], regs->regs[5],
regs->regs[6], regs->regs[7]);
}
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index fe22e54ab2b..dbe421dc3c1 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -9,6 +9,7 @@ CONFIG_PPC_MERGE=y
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_PPC=y
CONFIG_EARLY_PRINTK=y
@@ -55,6 +56,7 @@ CONFIG_SYSCTL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
@@ -69,10 +71,6 @@ CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
@@ -84,7 +82,6 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
@@ -93,6 +90,7 @@ CONFIG_STOP_MACHINE=y
#
# Block layer
#
+# CONFIG_BLK_DEV_IO_TRACE is not set
#
# IO Schedulers
@@ -126,6 +124,7 @@ CONFIG_RTAS_FLASH=y
CONFIG_MMIO_NVRAM=y
CONFIG_CELL_IIC=y
# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_WANT_EARLY_SERIAL is not set
@@ -167,7 +166,6 @@ CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
# CONFIG_MEMORY_HOTPLUG is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_MIGRATION=y
# CONFIG_PPC_64K_PAGES is not set
CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
@@ -184,7 +182,6 @@ CONFIG_GENERIC_ISA_DMA=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
# CONFIG_PCI_DEBUG is not set
#
@@ -226,6 +223,7 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
@@ -242,6 +240,7 @@ CONFIG_IPV6=y
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
CONFIG_INET6_TUNNEL=m
CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
@@ -632,6 +631,7 @@ CONFIG_SERIAL_NONSTANDARD=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -717,7 +717,6 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -736,9 +735,7 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -766,10 +763,6 @@ CONFIG_I2C_ALGOBIT=y
#
#
-# Multimedia Capabilities Port drivers
-#
-
-#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -818,6 +811,19 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# CONFIG_MMC is not set
#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
# InfiniBand support
#
CONFIG_INFINIBAND=y
@@ -834,6 +840,11 @@ CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
#
#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -889,7 +900,6 @@ CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
# CONFIG_CONFIGFS_FS is not set
#
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 39e348a3ade..3f7182db9ed 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -57,6 +57,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
+#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
+ PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
@@ -263,6 +265,20 @@ struct cpu_spec cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power5+",
},
+ { /* Power6 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x003e0000,
+ .cpu_name = "POWER6",
+ .cpu_features = CPU_FTRS_POWER6,
+ .cpu_user_features = COMMON_USER_POWER6,
+ .icache_bsize = 128,
+ .dcache_bsize = 128,
+ .num_pmcs = 6,
+ .cpu_setup = __setup_cpu_power4,
+ .oprofile_cpu_type = "ppc64/power6",
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .platform = "power6",
+ },
{ /* Cell Broadband Engine */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00700000,
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 856ef1a832b..f78866367b7 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -90,15 +90,15 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
- kprobe_opcode_t insn = *p->ainsn.insn;
-
regs->msr |= MSR_SE;
- /* single step inline if it is a trap variant */
- if (is_trap(insn))
- regs->nip = (unsigned long)p->addr;
- else
- regs->nip = (unsigned long)p->ainsn.insn;
+ /*
+ * On powerpc we should single step on the original
+ * instruction even if the probed insn is a trap
+ * variant as values in regs could play a part in
+ * if the trap is taken or not
+ */
+ regs->nip = (unsigned long)p->ainsn.insn;
}
static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 928b8581fcb..ba34001fca8 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -191,11 +191,19 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
(void *)hdr
+ sechdrs[sechdrs[i].sh_link].sh_offset);
}
- if (!me->arch.stubs_section || !me->arch.toc_section) {
- printk("%s: doesn't contain .toc or .stubs.\n", me->name);
+
+ if (!me->arch.stubs_section) {
+ printk("%s: doesn't contain .stubs.\n", me->name);
return -ENOEXEC;
}
+ /* If we don't have a .toc, just use .stubs. We need to set r2
+ to some reasonable value in case the module calls out to
+ other functions via a stub, or if a function pointer escapes
+ the module by some means. */
+ if (!me->arch.toc_section)
+ me->arch.toc_section = me->arch.stubs_section;
+
/* Override the stubs size */
sechdrs[me->arch.stubs_section].sh_size = get_stubs_size(hdr, sechdrs);
return 0;
@@ -342,7 +350,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
break;
case R_PPC64_TOC16:
- /* Subtact TOC pointer */
+ /* Subtract TOC pointer */
value -= my_r2(sechdrs, me);
if (value + 0x8000 > 0xffff) {
printk("%s: bad TOC16 relocation (%lu)\n",
@@ -355,7 +363,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
break;
case R_PPC64_TOC16_DS:
- /* Subtact TOC pointer */
+ /* Subtract TOC pointer */
value -= my_r2(sechdrs, me);
if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
printk("%s: bad TOC16_DS relocation (%lu)\n",
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 1cb69e8fb0b..9a07f97f071 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -885,6 +885,74 @@ void __init unflatten_device_tree(void)
DBG(" <- unflatten_device_tree()\n");
}
+/*
+ * ibm,pa-features is a per-cpu property that contains a string of
+ * attribute descriptors, each of which has a 2 byte header plus up
+ * to 254 bytes worth of processor attribute bits. First header
+ * byte specifies the number of bytes following the header.
+ * Second header byte is an "attribute-specifier" type, of which
+ * zero is the only currently-defined value.
+ * Implementation: Pass in the byte and bit offset for the feature
+ * that we are interested in. The function will return -1 if the
+ * pa-features property is missing, or a 1/0 to indicate if the feature
+ * is supported/not supported. Note that the bit numbers are
+ * big-endian to match the definition in PAPR.
+ */
+static struct ibm_pa_feature {
+ unsigned long cpu_features; /* CPU_FTR_xxx bit */
+ unsigned int cpu_user_ftrs; /* PPC_FEATURE_xxx bit */
+ unsigned char pabyte; /* byte number in ibm,pa-features */
+ unsigned char pabit; /* bit number (big-endian) */
+ unsigned char invert; /* if 1, pa bit set => clear feature */
+} ibm_pa_features[] __initdata = {
+ {0, PPC_FEATURE_HAS_MMU, 0, 0, 0},
+ {0, PPC_FEATURE_HAS_FPU, 0, 1, 0},
+ {CPU_FTR_SLB, 0, 0, 2, 0},
+ {CPU_FTR_CTRL, 0, 0, 3, 0},
+ {CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
+ {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
+ {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
+};
+
+static void __init check_cpu_pa_features(unsigned long node)
+{
+ unsigned char *pa_ftrs;
+ unsigned long len, tablelen, i, bit;
+
+ pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
+ if (pa_ftrs == NULL)
+ return;
+
+ /* find descriptor with type == 0 */
+ for (;;) {
+ if (tablelen < 3)
+ return;
+ len = 2 + pa_ftrs[0];
+ if (tablelen < len)
+ return; /* descriptor 0 not found */
+ if (pa_ftrs[1] == 0)
+ break;
+ tablelen -= len;
+ pa_ftrs += len;
+ }
+
+ /* loop over bits we know about */
+ for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) {
+ struct ibm_pa_feature *fp = &ibm_pa_features[i];
+
+ if (fp->pabyte >= pa_ftrs[0])
+ continue;
+ bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
+ if (bit ^ fp->invert) {
+ cur_cpu_spec->cpu_features |= fp->cpu_features;
+ cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
+ } else {
+ cur_cpu_spec->cpu_features &= ~fp->cpu_features;
+ cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs;
+ }
+ }
+}
+
static int __init early_init_dt_scan_cpus(unsigned long node,
const char *uname, int depth,
void *data)
@@ -969,6 +1037,8 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
}
#endif /* CONFIG_ALTIVEC */
+ check_cpu_pa_features(node);
+
#ifdef CONFIG_PPC_PSERIES
if (nthreads > 1)
cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 7e4d54821a0..078fb553354 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -636,10 +636,96 @@ static void __init early_cmdline_parse(void)
#ifdef CONFIG_PPC_PSERIES
/*
- * To tell the firmware what our capabilities are, we have to pass
- * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
- * that contain structures that contain the actual values.
+ * There are two methods for telling firmware what our capabilities are.
+ * Newer machines have an "ibm,client-architecture-support" method on the
+ * root node. For older machines, we have to call the "process-elf-header"
+ * method in the /packages/elf-loader node, passing it a fake 32-bit
+ * ELF header containing a couple of PT_NOTE sections that contain
+ * structures that contain various information.
*/
+
+/*
+ * New method - extensible architecture description vector.
+ *
+ * Because the description vector contains a mix of byte and word
+ * values, we declare it as an unsigned char array, and use this
+ * macro to put word values in.
+ */
+#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
+ ((x) >> 8) & 0xff, (x) & 0xff
+
+/* Option vector bits - generic bits in byte 1 */
+#define OV_IGNORE 0x80 /* ignore this vector */
+#define OV_CESSATION_POLICY 0x40 /* halt if unsupported option present*/
+
+/* Option vector 1: processor architectures supported */
+#define OV1_PPC_2_00 0x80 /* set if we support PowerPC 2.00 */
+#define OV1_PPC_2_01 0x40 /* set if we support PowerPC 2.01 */
+#define OV1_PPC_2_02 0x20 /* set if we support PowerPC 2.02 */
+#define OV1_PPC_2_03 0x10 /* set if we support PowerPC 2.03 */
+#define OV1_PPC_2_04 0x08 /* set if we support PowerPC 2.04 */
+#define OV1_PPC_2_05 0x04 /* set if we support PowerPC 2.05 */
+
+/* Option vector 2: Open Firmware options supported */
+#define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */
+
+/* Option vector 3: processor options supported */
+#define OV3_FP 0x80 /* floating point */
+#define OV3_VMX 0x40 /* VMX/Altivec */
+
+/* Option vector 5: PAPR/OF options supported */
+#define OV5_LPAR 0x80 /* logical partitioning supported */
+#define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */
+/* ibm,dynamic-reconfiguration-memory property supported */
+#define OV5_DRCONF_MEMORY 0x20
+#define OV5_LARGE_PAGES 0x10 /* large pages supported */
+
+/*
+ * The architecture vector has an array of PVR mask/value pairs,
+ * followed by # option vectors - 1, followed by the option vectors.
+ */
+static unsigned char ibm_architecture_vec[] = {
+ W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
+ W(0xffff0000), W(0x003e0000), /* POWER6 */
+ W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
+ 5 - 1, /* 5 option vectors */
+
+ /* option vector 1: processor architectures supported */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
+ OV1_PPC_2_04 | OV1_PPC_2_05,
+
+ /* option vector 2: Open Firmware options supported */
+ 34 - 1, /* length */
+ OV2_REAL_MODE,
+ 0, 0,
+ W(0xffffffff), /* real_base */
+ W(0xffffffff), /* real_size */
+ W(0xffffffff), /* virt_base */
+ W(0xffffffff), /* virt_size */
+ W(0xffffffff), /* load_base */
+ W(64), /* 128MB min RMA */
+ W(0xffffffff), /* full client load */
+ 0, /* min RMA percentage of total RAM */
+ 48, /* max log_2(hash table size) */
+
+ /* option vector 3: processor options supported */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV3_FP | OV3_VMX,
+
+ /* option vector 4: IBM PAPR implementation */
+ 2 - 1, /* length */
+ 0, /* don't halt */
+
+ /* option vector 5: PAPR/OF options */
+ 3 - 1, /* length */
+ 0, /* don't ignore, don't halt */
+ OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
+};
+
+/* Old method - ELF header with PT_NOTE sections */
static struct fake_elf {
Elf32_Ehdr elfhdr;
Elf32_Phdr phdr[2];
@@ -728,8 +814,26 @@ static struct fake_elf {
static void __init prom_send_capabilities(void)
{
- ihandle elfloader;
+ ihandle elfloader, root;
+ prom_arg_t ret;
+
+ root = call_prom("open", 1, 1, ADDR("/"));
+ if (root != 0) {
+ /* try calling the ibm,client-architecture-support method */
+ if (call_prom_ret("call-method", 3, 2, &ret,
+ ADDR("ibm,client-architecture-support"),
+ ADDR(ibm_architecture_vec)) == 0) {
+ /* the call exists... */
+ if (ret)
+ prom_printf("WARNING: ibm,client-architecture"
+ "-support call FAILED!\n");
+ call_prom("close", 1, 0, root);
+ return;
+ }
+ call_prom("close", 1, 0, root);
+ }
+ /* no ibm,client-architecture-support call, try the old way */
elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
if (elfloader == 0) {
prom_printf("couldn't open /packages/elf-loader\n");
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index bcb83574335..4a677d1bd4e 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -538,7 +538,7 @@ void do_syscall_trace_enter(struct pt_regs *regs)
do_syscall_trace();
if (unlikely(current->audit_context))
- audit_syscall_entry(current,
+ audit_syscall_entry(
#ifdef CONFIG_PPC32
AUDIT_ARCH_PPC,
#else
@@ -556,8 +556,7 @@ void do_syscall_trace_leave(struct pt_regs *regs)
#endif
if (unlikely(current->audit_context))
- audit_syscall_exit(current,
- (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+ audit_syscall_exit((regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
regs->result);
if ((test_thread_flag(TIF_SYSCALL_TRACE)
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 1d93e73a700..684ab1d49c6 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -516,3 +516,11 @@ void probe_machine(void)
printk(KERN_INFO "Using %s machine description\n", ppc_md.name);
}
+
+int check_legacy_ioport(unsigned long base_port)
+{
+ if (ppc_md.check_legacy_ioport == NULL)
+ return 0;
+ return ppc_md.check_legacy_ioport(base_port);
+}
+EXPORT_SYMBOL(check_legacy_ioport);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 13e91c4d70a..4467c49903b 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -594,14 +594,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
printk("[terminate]%04x %s\n", src, msg);
}
-int check_legacy_ioport(unsigned long base_port)
-{
- if (ppc_md.check_legacy_ioport == NULL)
- return 0;
- return ppc_md.check_legacy_ioport(base_port);
-}
-EXPORT_SYMBOL(check_legacy_ioport);
-
void cpu_die(void)
{
if (ppc_md.cpu_die)
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index ed737cacf92..5bc2585c803 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -322,13 +322,31 @@ static void register_nodes(void)
}
}
}
+
+int sysfs_add_device_to_node(struct sys_device *dev, int nid)
+{
+ struct node *node = &node_devices[nid];
+ return sysfs_create_link(&node->sysdev.kobj, &dev->kobj,
+ kobject_name(&dev->kobj));
+}
+
+void sysfs_remove_device_from_node(struct sys_device *dev, int nid)
+{
+ struct node *node = &node_devices[nid];
+ sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj));
+}
+
#else
static void register_nodes(void)
{
return;
}
+
#endif
+EXPORT_SYMBOL_GPL(sysfs_add_device_to_node);
+EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node);
+
/* Only valid if CPU is present. */
static ssize_t show_physical_id(struct sys_device *dev, char *buf)
{
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 0b98eea73c5..cf56a1d499f 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -325,6 +325,19 @@ SYSCALL(unshare)
SYSCALL(splice)
SYSCALL(tee)
SYSCALL(vmsplice)
+COMPAT_SYS(openat)
+SYSCALL(mkdirat)
+SYSCALL(mknodat)
+SYSCALL(fchownat)
+COMPAT_SYS(futimesat)
+SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64)
+SYSCALL(unlinkat)
+SYSCALL(renameat)
+SYSCALL(linkat)
+SYSCALL(symlinkat)
+SYSCALL(readlinkat)
+SYSCALL(fchmodat)
+SYSCALL(faccessat)
/*
* please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 7370f9f33e2..266b8b2ceac 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -30,13 +30,66 @@
#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
+#ifdef CONFIG_PPC_64K_PAGES
+#define HUGEPTE_INDEX_SIZE (PMD_SHIFT-HPAGE_SHIFT)
+#else
+#define HUGEPTE_INDEX_SIZE (PUD_SHIFT-HPAGE_SHIFT)
+#endif
+#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE)
+#define HUGEPTE_TABLE_SIZE (sizeof(pte_t) << HUGEPTE_INDEX_SIZE)
+
+#define HUGEPD_SHIFT (HPAGE_SHIFT + HUGEPTE_INDEX_SIZE)
+#define HUGEPD_SIZE (1UL << HUGEPD_SHIFT)
+#define HUGEPD_MASK (~(HUGEPD_SIZE-1))
+
+#define huge_pgtable_cache (pgtable_cache[HUGEPTE_CACHE_NUM])
+
+/* Flag to mark huge PD pointers. This means pmd_bad() and pud_bad()
+ * will choke on pointers to hugepte tables, which is handy for
+ * catching screwups early. */
+#define HUGEPD_OK 0x1
+
+typedef struct { unsigned long pd; } hugepd_t;
+
+#define hugepd_none(hpd) ((hpd).pd == 0)
+
+static inline pte_t *hugepd_page(hugepd_t hpd)
+{
+ BUG_ON(!(hpd.pd & HUGEPD_OK));
+ return (pte_t *)(hpd.pd & ~HUGEPD_OK);
+}
+
+static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr)
+{
+ unsigned long idx = ((addr >> HPAGE_SHIFT) & (PTRS_PER_HUGEPTE-1));
+ pte_t *dir = hugepd_page(*hpdp);
+
+ return dir + idx;
+}
+
+static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
+ unsigned long address)
+{
+ pte_t *new = kmem_cache_alloc(huge_pgtable_cache,
+ GFP_KERNEL|__GFP_REPEAT);
+
+ if (! new)
+ return -ENOMEM;
+
+ spin_lock(&mm->page_table_lock);
+ if (!hugepd_none(*hpdp))
+ kmem_cache_free(huge_pgtable_cache, new);
+ else
+ hpdp->pd = (unsigned long)new | HUGEPD_OK;
+ spin_unlock(&mm->page_table_lock);
+ return 0;
+}
+
/* Modelled after find_linux_pte() */
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pg;
pud_t *pu;
- pmd_t *pm;
- pte_t *pt;
BUG_ON(! in_hugepage_area(mm->context, addr));
@@ -46,26 +99,14 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
if (!pgd_none(*pg)) {
pu = pud_offset(pg, addr);
if (!pud_none(*pu)) {
- pm = pmd_offset(pu, addr);
#ifdef CONFIG_PPC_64K_PAGES
- /* Currently, we use the normal PTE offset within full
- * size PTE pages, thus our huge PTEs are scattered in
- * the PTE page and we do waste some. We may change
- * that in the future, but the current mecanism keeps
- * things much simpler
- */
- if (!pmd_none(*pm)) {
- /* Note: pte_offset_* are all equivalent on
- * ppc64 as we don't have HIGHMEM
- */
- pt = pte_offset_kernel(pm, addr);
- return pt;
- }
-#else /* CONFIG_PPC_64K_PAGES */
- /* On 4k pages, we put huge PTEs in the PMD page */
- pt = (pte_t *)pm;
- return pt;
-#endif /* CONFIG_PPC_64K_PAGES */
+ pmd_t *pm;
+ pm = pmd_offset(pu, addr);
+ if (!pmd_none(*pm))
+ return hugepte_offset((hugepd_t *)pm, addr);
+#else
+ return hugepte_offset((hugepd_t *)pu, addr);
+#endif
}
}
@@ -76,8 +117,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pg;
pud_t *pu;
- pmd_t *pm;
- pte_t *pt;
+ hugepd_t *hpdp = NULL;
BUG_ON(! in_hugepage_area(mm->context, addr));
@@ -87,23 +127,182 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
pu = pud_alloc(mm, pg, addr);
if (pu) {
+#ifdef CONFIG_PPC_64K_PAGES
+ pmd_t *pm;
pm = pmd_alloc(mm, pu, addr);
- if (pm) {
+ if (pm)
+ hpdp = (hugepd_t *)pm;
+#else
+ hpdp = (hugepd_t *)pu;
+#endif
+ }
+
+ if (! hpdp)
+ return NULL;
+
+ if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr))
+ return NULL;
+
+ return hugepte_offset(hpdp, addr);
+}
+
+static void free_hugepte_range(struct mmu_gather *tlb, hugepd_t *hpdp)
+{
+ pte_t *hugepte = hugepd_page(*hpdp);
+
+ hpdp->pd = 0;
+ tlb->need_flush = 1;
+ pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM,
+ HUGEPTE_TABLE_SIZE-1));
+}
+
#ifdef CONFIG_PPC_64K_PAGES
- /* See comment in huge_pte_offset. Note that if we ever
- * want to put the page size in the PMD, we would have
- * to open code our own pte_alloc* function in order
- * to populate and set the size atomically
- */
- pt = pte_alloc_map(mm, pm, addr);
-#else /* CONFIG_PPC_64K_PAGES */
- pt = (pte_t *)pm;
-#endif /* CONFIG_PPC_64K_PAGES */
- return pt;
- }
+static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pmd_t *pmd;
+ unsigned long next;
+ unsigned long start;
+
+ start = addr;
+ pmd = pmd_offset(pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+ if (pmd_none(*pmd))
+ continue;
+ free_hugepte_range(tlb, (hugepd_t *)pmd);
+ } while (pmd++, addr = next, addr != end);
+
+ start &= PUD_MASK;
+ if (start < floor)
+ return;
+ if (ceiling) {
+ ceiling &= PUD_MASK;
+ if (!ceiling)
+ return;
}
+ if (end - 1 > ceiling - 1)
+ return;
- return NULL;
+ pmd = pmd_offset(pud, start);
+ pud_clear(pud);
+ pmd_free_tlb(tlb, pmd);
+}
+#endif
+
+static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pud_t *pud;
+ unsigned long next;
+ unsigned long start;
+
+ start = addr;
+ pud = pud_offset(pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+#ifdef CONFIG_PPC_64K_PAGES
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ hugetlb_free_pmd_range(tlb, pud, addr, next, floor, ceiling);
+#else
+ if (pud_none(*pud))
+ continue;
+ free_hugepte_range(tlb, (hugepd_t *)pud);
+#endif
+ } while (pud++, addr = next, addr != end);
+
+ start &= PGDIR_MASK;
+ if (start < floor)
+ return;
+ if (ceiling) {
+ ceiling &= PGDIR_MASK;
+ if (!ceiling)
+ return;
+ }
+ if (end - 1 > ceiling - 1)
+ return;
+
+ pud = pud_offset(pgd, start);
+ pgd_clear(pgd);
+ pud_free_tlb(tlb, pud);
+}
+
+/*
+ * This function frees user-level page tables of a process.
+ *
+ * Must be called with pagetable lock held.
+ */
+void hugetlb_free_pgd_range(struct mmu_gather **tlb,
+ unsigned long addr, unsigned long end,
+ unsigned long floor, unsigned long ceiling)
+{
+ pgd_t *pgd;
+ unsigned long next;
+ unsigned long start;
+
+ /*
+ * Comments below take from the normal free_pgd_range(). They
+ * apply here too. The tests against HUGEPD_MASK below are
+ * essential, because we *don't* test for this at the bottom
+ * level. Without them we'll attempt to free a hugepte table
+ * when we unmap just part of it, even if there are other
+ * active mappings using it.
+ *
+ * The next few lines have given us lots of grief...
+ *
+ * Why are we testing HUGEPD* at this top level? Because
+ * often there will be no work to do at all, and we'd prefer
+ * not to go all the way down to the bottom just to discover
+ * that.
+ *
+ * Why all these "- 1"s? Because 0 represents both the bottom
+ * of the address space and the top of it (using -1 for the
+ * top wouldn't help much: the masks would do the wrong thing).
+ * The rule is that addr 0 and floor 0 refer to the bottom of
+ * the address space, but end 0 and ceiling 0 refer to the top
+ * Comparisons need to use "end - 1" and "ceiling - 1" (though
+ * that end 0 case should be mythical).
+ *
+ * Wherever addr is brought up or ceiling brought down, we
+ * must be careful to reject "the opposite 0" before it
+ * confuses the subsequent tests. But what about where end is
+ * brought down by HUGEPD_SIZE below? no, end can't go down to
+ * 0 there.
+ *
+ * Whereas we round start (addr) and ceiling down, by different
+ * masks at different levels, in order to test whether a table
+ * now has no other vmas using it, so can be freed, we don't
+ * bother to round floor or end up - the tests don't need that.
+ */
+
+ addr &= HUGEPD_MASK;
+ if (addr < floor) {
+ addr += HUGEPD_SIZE;
+ if (!addr)
+ return;
+ }
+ if (ceiling) {
+ ceiling &= HUGEPD_MASK;
+ if (!ceiling)
+ return;
+ }
+ if (end - 1 > ceiling - 1)
+ end -= HUGEPD_SIZE;
+ if (addr > end - 1)
+ return;
+
+ start = addr;
+ pgd = pgd_offset((*tlb)->mm, addr);
+ do {
+ BUG_ON(! in_hugepage_area((*tlb)->mm->context, addr));
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ hugetlb_free_pud_range(*tlb, pgd, addr, next, floor, ceiling);
+ } while (pgd++, addr = next, addr != end);
}
void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
@@ -841,3 +1040,27 @@ repeat:
out:
return err;
}
+
+static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
+{
+ memset(addr, 0, kmem_cache_size(cache));
+}
+
+static int __init hugetlbpage_init(void)
+{
+ if (!cpu_has_feature(CPU_FTR_16M_PAGE))
+ return -ENODEV;
+
+ huge_pgtable_cache = kmem_cache_create("hugepte_cache",
+ HUGEPTE_TABLE_SIZE,
+ HUGEPTE_TABLE_SIZE,
+ SLAB_HWCACHE_ALIGN |
+ SLAB_MUST_HWCACHE_ALIGN,
+ zero_ctor, NULL);
+ if (! huge_pgtable_cache)
+ panic("hugetlbpage_init(): could not create hugepte cache\n");
+
+ return 0;
+}
+
+module_init(hugetlbpage_init);
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index babebd15bdc..9e30f968c18 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -162,7 +162,14 @@ static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
};
#endif /* CONFIG_PPC_64K_PAGES */
+#ifdef CONFIG_HUGETLB_PAGE
+/* Hugepages need one extra cache, initialized in hugetlbpage.c. We
+ * can't put into the tables above, because HPAGE_SHIFT is not compile
+ * time constant. */
+kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)+1];
+#else
kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
+#endif
void pgtable_cache_init(void)
{
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 0a335f34974..092355f3739 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -194,7 +194,7 @@ static int *of_get_associativity(struct device_node *dev)
/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
* info is found.
*/
-static int of_node_to_nid(struct device_node *device)
+static int of_node_to_nid_single(struct device_node *device)
{
int nid = -1;
unsigned int *tmp;
@@ -216,6 +216,28 @@ out:
return nid;
}
+/* Walk the device tree upwards, looking for an associativity id */
+int of_node_to_nid(struct device_node *device)
+{
+ struct device_node *tmp;
+ int nid = -1;
+
+ of_node_get(device);
+ while (device) {
+ nid = of_node_to_nid_single(device);
+ if (nid != -1)
+ break;
+
+ tmp = device;
+ device = of_get_parent(tmp);
+ of_node_put(tmp);
+ }
+ of_node_put(device);
+
+ return nid;
+}
+EXPORT_SYMBOL_GPL(of_node_to_nid);
+
/*
* In theory, the "ibm,associativity" property may contain multiple
* associativity lists because a resource may be multiply connected
@@ -300,7 +322,7 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu)
goto out;
}
- nid = of_node_to_nid(cpu);
+ nid = of_node_to_nid_single(cpu);
if (nid < 0 || !node_online(nid))
nid = any_online_node(NODE_MASK_ALL);
@@ -393,7 +415,7 @@ static int __init parse_numa_properties(void)
cpu = find_cpu_node(i);
BUG_ON(!cpu);
- nid = of_node_to_nid(cpu);
+ nid = of_node_to_nid_single(cpu);
of_node_put(cpu);
/*
@@ -437,7 +459,7 @@ new_range:
* have associativity properties. If none, then
* everything goes to default_nid.
*/
- nid = of_node_to_nid(memory);
+ nid = of_node_to_nid_single(memory);
if (nid < 0)
nid = default_nid;
node_set_online(nid);
@@ -776,7 +798,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
ha_new_range:
start = read_n_cells(n_mem_addr_cells, &memcell_buf);
size = read_n_cells(n_mem_size_cells, &memcell_buf);
- nid = of_node_to_nid(memory);
+ nid = of_node_to_nid_single(memory);
/* Domains not present at boot default to 0 */
if (nid < 0 || !node_online(nid))
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index c2a3db8edb0..6a02d51086c 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -12,7 +12,8 @@ config SPU_FS
config SPUFS_MMAP
bool
- depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES
+ depends on SPU_FS && SPARSEMEM
+ select MEMORY_HOTPLUG
default y
endmenu
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index dac5d0365fd..6574b22b3cf 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -29,6 +29,8 @@
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/console.h>
+#include <linux/mutex.h>
+#include <linux/memory_hotplug.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -46,6 +48,7 @@
#include <asm/cputable.h>
#include <asm/ppc-pci.h>
#include <asm/irq.h>
+#include <asm/spu.h>
#include "interrupt.h"
#include "iommu.h"
@@ -69,77 +72,6 @@ static void cell_show_cpuinfo(struct seq_file *m)
of_node_put(root);
}
-#ifdef CONFIG_SPARSEMEM
-static int __init find_spu_node_id(struct device_node *spe)
-{
- unsigned int *id;
-#ifdef CONFIG_NUMA
- struct device_node *cpu;
- cpu = spe->parent->parent;
- id = (unsigned int *)get_property(cpu, "node-id", NULL);
-#else
- id = NULL;
-#endif
- return id ? *id : 0;
-}
-
-static void __init cell_spuprop_present(struct device_node *spe,
- const char *prop, int early)
-{
- struct address_prop {
- unsigned long address;
- unsigned int len;
- } __attribute__((packed)) *p;
- int proplen;
-
- unsigned long start_pfn, end_pfn, pfn;
- int node_id;
-
- p = (void*)get_property(spe, prop, &proplen);
- WARN_ON(proplen != sizeof (*p));
-
- node_id = find_spu_node_id(spe);
-
- start_pfn = p->address >> PAGE_SHIFT;
- end_pfn = (p->address + p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
-
- /* We need to call memory_present *before* the call to sparse_init,
- but we can initialize the page structs only *after* that call.
- Thus, we're being called twice. */
- if (early)
- memory_present(node_id, start_pfn, end_pfn);
- else {
- /* As the pages backing SPU LS and I/O are outside the range
- of regular memory, their page structs were not initialized
- by free_area_init. Do it here instead. */
- for (pfn = start_pfn; pfn < end_pfn; pfn++) {
- struct page *page = pfn_to_page(pfn);
- set_page_links(page, ZONE_DMA, node_id, pfn);
- init_page_count(page);
- reset_page_mapcount(page);
- SetPageReserved(page);
- INIT_LIST_HEAD(&page->lru);
- }
- }
-}
-
-static void __init cell_spumem_init(int early)
-{
- struct device_node *node;
- for (node = of_find_node_by_type(NULL, "spe");
- node; node = of_find_node_by_type(node, "spe")) {
- cell_spuprop_present(node, "local-store", early);
- cell_spuprop_present(node, "problem", early);
- cell_spuprop_present(node, "priv1", early);
- cell_spuprop_present(node, "priv2", early);
- }
-}
-#else
-static void __init cell_spumem_init(int early)
-{
-}
-#endif
-
static void cell_progress(char *s, unsigned short hex)
{
printk("*** %04x : %s\n", hex, s ? s : "");
@@ -172,8 +104,6 @@ static void __init cell_setup_arch(void)
#endif
mmio_nvram_init();
-
- cell_spumem_init(0);
}
/*
@@ -189,8 +119,6 @@ static void __init cell_init_early(void)
ppc64_interrupt_controller = IC_CELL_PIC;
- cell_spumem_init(1);
-
DBG(" <- cell_init_early()\n");
}
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 269dda4fd0b..ad141fe8d52 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -306,19 +306,19 @@ spu_request_irqs(struct spu *spu)
snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0", spu->number);
ret = request_irq(irq_base + spu->isrc,
- spu_irq_class_0, 0, spu->irq_c0, spu);
+ spu_irq_class_0, SA_INTERRUPT, spu->irq_c0, spu);
if (ret)
goto out;
snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1", spu->number);
ret = request_irq(irq_base + IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_1, 0, spu->irq_c1, spu);
+ spu_irq_class_1, SA_INTERRUPT, spu->irq_c1, spu);
if (ret)
goto out1;
snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2", spu->number);
ret = request_irq(irq_base + 2*IIC_CLASS_STRIDE + spu->isrc,
- spu_irq_class_2, 0, spu->irq_c2, spu);
+ spu_irq_class_2, SA_INTERRUPT, spu->irq_c2, spu);
if (ret)
goto out2;
goto out;
@@ -487,10 +487,14 @@ int spu_irq_class_1_bottom(struct spu *spu)
ea = spu->dar;
dsisr = spu->dsisr;
if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) {
+ u64 flags;
+
access = (_PAGE_PRESENT | _PAGE_USER);
access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
+ local_irq_save(flags);
if (hash_page(ea, access, 0x300) != 0)
error |= CLASS1_ENABLE_STORAGE_FAULT_INTR;
+ local_irq_restore(flags);
}
if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) {
if ((ret = spu_handle_mm_fault(spu)) != 0)
@@ -516,8 +520,50 @@ void spu_irq_setaffinity(struct spu *spu, int cpu)
}
EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
-static void __iomem * __init map_spe_prop(struct device_node *n,
- const char *name)
+static int __init find_spu_node_id(struct device_node *spe)
+{
+ unsigned int *id;
+ struct device_node *cpu;
+ cpu = spe->parent->parent;
+ id = (unsigned int *)get_property(cpu, "node-id", NULL);
+ return id ? *id : 0;
+}
+
+static int __init cell_spuprop_present(struct spu *spu, struct device_node *spe,
+ const char *prop)
+{
+ static DEFINE_MUTEX(add_spumem_mutex);
+
+ struct address_prop {
+ unsigned long address;
+ unsigned int len;
+ } __attribute__((packed)) *p;
+ int proplen;
+
+ unsigned long start_pfn, nr_pages;
+ struct pglist_data *pgdata;
+ struct zone *zone;
+ int ret;
+
+ p = (void*)get_property(spe, prop, &proplen);
+ WARN_ON(proplen != sizeof (*p));
+
+ start_pfn = p->address >> PAGE_SHIFT;
+ nr_pages = ((unsigned long)p->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ pgdata = NODE_DATA(spu->nid);
+ zone = pgdata->node_zones;
+
+ /* XXX rethink locking here */
+ mutex_lock(&add_spumem_mutex);
+ ret = __add_pages(zone, start_pfn, nr_pages);
+ mutex_unlock(&add_spumem_mutex);
+
+ return ret;
+}
+
+static void __iomem * __init map_spe_prop(struct spu *spu,
+ struct device_node *n, const char *name)
{
struct address_prop {
unsigned long address;
@@ -526,6 +572,8 @@ static void __iomem * __init map_spe_prop(struct device_node *n,
void *p;
int proplen;
+ void* ret = NULL;
+ int err = 0;
p = get_property(n, name, &proplen);
if (proplen != sizeof (struct address_prop))
@@ -533,7 +581,14 @@ static void __iomem * __init map_spe_prop(struct device_node *n,
prop = p;
- return ioremap(prop->address, prop->len);
+ err = cell_spuprop_present(spu, n, name);
+ if (err && (err != -EEXIST))
+ goto out;
+
+ ret = ioremap(prop->address, prop->len);
+
+ out:
+ return ret;
}
static void spu_unmap(struct spu *spu)
@@ -544,44 +599,45 @@ static void spu_unmap(struct spu *spu)
iounmap((u8 __iomem *)spu->local_store);
}
-static int __init spu_map_device(struct spu *spu, struct device_node *spe)
+static int __init spu_map_device(struct spu *spu, struct device_node *node)
{
char *prop;
int ret;
ret = -ENODEV;
- prop = get_property(spe, "isrc", NULL);
+ prop = get_property(node, "isrc", NULL);
if (!prop)
goto out;
spu->isrc = *(unsigned int *)prop;
- spu->name = get_property(spe, "name", NULL);
+ spu->name = get_property(node, "name", NULL);
if (!spu->name)
goto out;
- prop = get_property(spe, "local-store", NULL);
+ prop = get_property(node, "local-store", NULL);
if (!prop)
goto out;
spu->local_store_phys = *(unsigned long *)prop;
/* we use local store as ram, not io memory */
- spu->local_store = (void __force *)map_spe_prop(spe, "local-store");
+ spu->local_store = (void __force *)
+ map_spe_prop(spu, node, "local-store");
if (!spu->local_store)
goto out;
- prop = get_property(spe, "problem", NULL);
+ prop = get_property(node, "problem", NULL);
if (!prop)
goto out_unmap;
spu->problem_phys = *(unsigned long *)prop;
- spu->problem= map_spe_prop(spe, "problem");
+ spu->problem= map_spe_prop(spu, node, "problem");
if (!spu->problem)
goto out_unmap;
- spu->priv1= map_spe_prop(spe, "priv1");
+ spu->priv1= map_spe_prop(spu, node, "priv1");
/* priv1 is not available on a hypervisor */
- spu->priv2= map_spe_prop(spe, "priv2");
+ spu->priv2= map_spe_prop(spu, node, "priv2");
if (!spu->priv2)
goto out_unmap;
ret = 0;
@@ -593,17 +649,6 @@ out:
return ret;
}
-static int __init find_spu_node_id(struct device_node *spe)
-{
- unsigned int *id;
- struct device_node *cpu;
-
- cpu = spe->parent->parent;
- id = (unsigned int *)get_property(cpu, "node-id", NULL);
-
- return id ? *id : 0;
-}
-
static int __init create_spu(struct device_node *spe)
{
struct spu *spu;
@@ -620,6 +665,10 @@ static int __init create_spu(struct device_node *spe)
goto out_free;
spu->node = find_spu_node_id(spe);
+ spu->nid = of_node_to_nid(spe);
+ if (spu->nid == -1)
+ spu->nid = 0;
+
spu->stop_code = 0;
spu->slb_replace = 0;
spu->mm = NULL;
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index b283380a2a1..95b36430aa0 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -319,6 +319,19 @@ void *spu_syscall_table[] = {
[__NR_splice] sys_splice,
[__NR_tee] sys_tee,
[__NR_vmsplice] sys_vmsplice,
+ [__NR_openat] sys_openat,
+ [__NR_mkdirat] sys_mkdirat,
+ [__NR_mknodat] sys_mknodat,
+ [__NR_fchownat] sys_fchownat,
+ [__NR_futimesat] sys_futimesat,
+ [__NR_newfstatat] sys_newfstatat,
+ [__NR_unlinkat] sys_unlinkat,
+ [__NR_renameat] sys_renameat,
+ [__NR_linkat] sys_linkat,
+ [__NR_symlinkat] sys_symlinkat,
+ [__NR_readlinkat] sys_readlinkat,
+ [__NR_fchmodat] sys_fchmodat,
+ [__NR_faccessat] sys_faccessat,
};
long spu_sys_callback(struct spu_syscall_block *s)
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index a1bda6f96fd..40020c65c89 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -118,7 +118,15 @@ int eeh_send_failure_event (struct device_node *dn,
{
unsigned long flags;
struct eeh_event *event;
+ char *location;
+ if (!mem_init_done) {
+ printk(KERN_ERR "EEH: event during early boot not handled\n");
+ location = (char *) get_property(dn, "ibm,loc-code", NULL);
+ printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
+ printk(KERN_ERR "EEH: PCI location = %s\n", location);
+ return 1;
+ }
event = kmalloc(sizeof(*event), GFP_ATOMIC);
if (event == NULL) {
printk (KERN_ERR "EEH: out of memory, event not handled\n");
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index f841972f1fa..554776d4b8a 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -331,7 +331,7 @@ static void __init ocotea_init(void)
void __init platform_init(unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, unsigned long r7)
{
- ibm44x_platform_init(r3, r4, r5, r6, r7);
+ ibm440gx_platform_init(r3, r4, r5, r6, r7);
ppc_md.setup_arch = ocotea_setup_arch;
ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index bc9b94f77e3..e62b75707f7 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -26,11 +26,35 @@
#include <asm/irq.h>
#include <asm/ppc_sys.h>
#include <asm/ppcboot.h>
+#include <linux/fs_uart_pd.h>
#include "pq2ads_pd.h"
static void init_fcc1_ioports(void);
static void init_fcc2_ioports(void);
+static void init_scc1_uart_ioports(void);
+static void init_scc4_uart_ioports(void);
+
+static struct fs_uart_platform_info mpc8272_uart_pdata[] = {
+ [fsid_scc1_uart] = {
+ .init_ioports = init_scc1_uart_ioports,
+ .fs_no = fsid_scc1_uart,
+ .brg = 1,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_scc4_uart] = {
+ .init_ioports = init_scc4_uart_ioports,
+ .fs_no = fsid_scc4_uart,
+ .brg = 4,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+};
static struct fs_mii_bus_info mii_bus_info = {
.method = fsmii_bitbang,
@@ -201,6 +225,55 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev,
}
}
+static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc8272_uart_pdata);
+ int id = fs_uart_id_scc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc8272_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
+static void init_scc1_uart_ioports(void)
+{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+
+ /* SCC1 is only on port D */
+ setbits32(&immap->im_ioport.iop_ppard,0x00000003);
+ clrbits32(&immap->im_ioport.iop_psord,0x00000001);
+ setbits32(&immap->im_ioport.iop_psord,0x00000002);
+ clrbits32(&immap->im_ioport.iop_pdird,0x00000001);
+ setbits32(&immap->im_ioport.iop_pdird,0x00000002);
+
+ /* Wire BRG1 to SCC1 */
+ clrbits32(&immap->im_cpmux.cmx_scr,0x00ffffff);
+
+ iounmap(immap);
+}
+
+static void init_scc4_uart_ioports(void)
+{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+
+ setbits32(&immap->im_ioport.iop_ppard,0x00000600);
+ clrbits32(&immap->im_ioport.iop_psord,0x00000600);
+ clrbits32(&immap->im_ioport.iop_pdird,0x00000200);
+ setbits32(&immap->im_ioport.iop_pdird,0x00000400);
+
+ /* Wire BRG4 to SCC4 */
+ clrbits32(&immap->im_cpmux.cmx_scr,0x000000ff);
+ setbits32(&immap->im_cpmux.cmx_scr,0x0000001b);
+
+ iounmap(immap);
+}
+
static int mpc8272ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
@@ -209,6 +282,10 @@ static int mpc8272ads_platform_notify(struct device *dev)
.rtn = mpc8272ads_fixup_enet_pdata
},
{
+ .bus_id = "fsl-cpm-scc:uart",
+ .rtn = mpc
+ },
+ {
.bus_id = NULL
}
};
@@ -230,7 +307,44 @@ int __init mpc8272ads_init(void)
ppc_sys_device_enable(MPC82xx_CPM_FCC1);
ppc_sys_device_enable(MPC82xx_CPM_FCC2);
+ /* to be ready for console, let's attach pdata here */
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ ppc_sys_device_setfunc(MPC82xx_CPM_SCC1, PPC_SYS_FUNC_UART);
+ ppc_sys_device_enable(MPC82xx_CPM_SCC1);
+
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ ppc_sys_device_setfunc(MPC82xx_CPM_SCC4, PPC_SYS_FUNC_UART);
+ ppc_sys_device_enable(MPC82xx_CPM_SCC4);
+#endif
+
+
return 0;
}
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SCC1 and by 1 assumed SCC4
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SCC4 here*/
+ pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC4];
+ pinfo = &mpc8272<F12>_uart_pdata[1];
+ } else { /*over SCC1*/
+ pdev = &ppc_sys_platform_devices[MPC82xx_CPM_SCC1];
+ pinfo = &mpc8272_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
arch_initcall(mpc8272ads_init);
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index ac8fcc68afe..d919dab6134 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
#include <linux/mii.h>
#include <asm/delay.h>
@@ -37,6 +38,11 @@
extern unsigned char __res[];
+static void setup_fec1_ioports(void);
+static void setup_scc1_ioports(void);
+static void setup_smc1_ioports(void);
+static void setup_smc2_ioports(void);
+
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
@@ -79,6 +85,28 @@ static struct fs_platform_info mpc8xx_scc_pdata = {
.phy_irq = -1,
.bus_info = &scc_mii_bus_info,
+
+};
+
+static struct fs_uart_platform_info mpc866_uart_pdata[] = {
+ [fsid_smc1_uart] = {
+ .brg = 1,
+ .fs_no = fsid_smc1_uart,
+ .init_ioports = setup_smc1_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_smc2_uart] = {
+ .brg = 2,
+ .fs_no = fsid_smc2_uart,
+ .init_ioports = setup_smc2_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
};
void __init board_init(void)
@@ -92,9 +120,12 @@ void __init board_init(void)
printk(KERN_CRIT "Could not remap BCSR1\n");
return;
}
+
#ifdef CONFIG_SERIAL_CPM_SMC1
cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
clrbits32(bcsr_io,(0x80000000 >> 7));
+ cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,(0x80000000 >> 7));
@@ -108,6 +139,8 @@ void __init board_init(void)
cp->cp_simode &= ~(0xe0000000 >> 1);
cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
clrbits32(bcsr_io,(0x80000000 >> 13));
+ cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
clrbits32(bcsr_io,(0x80000000 >> 13));
cp->cp_pbpar &= ~(0x00000c00);
@@ -232,6 +265,74 @@ static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
}
+static void setup_smc1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x000000c0;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+
+ clrbits32(bcsr_io,BCSR1_RS232EN_1);
+ iounmap(bcsr_io);
+
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+
+}
+
+static void setup_smc2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x00000c00;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+
+ clrbits32(bcsr_io,BCSR1_RS232EN_2);
+
+ iounmap(bcsr_io);
+
+#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+#else
+ setbits16(&immap->im_ioport.iop_papar, iobits);
+ clrbits16(&immap->im_ioport.iop_padir, iobits);
+ clrbits16(&immap->im_ioport.iop_paodr, iobits);
+#endif
+
+}
+
+static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc866_uart_pdata);
+
+ int id = fs_uart_id_smc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc866_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
static int mpc866ads_platform_notify(struct device *dev)
{
static const struct platform_notify_dev_map dev_map[] = {
@@ -244,6 +345,10 @@ static int mpc866ads_platform_notify(struct device *dev)
.rtn = mpc866ads_fixup_scc_enet_pdata,
},
{
+ .bus_id = "fsl-cpm-smc:uart",
+ .rtn = mpc866ads_fixup_uart_pdata
+ },
+ {
.bus_id = NULL
}
};
@@ -267,7 +372,42 @@ int __init mpc866ads_init(void)
#endif
ppc_sys_device_enable(MPC8xx_CPM_FEC1);
+/* Since either of the uarts could be used as console, they need to ready */
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC
+ ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+#endif
+
return 0;
}
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SMC1 and by 1 assumed SMC2
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SMC2 here*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+ pinfo = &mpc866_uart_pdata[1];
+ } else { /*over SMC1*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+ pinfo = &mpc866_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
arch_initcall(mpc866ads_init);
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
index 50a99e5f7c6..4b88679cd31 100644
--- a/arch/ppc/platforms/mpc885ads_setup.c
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
#include <linux/mii.h>
#include <asm/delay.h>
@@ -35,9 +36,32 @@
#include <asm/ppc_sys.h>
extern unsigned char __res[];
+static void setup_smc1_ioports(void);
+static void setup_smc2_ioports(void);
static void __init mpc885ads_scc_phy_init(char);
+static struct fs_uart_platform_info mpc885_uart_pdata[] = {
+ [fsid_smc1_uart] = {
+ .brg = 1,
+ .fs_no = fsid_smc1_uart,
+ .init_ioports = setup_smc1_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+ [fsid_smc2_uart] = {
+ .brg = 2,
+ .fs_no = fsid_smc2_uart,
+ .init_ioports = setup_smc2_ioports,
+ .tx_num_fifo = 4,
+ .tx_buf_size = 32,
+ .rx_num_fifo = 4,
+ .rx_buf_size = 32,
+ },
+};
+
static struct fs_mii_bus_info fec_mii_bus_info = {
.method = fsmii_fec,
.id = 0,
@@ -116,6 +140,8 @@ void __init board_init(void)
#ifdef CONFIG_SERIAL_CPM_SMC1
cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
clrbits32(bcsr_io, BCSR1_RS232EN_1);
+ cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,BCSR1_RS232EN_1);
cp->cp_smc[0].smc_smcmr = 0;
@@ -126,6 +152,8 @@ void __init board_init(void)
cp->cp_simode &= ~(0xe0000000 >> 1);
cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
clrbits32(bcsr_io,BCSR1_RS232EN_2);
+ cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
+ cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
#else
setbits32(bcsr_io,BCSR1_RS232EN_2);
cp->cp_smc[1].smc_smcmr = 0;
@@ -343,6 +371,70 @@ static void mpc885ads_scc_phy_init(char phy_addr)
out_be32(&fecp->fec_mii_speed, 0);
}
+static void setup_smc1_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x000000c0;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+ clrbits32(bcsr_io,BCSR1_RS232EN_1);
+ iounmap(bcsr_io);
+
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+}
+
+static void setup_smc2_ioports(void)
+{
+ immap_t *immap = (immap_t *) IMAP_ADDR;
+ unsigned *bcsr_io;
+ unsigned int iobits = 0x00000c00;
+
+ bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+ if (bcsr_io == NULL) {
+ printk(KERN_CRIT "Could not remap BCSR1\n");
+ return;
+ }
+ clrbits32(bcsr_io,BCSR1_RS232EN_2);
+ iounmap(bcsr_io);
+
+#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
+ setbits32(&immap->im_cpm.cp_pbpar, iobits);
+ clrbits32(&immap->im_cpm.cp_pbdir, iobits);
+ clrbits16(&immap->im_cpm.cp_pbodr, iobits);
+#else
+ setbits16(&immap->im_ioport.iop_papar, iobits);
+ clrbits16(&immap->im_ioport.iop_padir, iobits);
+ clrbits16(&immap->im_ioport.iop_paodr, iobits);
+#endif
+}
+
+static void __init mpc885ads_fixup_uart_pdata(struct platform_device *pdev,
+ int idx)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+ int num = ARRAY_SIZE(mpc885_uart_pdata);
+
+ int id = fs_uart_id_smc2fsid(idx);
+
+ /* no need to alter anything if console */
+ if ((id <= num) && (!pdev->dev.platform_data)) {
+ pinfo = &mpc885_uart_pdata[id];
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ }
+}
+
+
static int mpc885ads_platform_notify(struct device *dev)
{
@@ -356,12 +448,17 @@ static int mpc885ads_platform_notify(struct device *dev)
.rtn = mpc885ads_fixup_scc_enet_pdata,
},
{
+ .bus_id = "fsl-cpm-smc:uart",
+ .rtn = mpc885ads_fixup_uart_pdata
+ },
+ {
.bus_id = NULL
}
};
platform_notify_map(dev_map,dev);
+ return 0;
}
int __init mpc885ads_init(void)
@@ -383,7 +480,41 @@ int __init mpc885ads_init(void)
ppc_sys_device_enable(MPC8xx_CPM_FEC2);
#endif
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ ppc_sys_device_enable(MPC8xx_CPM_SMC1);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+ ppc_sys_device_enable(MPC8xx_CPM_SMC2);
+ ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
+#endif
return 0;
}
arch_initcall(mpc885ads_init);
+
+/*
+ To prevent confusion, console selection is gross:
+ by 0 assumed SMC1 and by 1 assumed SMC2
+ */
+struct platform_device* early_uart_get_pdev(int index)
+{
+ bd_t *bd = (bd_t *) __res;
+ struct fs_uart_platform_info *pinfo;
+
+ struct platform_device* pdev = NULL;
+ if(index) { /*assume SMC2 here*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
+ pinfo = &mpc885_uart_pdata[1];
+ } else { /*over SMC1*/
+ pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
+ pinfo = &mpc885_uart_pdata[0];
+ }
+
+ pinfo->uart_clk = bd->bi_intfreq;
+ pdev->dev.platform_data = pinfo;
+ ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
+ return NULL;
+}
+
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c
index 3365fd788a7..7fc2e02f524 100644
--- a/arch/ppc/platforms/pq2ads.c
+++ b/arch/ppc/platforms/pq2ads.c
@@ -14,11 +14,40 @@
#include <linux/init.h>
+#include <asm/io.h>
#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+#include <asm/immap_cpm2.h>
void __init
m82xx_board_setup(void)
{
+ cpm2_map_t* immap = ioremap(CPM_MAP_ADDR, sizeof(cpm2_map_t));
+ u32 *bcsr = ioremap(BCSR_ADDR+4, sizeof(u32));
+
/* Enable the 2nd UART port */
- *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2;
+ clrbits32(bcsr, BCSR1_RS232_EN2);
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ clrbits32((u32*)&immap->im_scc[0].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[0].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+ clrbits32((u32*)&immap->im_scc[1].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[1].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+ clrbits32((u32*)&immap->im_scc[2].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[2].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ clrbits32((u32*)&immap->im_scc[3].scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+ clrbits32((u32*)&immap->im_scc[3].scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
+
+ iounmap(bcsr);
+ iounmap(immap);
}
diff --git a/arch/ppc/syslib/ibm440gx_common.c b/arch/ppc/syslib/ibm440gx_common.c
index a7dd55f1c63..f6cc1688852 100644
--- a/arch/ppc/syslib/ibm440gx_common.c
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -2,7 +2,7 @@
* PPC440GX system library
*
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003, 2004 Zultys Technologies
+ * Copyright (c) 2003 - 2006 Zultys Technologies
*
* 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
@@ -282,3 +282,14 @@ int ibm440gx_show_cpuinfo(struct seq_file *m){
return 0;
}
+void __init ibm440gx_platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6,
+ unsigned long r7)
+{
+ /* Erratum 440_43 workaround, disable L1 cache parity checking */
+ if (!strcmp(cur_cpu_spec->cpu_name, "440GX Rev. C") ||
+ !strcmp(cur_cpu_spec->cpu_name, "440GX Rev. F"))
+ mtspr(SPRN_CCR1, mfspr(SPRN_CCR1) | CCR1_DPC);
+
+ ibm44x_platform_init(r3, r4, r5, r6, r7);
+}
diff --git a/arch/ppc/syslib/ibm440gx_common.h b/arch/ppc/syslib/ibm440gx_common.h
index a2ab9fab8e3..a03ec6022e8 100644
--- a/arch/ppc/syslib/ibm440gx_common.h
+++ b/arch/ppc/syslib/ibm440gx_common.h
@@ -29,6 +29,10 @@
void ibm440gx_get_clocks(struct ibm44x_clocks*, unsigned int sys_clk,
unsigned int ser_clk) __init;
+/* common 440GX platform init */
+void ibm440gx_platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7) __init;
+
/* Enable L2 cache */
void ibm440gx_l2c_enable(void) __init;
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c
index bd41ed83beb..6f536383866 100644
--- a/arch/ppc/syslib/mpc8xx_devices.c
+++ b/arch/ppc/syslib/mpc8xx_devices.c
@@ -170,12 +170,18 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC8xx_CPM_SMC1] = {
.name = "fsl-cpm-smc",
.id = 1,
- .num_resources = 2,
+ .num_resources = 3,
.resource = (struct resource[]) {
{
.name = "regs",
- .start = 0xa82,
- .end = 0xa91,
+ .start = 0xa80,
+ .end = 0xa8f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "pram",
+ .start = 0x3e80,
+ .end = 0x3ebf,
.flags = IORESOURCE_MEM,
},
{
@@ -189,15 +195,22 @@ struct platform_device ppc_sys_platform_devices[] = {
[MPC8xx_CPM_SMC2] = {
.name = "fsl-cpm-smc",
.id = 2,
- .num_resources = 2,
+ .num_resources = 3,
.resource = (struct resource[]) {
{
.name = "regs",
- .start = 0xa92,
- .end = 0xaa1,
+ .start = 0xa90,
+ .end = 0xa9f,
.flags = IORESOURCE_MEM,
},
{
+ .name = "pram",
+ .start = 0x3f80,
+ .end = 0x3fbf,
+ .flags = IORESOURCE_MEM,
+
+ },
+ {
.name = "interrupt",
.start = MPC8xx_INT_SMC2,
.end = MPC8xx_INT_SMC2,
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 7662c4e6e7d..2d48018b71d 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -109,9 +109,11 @@ ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr)
int i;
for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i];
- if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) {
+ if (((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) &&
+ ((r->flags & PPC_SYS_IORESOURCE_FIXUPPED) != PPC_SYS_IORESOURCE_FIXUPPED)) {
r->start += paddr;
r->end += paddr;
+ r->flags |= PPC_SYS_IORESOURCE_FIXUPPED;
}
}
}
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c
index 75e64f1c144..433b0fa203e 100644
--- a/arch/ppc/syslib/pq2_sys.c
+++ b/arch/ppc/syslib/pq2_sys.c
@@ -113,13 +113,13 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8248",
.mask = 0x0000ff00,
.value = 0x00000c00,
- .num_devices = 11,
+ .num_devices = 12,
.device_list = (enum ppc_sys_devices[])
{
MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
- MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SMC1,
- MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C,
- MPC82xx_CPM_USB, MPC82xx_SEC1,
+ MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
+ MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
+ MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
},
},
{
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 37dfe33dab7..8f36504075e 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -734,7 +734,7 @@ asmlinkage void
syscall_trace(struct pt_regs *regs, int entryexit)
{
if (unlikely(current->audit_context) && entryexit)
- audit_syscall_exit(current, AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
+ audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
if (!test_thread_flag(TIF_SYSCALL_TRACE))
goto out;
@@ -761,8 +761,7 @@ syscall_trace(struct pt_regs *regs, int entryexit)
}
out:
if (unlikely(current->audit_context) && !entryexit)
- audit_syscall_entry(current,
- test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
+ audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X,
regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
regs->gprs[4], regs->gprs[5]);
}
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index ae1927e48cf..d48cfc726b6 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -358,8 +358,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} else {
regs->gprs[14] = (unsigned long)
frame->retcode | PSW_ADDR_AMODE;
- err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
- (u16 __user *)(frame->retcode));
+ if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
+ (u16 __user *)(frame->retcode)))
+ goto give_sigsegv;
}
/* Set up backchain. */
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index db8faa75f94..6e1135cc03b 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -23,7 +23,7 @@ sys_call_table:
/*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
/*15*/ .long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek
/*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
-/*25*/ .long sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
+/*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
/*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
/*35*/ .long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile
/*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_getuid
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 49e6dedd027..d31975e6d6f 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -653,7 +653,7 @@ asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
result = AUDITSC_FAILURE;
- audit_syscall_exit(current, result, regs->u_regs[UREG_I0]);
+ audit_syscall_exit(result, regs->u_regs[UREG_I0]);
}
if (!(current->ptrace & PT_PTRACED))
@@ -677,8 +677,7 @@ asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
out:
if (unlikely(current->audit_context) && !syscall_exit_p)
- audit_syscall_entry(current,
- (test_thread_flag(TIF_32BIT) ?
+ audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
AUDIT_ARCH_SPARC :
AUDIT_ARCH_SPARC64),
regs->u_regs[UREG_G1],
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index f9b75760163..bdf1f4d02e3 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -139,6 +139,7 @@ SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
SIGN2(sys32_splice, sys_splice, %o0, %o1)
SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
SIGN2(sys32_tee, sys_tee, %o0, %o1)
+SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
.globl sys32_mmap2
sys32_mmap2:
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 62672cd92ec..d4b39cd3031 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -25,7 +25,7 @@ sys_call_table32:
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
/*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
-/*25*/ .word compat_sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
+/*25*/ .word sys32_vmsplice, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
/*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid
@@ -94,7 +94,7 @@ sys_call_table:
/*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod
/*15*/ .word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
-/*25*/ .word sys_nis_syscall, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
+/*25*/ .word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
/*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
.word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile64
/*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c
index a079cf42505..3f10fc921b0 100644
--- a/arch/sparc64/mm/tlb.c
+++ b/arch/sparc64/mm/tlb.c
@@ -8,6 +8,7 @@
#include <linux/percpu.h>
#include <linux/mm.h>
#include <linux/swap.h>
+#include <linux/preempt.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -24,6 +25,8 @@ void flush_tlb_pending(void)
{
struct mmu_gather *mp = &__get_cpu_var(mmu_gathers);
+ preempt_disable();
+
if (mp->tlb_nr) {
flush_tsb_user(mp);
@@ -38,6 +41,8 @@ void flush_tlb_pending(void)
}
mp->tlb_nr = 0;
}
+
+ preempt_enable();
}
void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 05fbb20636c..76e85bbaea5 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -57,20 +57,6 @@ config STATIC_LINK
chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
here.
-config HOST_2G_2G
- bool "2G/2G host address space split"
- default n
- depends on MODE_TT
- help
- This is needed when the host on which you run has a 2G/2G memory
- split, instead of the customary 3G/1G.
-
- Note that to enable such a host
- configuration, which makes sense only in some cases, you need special
- host patches.
-
- So, if you do not know what to do here, say 'N'.
-
config KERNEL_HALF_GIGS
int "Kernel address space size (in .5G units)"
default "1"
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386
index 85e6a55b3b5..f6eb72d117b 100644
--- a/arch/um/Kconfig.i386
+++ b/arch/um/Kconfig.i386
@@ -16,6 +16,19 @@ config SEMAPHORE_SLEEPERS
bool
default y
+config HOST_2G_2G
+ bool "2G/2G host address space split"
+ default n
+ help
+ This is needed when the host on which you run has a 2G/2G memory
+ split, instead of the customary 3G/1G.
+
+ Note that to enable such a host
+ configuration, which makes sense only in some cases, you need special
+ host patches.
+
+ So, if you do not know what to do here, say 'N'.
+
config TOP_ADDR
hex
default 0xc0000000 if !HOST_2G_2G
@@ -35,11 +48,13 @@ config 3_LEVEL_PGTABLES
config STUB_CODE
hex
- default 0xbfffe000
+ default 0xbfffe000 if !HOST_2G_2G
+ default 0x7fffe000 if HOST_2G_2G
config STUB_DATA
hex
- default 0xbffff000
+ default 0xbffff000 if !HOST_2G_2G
+ default 0x7ffff000 if HOST_2G_2G
config STUB_START
hex
diff --git a/arch/um/Makefile b/arch/um/Makefile
index a508e7a0289..f6ad832faf1 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -96,7 +96,8 @@ PHONY += linux
all: linux
linux: vmlinux
- ln -f $< $@
+ @echo ' LINK $@'
+ $(Q)ln -f $< $@
define archhelp
echo '* linux - Binary kernel image (./linux) - for backward'
@@ -117,6 +118,10 @@ prepare: $(ARCH_DIR)/include/kern_constants.h
LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib
+CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) \
+ $(call cc-option, -fno-stack-protector,) \
+ $(call cc-option, -fno-stack-protector-all,)
+
CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
CONFIG_KERNEL_STACK_ORDER ?= 2
STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
@@ -203,8 +208,8 @@ endef
$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
$(call filechk,umlconfig)
-$(ARCH_DIR)/user-offsets.s: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.c
- $(CC) $(USER_CFLAGS) -S -o $@ $<
+$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE
+ $(Q)$(MAKE) $(build)=$(ARCH_DIR)/sys-$(SUBARCH) $@
define filechk_gen-asm-offsets
(set -e; \
@@ -219,13 +224,11 @@ define filechk_gen-asm-offsets
echo ""; )
endef
-$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/user-offsets.s
+$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s
$(call filechk,gen-asm-offsets)
-CLEAN_FILES += $(ARCH_DIR)/user-offsets.s
-
$(ARCH_DIR)/include/kern_constants.h: $(objtree)/$(ARCH_DIR)/include
@echo ' SYMLINK $@'
- $(Q) ln -sf ../../../include/asm-um/asm-offsets.h $@
+ $(Q)ln -sf ../../../include/asm-um/asm-offsets.h $@
-export SUBARCH USER_CFLAGS OS
+export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 80d30d19d75..402a74dc502 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc6-mm1
-# Tue Jun 14 18:22:21 2005
+# Linux kernel version: 2.6.17-rc3
+# Fri Apr 28 09:31:20 2006
#
CONFIG_GENERIC_HARDIRQS=y
CONFIG_UML=y
CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_IRQ_RELEASE_METHOD=y
#
# UML-specific options
@@ -16,8 +15,50 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_MODE_TT is not set
# CONFIG_STATIC_LINK is not set
CONFIG_MODE_SKAS=y
+
+#
+# Host processor type and features
+#
+# CONFIG_M386 is not set
+# CONFIG_M486 is not set
+# CONFIG_M586 is not set
+# CONFIG_M586TSC is not set
+# CONFIG_M586MMX is not set
+CONFIG_M686=y
+# CONFIG_MPENTIUMII is not set
+# CONFIG_MPENTIUMIII is not set
+# CONFIG_MPENTIUMM is not set
+# CONFIG_MPENTIUM4 is not set
+# CONFIG_MK6 is not set
+# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
+# CONFIG_MCRUSOE is not set
+# CONFIG_MEFFICEON is not set
+# CONFIG_MWINCHIPC6 is not set
+# CONFIG_MWINCHIP2 is not set
+# CONFIG_MWINCHIP3D is not set
+# CONFIG_MGEODEGX1 is not set
+# CONFIG_MGEODE_LX is not set
+# CONFIG_MCYRIXIII is not set
+# CONFIG_MVIAC3_2 is not set
+# CONFIG_X86_GENERIC is not set
+CONFIG_X86_CMPXCHG=y
+CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=5
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_X86_PPRO_FENCE=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
+CONFIG_X86_BSWAP=y
+CONFIG_X86_POPAD_OK=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_TSC=y
CONFIG_UML_X86=y
# CONFIG_64BIT is not set
+CONFIG_SEMAPHORE_SLEEPERS=y
+# CONFIG_HOST_2G_2G is not set
CONFIG_TOP_ADDR=0xc0000000
# CONFIG_3_LEVEL_PGTABLES is not set
CONFIG_STUB_CODE=0xbfffe000
@@ -25,22 +66,24 @@ CONFIG_STUB_DATA=0xbffff000
CONFIG_STUB_START=0xbfffe000
CONFIG_ARCH_HAS_SC_SIGNALS=y
CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
+CONFIG_GENERIC_HWEIGHT=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_LD_SCRIPT_DYN=y
CONFIG_NET=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_HOSTFS is not set
+# CONFIG_HPPFS is not set
CONFIG_MCONSOLE=y
# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_HOST_2G_2G is not set
CONFIG_NEST_LEVEL=0
-CONFIG_KERNEL_HALF_GIGS=1
# CONFIG_HIGHMEM is not set
CONFIG_KERNEL_STACK_ORDER=2
CONFIG_UML_REAL_TIME_CLOCK=y
@@ -49,7 +92,6 @@ CONFIG_UML_REAL_TIME_CLOCK=y
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
@@ -57,6 +99,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
# General setup
#
CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
@@ -64,26 +107,28 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
+CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
#
# Loadable module support
@@ -91,18 +136,43 @@ CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_KMOD=y
#
-# Generic Driver Options
+# Block layer
#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Block devices
+#
+CONFIG_BLK_DEV_UBD=y
+# CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
+# CONFIG_MMAPPER is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# Character Devices
@@ -127,50 +197,23 @@ CONFIG_UML_SOUND=m
CONFIG_SOUND=m
CONFIG_HOSTAUDIO=m
CONFIG_UML_RANDOM=y
-# CONFIG_MMAPPER is not set
-
-#
-# Block devices
-#
-CONFIG_BLK_DEV_UBD=y
-CONFIG_BLK_DEV_UBD_SYNC=y
-CONFIG_BLK_DEV_COW_COMMON=y
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_RAM is not set
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_LBD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
-CONFIG_NETDEVICES=y
#
-# UML Network Devices
+# Generic Driver Options
#
-CONFIG_UML_NET=y
-CONFIG_UML_NET_ETHERTAP=y
-CONFIG_UML_NET_TUNTAP=y
-CONFIG_UML_NET_SLIP=y
-CONFIG_UML_NET_DAEMON=y
-CONFIG_UML_NET_MCAST=y
-CONFIG_UML_NET_SLIRP=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
#
-# Networking support
+# Networking
#
#
# Networking options
#
+# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -178,6 +221,7 @@ CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -186,27 +230,31 @@ CONFIG_INET=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# TCP congestion control
-#
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
-CONFIG_TCP_CONG_WESTWOOD=y
-CONFIG_TCP_CONG_HTCP=y
-# CONFIG_TCP_CONG_HSTCP is not set
-# CONFIG_TCP_CONG_HYBLA is not set
-# CONFIG_TCP_CONG_VEGAS is not set
-# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETFILTER is not set
#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
@@ -224,27 +272,47 @@ CONFIG_TCP_CONG_HTCP=y
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
-# CONFIG_KGDBOE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
+
+#
+# UML Network Devices
+#
+CONFIG_UML_NET=y
+CONFIG_UML_NET_ETHERTAP=y
+CONFIG_UML_NET_TUNTAP=y
+CONFIG_UML_NET_SLIP=y
+CONFIG_UML_NET_DAEMON=y
+CONFIG_UML_NET_MCAST=y
+# CONFIG_UML_NET_PCAP is not set
+CONFIG_UML_NET_SLIRP=y
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
#
+# PHY device support
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
# Wan interfaces
#
# CONFIG_WAN is not set
@@ -263,6 +331,13 @@ CONFIG_SLIP=m
# CONFIG_SLIP_MODE_SLIP6 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
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
#
# File systems
@@ -274,17 +349,14 @@ CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
-# CONFIG_REISER4_FS is not set
CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_REISERFS_FS_XATTR is not set
# CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
@@ -295,11 +367,6 @@ CONFIG_QUOTACTL=y
CONFIG_DNOTIFY=y
CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
-
-#
-# Caches
-#
-# CONFIG_FSCACHE is not set
# CONFIG_FUSE_FS is not set
#
@@ -323,14 +390,10 @@ CONFIG_JOLIET=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
# CONFIG_CONFIGFS_FS is not set
-# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -430,6 +493,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=m
# CONFIG_LIBCRC32C is not set
@@ -448,12 +512,18 @@ CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SLAB_LEAK is not set
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_GPROF is not set
# CONFIG_GCOV is not set
# CONFIG_SYSCALL_DEBUG is not set
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 6ab852bfcd3..0ec4052db9c 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -100,7 +100,7 @@ struct cow_header_v3_broken {
__u32 alignment;
__u32 cow_format;
char backing_file[PATH_LEN_V3];
-} __attribute__((packed));
+};
/* COW format definitions - for now, we have only the usual COW bitmap */
#define COW_BITMAP 0
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index c39ea3abeda..2ffda012385 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -89,16 +89,18 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
struct irq_fd *irq_fd;
int n;
- if(smp_sigio_handler()) return;
- while(1){
+ if (smp_sigio_handler())
+ return;
+
+ while (1) {
n = os_waiting_for_events(active_fds);
if (n <= 0) {
if(n == -EINTR) continue;
else break;
}
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if(irq_fd->current_events != 0){
+ for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+ if (irq_fd->current_events != 0) {
irq_fd->current_events = 0;
do_IRQ(irq_fd->irq, regs);
}
@@ -110,19 +112,17 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
static void maybe_sigio_broken(int fd, int type)
{
- if(os_isatty(fd)){
- if((type == IRQ_WRITE) && !pty_output_sigio){
+ if (os_isatty(fd)) {
+ if ((type == IRQ_WRITE) && !pty_output_sigio) {
write_sigio_workaround();
add_sigio_fd(fd, 0);
- }
- else if((type == IRQ_READ) && !pty_close_sigio){
+ } else if ((type == IRQ_READ) && !pty_close_sigio) {
write_sigio_workaround();
add_sigio_fd(fd, 1);
}
}
}
-
int activate_fd(int irq, int fd, int type, void *dev_id)
{
struct pollfd *tmp_pfd;
@@ -132,16 +132,18 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
pid = os_getpid();
err = os_set_fd_async(fd, pid);
- if(err < 0)
+ if (err < 0)
goto out;
new_fd = um_kmalloc(sizeof(*new_fd));
err = -ENOMEM;
- if(new_fd == NULL)
+ if (new_fd == NULL)
goto out;
- if(type == IRQ_READ) events = UM_POLLIN | UM_POLLPRI;
- else events = UM_POLLOUT;
+ if (type == IRQ_READ)
+ events = UM_POLLIN | UM_POLLPRI;
+ else
+ events = UM_POLLOUT;
*new_fd = ((struct irq_fd) { .next = NULL,
.id = dev_id,
.fd = fd,
@@ -165,8 +167,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
* a semaphore.
*/
flags = irq_lock();
- for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
- if((irq_fd->fd == fd) && (irq_fd->type == type)){
+ for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) {
+ if ((irq_fd->fd == fd) && (irq_fd->type == type)) {
printk("Registering fd %d twice\n", fd);
printk("Irqs : %d, %d\n", irq_fd->irq, irq);
printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id);
@@ -175,13 +177,13 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
}
/*-------------*/
- if(type == IRQ_WRITE)
+ if (type == IRQ_WRITE)
fd = -1;
tmp_pfd = NULL;
n = 0;
- while(1){
+ while (1) {
n = os_create_pollfd(fd, events, tmp_pfd, n);
if (n == 0)
break;
@@ -198,10 +200,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
* then we free the buffer tmp_fds and try again.
*/
irq_unlock(flags);
- if (tmp_pfd != NULL) {
- kfree(tmp_pfd);
- tmp_pfd = NULL;
- }
+ kfree(tmp_pfd);
+ tmp_pfd = NULL;
tmp_pfd = um_kmalloc(n);
if (tmp_pfd == NULL)
@@ -249,7 +249,7 @@ static int same_irq_and_dev(struct irq_fd *irq, void *d)
{
struct irq_and_dev *data = d;
- return((irq->irq == data->irq) && (irq->id == data->dev));
+ return ((irq->irq == data->irq) && (irq->id == data->dev));
}
void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
@@ -262,7 +262,7 @@ void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
static int same_fd(struct irq_fd *irq, void *fd)
{
- return(irq->fd == *((int *) fd));
+ return (irq->fd == *((int *)fd));
}
void free_irq_by_fd(int fd)
@@ -276,16 +276,17 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
int i = 0;
int fdi;
- for(irq=active_fds; irq != NULL; irq = irq->next){
- if((irq->fd == fd) && (irq->irq == irqnum)) break;
+ for (irq = active_fds; irq != NULL; irq = irq->next) {
+ if ((irq->fd == fd) && (irq->irq == irqnum))
+ break;
i++;
}
- if(irq == NULL){
+ if (irq == NULL) {
printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
goto out;
}
fdi = os_get_pollfd(i);
- if((fdi != -1) && (fdi != fd)){
+ if ((fdi != -1) && (fdi != fd)) {
printk("find_irq_by_fd - mismatch between active_fds and "
"pollfds, fd %d vs %d, need %d\n", irq->fd,
fdi, fd);
@@ -294,7 +295,7 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
}
*index_out = i;
out:
- return(irq);
+ return irq;
}
void reactivate_fd(int fd, int irqnum)
@@ -305,7 +306,7 @@ void reactivate_fd(int fd, int irqnum)
flags = irq_lock();
irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL){
+ if (irq == NULL) {
irq_unlock(flags);
return;
}
@@ -326,7 +327,7 @@ void deactivate_fd(int fd, int irqnum)
flags = irq_lock();
irq = find_irq_by_fd(fd, irqnum, &i);
- if(irq == NULL)
+ if (irq == NULL)
goto out;
os_set_pollfd(i, -1);
out:
@@ -338,15 +339,15 @@ int deactivate_all_fds(void)
struct irq_fd *irq;
int err;
- for(irq=active_fds;irq != NULL;irq = irq->next){
+ for (irq = active_fds; irq != NULL; irq = irq->next) {
err = os_clear_fd_async(irq->fd);
- if(err)
- return(err);
+ if (err)
+ return err;
}
/* If there is a signal already queued, after unblocking ignore it */
os_set_ioignore();
- return(0);
+ return 0;
}
void forward_interrupts(int pid)
@@ -356,9 +357,9 @@ void forward_interrupts(int pid)
int err;
flags = irq_lock();
- for(irq=active_fds;irq != NULL;irq = irq->next){
+ for (irq = active_fds; irq != NULL; irq = irq->next) {
err = os_set_owner(irq->fd, pid);
- if(err < 0){
+ if (err < 0) {
/* XXX Just remove the irq rather than
* print out an infinite stream of these
*/
@@ -379,7 +380,7 @@ void forward_interrupts(int pid)
unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
{
irq_enter();
- __do_IRQ(irq, (struct pt_regs *) regs);
+ __do_IRQ(irq, (struct pt_regs *)regs);
irq_exit();
return 1;
}
@@ -392,12 +393,12 @@ int um_request_irq(unsigned int irq, int fd, int type,
int err;
err = request_irq(irq, handler, irqflags, devname, dev_id);
- if(err)
- return(err);
+ if (err)
+ return err;
- if(fd != -1)
+ if (fd != -1)
err = activate_fd(irq, fd, type, dev_id);
- return(err);
+ return err;
}
EXPORT_SYMBOL(um_request_irq);
EXPORT_SYMBOL(reactivate_fd);
@@ -409,7 +410,7 @@ unsigned long irq_lock(void)
unsigned long flags;
spin_lock_irqsave(&irq_spinlock, flags);
- return(flags);
+ return flags;
}
void irq_unlock(unsigned long flags)
@@ -452,7 +453,7 @@ void __init init_IRQ(void)
irq_desc[TIMER_IRQ].depth = 1;
irq_desc[TIMER_IRQ].handler = &SIGVTALRM_irq_type;
enable_irq(TIMER_IRQ);
- for(i=1;i<NR_IRQS;i++){
+ for (i = 1; i < NR_IRQS; i++) {
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
@@ -467,7 +468,7 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
int fds[2], err;
err = os_pipe(fds, 1, 1);
- if(err){
+ if (err) {
printk("init_aio_irq - os_pipe failed, err = %d\n", -err);
goto out;
}
@@ -475,7 +476,7 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
err = um_request_irq(irq, fds[0], IRQ_READ, handler,
SA_INTERRUPT | SA_SAMPLE_RANDOM, name,
(void *) (long) fds[0]);
- if(err){
+ if (err) {
printk("init_aio_irq - : um_request_irq failed, err = %d\n",
err);
goto out_close;
@@ -488,5 +489,5 @@ int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *,
os_close_file(fds[0]);
os_close_file(fds[1]);
out:
- return(err);
+ return err;
}
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index 0500800df1c..fc0f0b085ca 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -407,6 +407,8 @@ unsigned long find_iomem(char *driver, unsigned long *len_out)
*len_out = region->size;
return(region->virt);
}
+
+ region = region->next;
}
return(0);
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 60d2eda995c..9a77fb3c269 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -275,15 +275,13 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
if (unlikely(current->audit_context)) {
if (!entryexit)
- audit_syscall_entry(current,
- HOST_AUDIT_ARCH,
+ audit_syscall_entry(HOST_AUDIT_ARCH,
UPT_SYSCALL_NR(regs),
UPT_SYSCALL_ARG1(regs),
UPT_SYSCALL_ARG2(regs),
UPT_SYSCALL_ARG3(regs),
UPT_SYSCALL_ARG4(regs));
- else audit_syscall_exit(current,
- AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
+ else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
UPT_SYSCALL_RET(regs));
}
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 57181a920d4..ea3a8e409a6 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -6,9 +6,11 @@
obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
syscall.o tlb.o uaccess.o
-USER_OBJS := clone.o
+# clone.o is in the stub, so it can't be built with profiling
+# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
+# disable it
-include arch/um/scripts/Makefile.rules
+CFLAGS_clone.o := $(CFLAGS_NO_HARDENING)
+UNPROFILE_OBJS := clone.o
-# clone.o is in the stub, so it can't be built with profiling
-$(obj)/clone.o : c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 3c7626cdba4..528cf623f8b 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -209,4 +209,4 @@ int __init timer_init(void)
return(0);
}
-__initcall(timer_init);
+arch_initcall(timer_init);
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 3bd10deea28..09251338d99 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -171,7 +171,7 @@ int os_sigio_async(int master, int slave)
flags = fcntl(master, F_GETFL);
if(flags < 0)
- return errno;
+ return -errno;
if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
(fcntl(master, F_SETOWN, os_getpid()) < 0))
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index e599be423da..3788d4568d3 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -29,21 +29,21 @@ int os_waiting_for_events(struct irq_fd *active_fds)
int i, n, err;
n = poll(pollfds, pollfds_num, 0);
- if(n < 0){
+ if (n < 0) {
err = -errno;
- if(errno != EINTR)
+ if (errno != EINTR)
printk("sigio_handler: os_waiting_for_events:"
" poll returned %d, errno = %d\n", n, errno);
return err;
}
- if(n == 0)
+ if (n == 0)
return 0;
irq_fd = active_fds;
- for(i = 0; i < pollfds_num; i++){
- if(pollfds[i].revents != 0){
+ for (i = 0; i < pollfds_num; i++) {
+ if (pollfds[i].revents != 0) {
irq_fd->current_events = pollfds[i].revents;
pollfds[i].fd = -1;
}
@@ -54,7 +54,7 @@ int os_waiting_for_events(struct irq_fd *active_fds)
int os_isatty(int fd)
{
- return(isatty(fd));
+ return isatty(fd);
}
int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
@@ -65,7 +65,7 @@ int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
return((pollfds_size + 1) * sizeof(pollfds[0]));
}
- if(pollfds != NULL){
+ if (pollfds != NULL) {
memcpy(tmp_pfd, pollfds,
sizeof(pollfds[0]) * pollfds_size);
/* remove old pollfds */
@@ -73,18 +73,15 @@ int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
}
pollfds = tmp_pfd;
pollfds_size++;
- } else {
- /* remove not used tmp_pfd */
- if (tmp_pfd != NULL)
- kfree(tmp_pfd);
- }
+ } else
+ kfree(tmp_pfd); /* remove not used tmp_pfd */
- pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
- .events = events,
- .revents = 0 });
+ pollfds[pollfds_num] = ((struct pollfd) { .fd = fd,
+ .events = events,
+ .revents = 0 });
pollfds_num++;
- return(0);
+ return 0;
}
void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
@@ -94,11 +91,11 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
int i = 0;
prev = &active_fds;
- while(*prev != NULL){
- if((*test)(*prev, arg)){
+ while (*prev != NULL) {
+ if ((*test)(*prev, arg)) {
struct irq_fd *old_fd = *prev;
- if((pollfds[i].fd != -1) &&
- (pollfds[i].fd != (*prev)->fd)){
+ if ((pollfds[i].fd != -1) &&
+ (pollfds[i].fd != (*prev)->fd)) {
printk("os_free_irq_by_cb - mismatch between "
"active_fds and pollfds, fd %d vs %d\n",
(*prev)->fd, pollfds[i].fd);
@@ -110,7 +107,6 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
/* This moves the *whole* array after pollfds[i]
* (though it doesn't spot as such)!
*/
-
memmove(&pollfds[i], &pollfds[i + 1],
(pollfds_num - i) * sizeof(pollfds[0]));
if(*last_irq_ptr2 == &old_fd->next)
@@ -129,10 +125,9 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
return;
}
-
int os_get_pollfd(int i)
{
- return(pollfds[i].fd);
+ return pollfds[i].fd;
}
void os_set_pollfd(int i, int fd)
@@ -151,8 +146,10 @@ void init_irq_signals(int on_sigstack)
int flags;
flags = on_sigstack ? SA_ONSTACK : 0;
- if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
- else h = boot_timer_handler;
+ if (timer_irq_inited)
+ h = (__sighandler_t)alarm_handler;
+ else
+ h = boot_timer_handler;
set_handler(SIGVTALRM, h, flags | SA_RESTART,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 2878e89a674..3a0ac38e978 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -74,6 +74,34 @@ static void last_ditch_exit(int sig)
exit(1);
}
+#define UML_LIB_PATH ":/usr/lib/uml"
+
+static void setup_env_path(void)
+{
+ char *new_path = NULL;
+ char *old_path = NULL;
+ int path_len = 0;
+
+ old_path = getenv("PATH");
+ /* if no PATH variable is set or it has an empty value
+ * just use the default + /usr/lib/uml
+ */
+ if (!old_path || (path_len = strlen(old_path)) == 0) {
+ putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH);
+ return;
+ }
+
+ /* append /usr/lib/uml to the existing path */
+ path_len += strlen("PATH=" UML_LIB_PATH) + 1;
+ new_path = malloc(path_len);
+ if (!new_path) {
+ perror("coudn't malloc to set a new PATH");
+ return;
+ }
+ snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
+ putenv(new_path);
+}
+
extern int uml_exitcode;
extern void scan_elf_aux( char **envp);
@@ -114,6 +142,8 @@ int main(int argc, char **argv, char **envp)
set_stklim();
+ setup_env_path();
+
new_argv = malloc((argc + 1) * sizeof(char *));
if(new_argv == NULL){
perror("Mallocing argv");
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 3505f44f8a2..233be2f4f8c 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -206,29 +206,36 @@ int os_drop_memory(void *addr, int length)
int can_drop_memory(void)
{
void *addr;
- int fd;
+ int fd, ok = 0;
printk("Checking host MADV_REMOVE support...");
fd = create_mem_file(UM_KERN_PAGE_SIZE);
if(fd < 0){
printk("Creating test memory file failed, err = %d\n", -fd);
- return 0;
+ goto out;
}
addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if(addr == MAP_FAILED){
printk("Mapping test memory file failed, err = %d\n", -errno);
- return 0;
+ goto out_close;
}
if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){
printk("MADV_REMOVE failed, err = %d\n", -errno);
- return 0;
+ goto out_unmap;
}
printk("OK\n");
- return 1;
+ ok = 1;
+
+out_unmap:
+ munmap(addr, UM_KERN_PAGE_SIZE);
+out_close:
+ close(fd);
+out:
+ return ok;
}
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 0776bc18ca8..bd89c6b99d5 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -344,12 +344,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
err = ptrace_setregs(pid, regs);
if(err < 0)
panic("copy_context_skas0 : PTRACE_SETREGS failed, "
- "pid = %d, errno = %d\n", pid, errno);
+ "pid = %d, errno = %d\n", pid, -err);
err = ptrace_setfpregs(pid, fp_regs);
if(err < 0)
panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
- "pid = %d, errno = %d\n", pid, errno);
+ "pid = %d, errno = %d\n", pid, -err);
/* set a well known return code for detection of child write failure */
child_data->err = 12345678;
@@ -362,7 +362,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
pid = data->err;
if(pid < 0)
panic("copy_context_skas0 - stub-parent reports error %d\n",
- pid);
+ -pid);
/* Wait, until child has finished too: read child's result from
* child's stack and check it.
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 7a6f6b99cef..516f66dd87e 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -104,7 +104,7 @@ void init_registers(int pid)
err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
if(err)
panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- err);
+ errno);
errno = 0;
err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
@@ -119,7 +119,7 @@ void init_registers(int pid)
err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
if(err)
panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
- err);
+ errno);
}
void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index 001941fa1a1..becd898d939 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -62,12 +62,12 @@ void init_registers(int pid)
err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
if(err)
panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- err);
+ errno);
err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
if(err)
panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
- err);
+ errno);
}
void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 34bfc1bb9e3..362db059fe3 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -178,14 +178,14 @@ static void __init create_pid_file(void)
fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644);
if(fd < 0){
printk("Open of machine pid file \"%s\" failed: %s\n",
- file, strerror(-fd));
+ file, strerror(errno));
return;
}
snprintf(pid, sizeof(pid), "%d\n", getpid());
n = write(fd, pid, strlen(pid));
if(n != strlen(pid))
- printk("Write of pid file failed - err = %d\n", -n);
+ printk("Write of pid file failed - err = %d\n", errno);
close(fd);
}
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 2598158e1f5..3f33165ada6 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -96,6 +96,13 @@ EXPORT_SYMBOL_PROTO(getuid);
EXPORT_SYMBOL_PROTO(fsync);
EXPORT_SYMBOL_PROTO(fdatasync);
+/* Export symbols used by GCC for the stack protector. */
+extern void __stack_smash_handler(void *) __attribute__((weak));
+EXPORT_SYMBOL(__stack_smash_handler);
+
+extern long __guard __attribute__((weak));
+EXPORT_SYMBOL(__guard);
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 5e7a9c310aa..1347dc6d521 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -7,11 +7,19 @@ USER_SINGLE_OBJS := \
USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-$(USER_OBJS) $(USER_OBJS:.o=.i) $(USER_OBJS:.o=.s) $(USER_OBJS:.o=.lst): \
- c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(notdir $@))
+$(USER_OBJS:.o=.%): \
+ c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(*F).o)
$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
-Dunix -D__unix__ -D__$(SUBARCH)__
+# These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of
+# using it directly.
+UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file))
+
+$(UNPROFILE_OBJS:.o=.%): \
+ c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(*F).o)
+$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
+ -Dunix -D__unix__ -D__$(SUBARCH)__
# The stubs and unmap.o can't try to call mcount or update basic block data
define unprofile
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 98b20b7bba4..374d61a1943 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -8,11 +8,16 @@ subarch-obj-y = lib/bitops.o kernel/semaphore.o
subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o
subarch-obj-$(CONFIG_MODULES) += kernel/module.o
-USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o stub_segv.o
+USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
-include arch/um/scripts/Makefile.rules
+USER_OBJS += user-offsets.s
+extra-y += user-offsets.s
extra-$(CONFIG_MODE_TT) += unmap.o
-$(obj)/stub_segv.o $(obj)/unmap.o: \
- _c_flags = $(call unprofile,$(CFLAGS))
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
+
+include arch/um/scripts/Makefile.rules
+
+$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index b5fc22babdd..c19794d435d 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -16,11 +16,16 @@ subarch-obj-$(CONFIG_MODULES) += kernel/module.o
ldt-y = ../sys-i386/ldt.o
-USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o
+USER_OBJS := ptrace_user.o sigcontext.o
-include arch/um/scripts/Makefile.rules
+USER_OBJS += user-offsets.s
+extra-y += user-offsets.s
extra-$(CONFIG_MODE_TT) += unmap.o
-$(obj)/stub_segv.o $(obj)/unmap.o: \
- _c_flags = $(call unprofile,$(CFLAGS))
+UNPROFILE_OBJS := stub_segv.o
+CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
+
+include arch/um/scripts/Makefile.rules
+
+$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 57fc37e0fb9..5a92fed2d1d 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -695,4 +695,5 @@ ia32_sys_call_table:
.quad sys_splice
.quad sys_sync_file_range
.quad sys_tee
+ .quad compat_sys_vmsplice
ia32_syscall_end:
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index da8e7903d81..2d50024c9f3 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -600,12 +600,12 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
if (unlikely(current->audit_context)) {
if (test_thread_flag(TIF_IA32)) {
- audit_syscall_entry(current, AUDIT_ARCH_I386,
+ audit_syscall_entry(AUDIT_ARCH_I386,
regs->orig_rax,
regs->rbx, regs->rcx,
regs->rdx, regs->rsi);
} else {
- audit_syscall_entry(current, AUDIT_ARCH_X86_64,
+ audit_syscall_entry(AUDIT_ARCH_X86_64,
regs->orig_rax,
regs->rdi, regs->rsi,
regs->rdx, regs->r10);
@@ -616,7 +616,7 @@ asmlinkage void syscall_trace_enter(struct pt_regs *regs)
asmlinkage void syscall_trace_leave(struct pt_regs *regs)
{
if (unlikely(current->audit_context))
- audit_syscall_exit(current, AUDITSC_RESULT(regs->rax), regs->rax);
+ audit_syscall_exit(AUDITSC_RESULT(regs->rax), regs->rax);
if ((test_thread_flag(TIF_SYSCALL_TRACE)
|| test_thread_flag(TIF_SINGLESTEP))
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 759070c8275..ebc3c33b1c6 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -1426,3 +1426,22 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
+#ifdef CONFIG_INPUT_PCSPKR
+#include <linux/platform_device.h>
+static __init int add_pcspkr(void)
+{
+ struct platform_device *pd;
+ int ret;
+
+ pd = platform_device_alloc("pcspkr", -1);
+ if (!pd)
+ return -ENOMEM;
+
+ ret = platform_device_add(pd);
+ if (ret)
+ platform_device_put(pd);
+
+ return ret;
+}
+device_initcall(add_pcspkr);
+#endif
diff --git a/block/genhd.c b/block/genhd.c
index 5a8d3bf02f1..d9657258962 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -182,6 +182,7 @@ static int exact_lock(dev_t dev, void *data)
*/
void add_disk(struct gendisk *disk)
{
+ get_device(disk->driverfs_dev);
disk->flags |= GENHD_FL_UP;
blk_register_region(MKDEV(disk->major, disk->first_minor),
disk->minors, NULL, exact_match, exact_lock, disk);
@@ -427,6 +428,7 @@ static struct attribute * default_attrs[] = {
static void disk_release(struct kobject * kobj)
{
struct gendisk *disk = to_disk(kobj);
+ put_device(disk->driverfs_dev);
kfree(disk->random);
kfree(disk->part);
free_disk_stats(disk);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index bedb689b051..dff1e67b1dd 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4301,7 +4301,7 @@ static int __init floppy_init(void)
}
use_virtual_dma = can_use_virtual_dma & 1;
-#if defined(CONFIG_PPC64)
+#if defined(CONFIG_PPC_MERGE)
if (check_legacy_ioport(FDC1)) {
del_timer(&fd_timeout);
err = -ENODEV;
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index d3a2bc36129..588fca542a9 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -200,13 +200,13 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf,
/* first test allows optimizer to nuke this case for 32-bit machines */
if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
unsigned int uidata = data;
- retval = put_user(uidata, (unsigned long __user *)buf);
+ retval = put_user(uidata, (unsigned int __user *)buf) ?:
+ sizeof(unsigned int);
}
else {
- retval = put_user(data, (unsigned long __user *)buf);
+ retval = put_user(data, (unsigned long __user *)buf) ?:
+ sizeof(unsigned long);
}
- if (!retval)
- retval = sizeof(unsigned long);
out:
current->state = TASK_RUNNING;
remove_wait_queue(&gen_rtc_wait, &wait);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 935670a3cd9..5755b7e5f18 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -860,9 +860,32 @@ static void k_slock(struct vc_data *vc, unsigned char value, char up_flag, struc
}
/* by default, 300ms interval for combination release */
-static long brl_timeout = 300;
-MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for combination on first release, < 0 for dead characters)");
-module_param(brl_timeout, long, 0644);
+static unsigned brl_timeout = 300;
+MODULE_PARM_DESC(brl_timeout, "Braille keys release delay in ms (0 for commit on first key release)");
+module_param(brl_timeout, uint, 0644);
+
+static unsigned brl_nbchords = 1;
+MODULE_PARM_DESC(brl_nbchords, "Number of chords that produce a braille pattern (0 for dead chords)");
+module_param(brl_nbchords, uint, 0644);
+
+static void k_brlcommit(struct vc_data *vc, unsigned int pattern, char up_flag, struct pt_regs *regs)
+{
+ static unsigned long chords;
+ static unsigned committed;
+
+ if (!brl_nbchords)
+ k_deadunicode(vc, BRL_UC_ROW | pattern, up_flag, regs);
+ else {
+ committed |= pattern;
+ chords++;
+ if (chords == brl_nbchords) {
+ k_unicode(vc, BRL_UC_ROW | committed, up_flag, regs);
+ chords = 0;
+ committed = 0;
+ }
+ }
+}
+
static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
{
static unsigned pressed,committing;
@@ -882,11 +905,6 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct
if (value > 8)
return;
- if (brl_timeout < 0) {
- k_deadunicode(vc, BRL_UC_ROW | (1 << (value - 1)), up_flag, regs);
- return;
- }
-
if (up_flag) {
if (brl_timeout) {
if (!committing ||
@@ -897,13 +915,13 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag, struct
pressed &= ~(1 << (value - 1));
if (!pressed) {
if (committing) {
- k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+ k_brlcommit(vc, committing, 0, regs);
committing = 0;
}
}
} else {
if (committing) {
- k_unicode(vc, BRL_UC_ROW | committing, 0, regs);
+ k_brlcommit(vc, committing, 0, regs);
committing = 0;
}
pressed &= ~(1 << (value - 1));
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index 66572c5323a..fce31936e6d 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -25,6 +25,8 @@
#include <linux/slab.h>
#include "edac_mc.h"
+static int force_function_unhide;
+
#define e752x_printk(level, fmt, arg...) \
edac_printk(level, "e752x", fmt, ##arg)
@@ -782,8 +784,16 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
debugf0("%s(): mci\n", __func__);
debugf0("Starting Probe1\n");
- /* enable device 0 function 1 */
+ /* check to see if device 0 function 1 is enabled; if it isn't, we
+ * assume the BIOS has reserved it for a reason and is expecting
+ * exclusive access, we take care not to violate that assumption and
+ * fail the probe. */
pci_read_config_byte(pdev, E752X_DEVPRES1, &stat8);
+ if (!force_function_unhide && !(stat8 & (1 << 5))) {
+ printk(KERN_INFO "Contact your BIOS vendor to see if the "
+ "E752x error registers can be safely un-hidden\n");
+ goto fail;
+ }
stat8 |= (1 << 5);
pci_write_config_byte(pdev, E752X_DEVPRES1, stat8);
@@ -1063,3 +1073,8 @@ module_exit(e752x_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Tom Zimmerman\n");
MODULE_DESCRIPTION("MC support for Intel e752x memory controllers");
+
+module_param(force_function_unhide, int, 0444);
+MODULE_PARM_DESC(force_function_unhide, "if BIOS sets Dev0:Fun1 up as hidden:"
+" 1=force unhide and hope BIOS doesn't fight driver for Dev0:Fun1 access");
+
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
index 593e28969c6..46762387f5f 100644
--- a/drivers/infiniband/hw/ipath/ipath_debug.h
+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -60,11 +60,11 @@
#define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */
#define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */
#define __IPATH_SMADBG 0x8000 /* sma packet debug */
-#define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) general debug on */
-#define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings on */
-#define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors on */
-#define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump on */
-#define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump on */
+#define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) gen debug */
+#define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings */
+#define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors */
+#define __IPATH_IPATHPD 0x80000 /* Ethernet (IPATH) packet dump */
+#define __IPATH_IPATHTABLE 0x100000 /* Ethernet (IPATH) table dump */
#else /* _IPATH_DEBUGGING */
@@ -79,11 +79,12 @@
#define __IPATH_TRSAMPLE 0x0 /* generate trace buffer sample entries */
#define __IPATH_VERBDBG 0x0 /* very verbose debug */
#define __IPATH_PKTDBG 0x0 /* print packet data */
-#define __IPATH_PROCDBG 0x0 /* print process startup (init)/exit messages */
+#define __IPATH_PROCDBG 0x0 /* process startup (init)/exit messages */
/* print mmap/nopage stuff, not using VDBG any more */
#define __IPATH_MMDBG 0x0
#define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */
-#define __IPATH_SMADBG 0x0 /* print process startup (init)/exit messages */#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */
+#define __IPATH_SMADBG 0x0 /* process startup (init)/exit messages */
+#define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */
#define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */
#define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */
#define __IPATH_IPATHPD 0x0 /* Ethernet (IPATH) packet dump on */
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index 7d3fb6996b4..28ddceb260e 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -277,13 +277,14 @@ static int ipath_diag_open(struct inode *in, struct file *fp)
bail:
spin_unlock_irqrestore(&ipath_devs_lock, flags);
- mutex_unlock(&ipath_mutex);
/* Only expose a way to reset the device if we
make it into diag mode. */
if (ret == 0)
ipath_expose_reset(&dd->pcidev->dev);
+ mutex_unlock(&ipath_mutex);
+
return ret;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index e7617c3982e..398add4d4cb 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -418,9 +418,19 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
if (ret) {
- dev_info(&pdev->dev, "pci_set_dma_mask unit %u "
- "fails: %d\n", dd->ipath_unit, ret);
- goto bail_regions;
+ /*
+ * if the 64 bit setup fails, try 32 bit. Some systems
+ * do not setup 64 bit maps on systems with 2GB or less
+ * memory installed.
+ */
+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (ret) {
+ dev_info(&pdev->dev, "pci_set_dma_mask unit %u "
+ "fails: %d\n", dd->ipath_unit, ret);
+ goto bail_regions;
+ }
+ else
+ ipath_dbg("No 64bit DMA mask, used 32 bit mask\n");
}
pci_set_master(pdev);
@@ -1949,7 +1959,7 @@ int ipath_reset_device(int unit)
}
if (dd->ipath_pd)
- for (i = 1; i < dd->ipath_portcnt; i++) {
+ for (i = 1; i < dd->ipath_cfgports; i++) {
if (dd->ipath_pd[i] && dd->ipath_pd[i]->port_cnt) {
ipath_dbg("unit %u port %d is in use "
"(PID %u cmd %s), can't reset\n",
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 2823ff9c0c6..16f640e1c16 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -53,13 +53,19 @@ MODULE_PARM_DESC(cfgports, "Set max number of ports to use");
/*
* Number of buffers reserved for driver (layered drivers and SMA
- * send). Reserved at end of buffer list.
+ * send). Reserved at end of buffer list. Initialized based on
+ * number of PIO buffers if not set via module interface.
+ * The problem with this is that it's global, but we'll use different
+ * numbers for different chip types. So the default value is not
+ * very useful. I've redefined it for the 1.3 release so that it's
+ * zero unless set by the user to something else, in which case we
+ * try to respect it.
*/
-static ushort ipath_kpiobufs = 32;
+static ushort ipath_kpiobufs;
static int ipath_set_kpiobufs(const char *val, struct kernel_param *kp);
-module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_uint,
+module_param_call(kpiobufs, ipath_set_kpiobufs, param_get_ushort,
&ipath_kpiobufs, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver");
@@ -531,8 +537,11 @@ static int init_housekeeping(struct ipath_devdata *dd,
* Don't clear ipath_flags as 8bit mode was set before
* entering this func. However, we do set the linkstate to
* unknown, so we can watch for a transition.
+ * PRESENT is set because we want register reads to work,
+ * and the kernel infrastructure saw it in config space;
+ * We clear it if we have failures.
*/
- dd->ipath_flags |= IPATH_LINKUNK;
+ dd->ipath_flags |= IPATH_LINKUNK | IPATH_PRESENT;
dd->ipath_flags &= ~(IPATH_LINKACTIVE | IPATH_LINKARMED |
IPATH_LINKDOWN | IPATH_LINKINIT);
@@ -560,6 +569,7 @@ static int init_housekeeping(struct ipath_devdata *dd,
|| (dd->ipath_uregbase & 0xffffffff) == 0xffffffff) {
ipath_dev_err(dd, "Register read failures from chip, "
"giving up initialization\n");
+ dd->ipath_flags &= ~IPATH_PRESENT;
ret = -ENODEV;
goto done;
}
@@ -682,16 +692,14 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
*/
dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2)
/ (sizeof(u64) * BITS_PER_BYTE / 2);
- if (!ipath_kpiobufs) /* have to have at least 1, for SMA */
- kpiobufs = ipath_kpiobufs = 1;
- else if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) <
- (dd->ipath_cfgports * IPATH_MIN_USER_PORT_BUFCNT)) {
- dev_info(&dd->pcidev->dev, "Too few PIO buffers (%u) "
- "for %u ports to have %u each!\n",
- dd->ipath_piobcnt2k + dd->ipath_piobcnt4k,
- dd->ipath_cfgports, IPATH_MIN_USER_PORT_BUFCNT);
- kpiobufs = 1; /* reserve just the minimum for SMA/ether */
- } else
+ if (ipath_kpiobufs == 0) {
+ /* not set by user, or set explictly to default */
+ if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > 128)
+ kpiobufs = 32;
+ else
+ kpiobufs = 16;
+ }
+ else
kpiobufs = ipath_kpiobufs;
if (kpiobufs >
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 0bcb428041f..3e72a1fe3d7 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -665,14 +665,14 @@ static void handle_layer_pioavail(struct ipath_devdata *dd)
ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
if (ret > 0)
- goto clear;
+ goto set;
ret = __ipath_verbs_piobufavail(dd);
if (ret > 0)
- goto clear;
+ goto set;
return;
-clear:
+set:
set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
@@ -719,11 +719,24 @@ static void handle_rcv(struct ipath_devdata *dd, u32 istat)
irqreturn_t ipath_intr(int irq, void *data, struct pt_regs *regs)
{
struct ipath_devdata *dd = data;
- u32 istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
+ u32 istat;
ipath_err_t estat = 0;
static unsigned unexpected = 0;
irqreturn_t ret;
+ if(!(dd->ipath_flags & IPATH_PRESENT)) {
+ /* this is mostly so we don't try to touch the chip while
+ * it is being reset */
+ /*
+ * This return value is perhaps odd, but we do not want the
+ * interrupt core code to remove our interrupt handler
+ * because we don't appear to be handling an interrupt
+ * during a chip reset.
+ */
+ return IRQ_HANDLED;
+ }
+
+ istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
if (unlikely(!istat)) {
ipath_stats.sps_nullintr++;
ret = IRQ_NONE; /* not our interrupt, or already handled */
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 0ce5f19c9d6..e6507f8115b 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -731,7 +731,7 @@ u64 ipath_read_kreg64_port(const struct ipath_devdata *, ipath_kreg,
static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
ipath_ureg regno, int port)
{
- if (!dd->ipath_kregbase)
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
return 0;
return readl(regno + (u64 __iomem *)
@@ -762,7 +762,7 @@ static inline void ipath_write_ureg(const struct ipath_devdata *dd,
static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd,
ipath_kreg regno)
{
- if (!dd->ipath_kregbase)
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
return -1;
return readl((u32 __iomem *) & dd->ipath_kregbase[regno]);
}
@@ -770,7 +770,7 @@ static inline u32 ipath_read_kreg32(const struct ipath_devdata *dd,
static inline u64 ipath_read_kreg64(const struct ipath_devdata *dd,
ipath_kreg regno)
{
- if (!dd->ipath_kregbase)
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
return -1;
return readq(&dd->ipath_kregbase[regno]);
@@ -786,7 +786,7 @@ static inline void ipath_write_kreg(const struct ipath_devdata *dd,
static inline u64 ipath_read_creg(const struct ipath_devdata *dd,
ipath_sreg regno)
{
- if (!dd->ipath_kregbase)
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
return 0;
return readq(regno + (u64 __iomem *)
@@ -797,7 +797,7 @@ static inline u64 ipath_read_creg(const struct ipath_devdata *dd,
static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
ipath_sreg regno)
{
- if (!dd->ipath_kregbase)
+ if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT))
return 0;
return readl(regno + (u64 __iomem *)
(dd->ipath_cregbase +
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
index 69ed1100701..9cb5258ffed 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.c
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -46,13 +46,15 @@
/* Acquire before ipath_devs_lock. */
static DEFINE_MUTEX(ipath_layer_mutex);
+static int ipath_verbs_registered;
+
u16 ipath_layer_rcv_opcode;
+
static int (*layer_intr)(void *, u32);
static int (*layer_rcv)(void *, void *, struct sk_buff *);
static int (*layer_rcv_lid)(void *, void *);
static int (*verbs_piobufavail)(void *);
static void (*verbs_rcv)(void *, void *, void *, u32);
-static int ipath_verbs_registered;
static void *(*layer_add_one)(int, struct ipath_devdata *);
static void (*layer_remove_one)(void *);
@@ -586,6 +588,8 @@ void ipath_verbs_unregister(void)
verbs_rcv = NULL;
verbs_timer_cb = NULL;
+ ipath_verbs_registered = 0;
+
mutex_unlock(&ipath_layer_mutex);
}
diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c
index e1dc4f75706..6318067ab5e 100644
--- a/drivers/infiniband/hw/ipath/ipath_pe800.c
+++ b/drivers/infiniband/hw/ipath/ipath_pe800.c
@@ -972,6 +972,8 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
/* Use ERROR so it shows up in logs, etc. */
ipath_dev_err(dd, "Resetting PE-800 unit %u\n",
dd->ipath_unit);
+ /* keep chip from being accessed in a few places */
+ dd->ipath_flags &= ~(IPATH_INITTED|IPATH_PRESENT);
val = dd->ipath_control | INFINIPATH_C_RESET;
ipath_write_kreg(dd, dd->ipath_kregs->kr_control, val);
mb();
@@ -997,6 +999,8 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd)
if ((r = pci_enable_device(dd->pcidev)))
ipath_dev_err(dd, "pci_enable_device failed after "
"reset: %d\n", r);
+ /* whether it worked or not, mark as present, again */
+ dd->ipath_flags |= IPATH_PRESENT;
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision);
if (val == dd->ipath_revision) {
ipath_cdbg(VERBOSE, "Got matching revision "
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
index 1e59750c5f6..402126eb79c 100644
--- a/drivers/infiniband/hw/ipath/ipath_registers.h
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -34,8 +34,9 @@
#define _IPATH_REGISTERS_H
/*
- * This file should only be included by kernel source, and by the diags.
- * It defines the registers, and their contents, for the InfiniPath HT-400 chip
+ * This file should only be included by kernel source, and by the diags. It
+ * defines the registers, and their contents, for the InfiniPath HT-400
+ * chip.
*/
/*
@@ -156,8 +157,10 @@
#define INFINIPATH_IBCC_FLOWCTRLWATERMARK_SHIFT 8
#define INFINIPATH_IBCC_LINKINITCMD_MASK 0x3ULL
#define INFINIPATH_IBCC_LINKINITCMD_DISABLE 1
-#define INFINIPATH_IBCC_LINKINITCMD_POLL 2 /* cycle through TS1/TS2 till OK */
-#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3 /* wait for TS1, then go on */
+/* cycle through TS1/TS2 till OK */
+#define INFINIPATH_IBCC_LINKINITCMD_POLL 2
+/* wait for TS1, then go on */
+#define INFINIPATH_IBCC_LINKINITCMD_SLEEP 3
#define INFINIPATH_IBCC_LINKINITCMD_SHIFT 16
#define INFINIPATH_IBCC_LINKCMD_MASK 0x3ULL
#define INFINIPATH_IBCC_LINKCMD_INIT 1 /* move to 0x11 */
@@ -182,7 +185,8 @@
#define INFINIPATH_IBCS_LINKSTATE_SHIFT 4
#define INFINIPATH_IBCS_TXREADY 0x40000000
#define INFINIPATH_IBCS_TXCREDITOK 0x80000000
-/* link training states (shift by INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */
+/* link training states (shift by
+ INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) */
#define INFINIPATH_IBCS_LT_STATE_DISABLED 0x00
#define INFINIPATH_IBCS_LT_STATE_LINKUP 0x01
#define INFINIPATH_IBCS_LT_STATE_POLLACTIVE 0x02
@@ -267,10 +271,12 @@
/* kr_serdesconfig0 bits */
#define INFINIPATH_SERDC0_RESET_MASK 0xfULL /* overal reset bits */
#define INFINIPATH_SERDC0_RESET_PLL 0x10000000ULL /* pll reset */
-#define INFINIPATH_SERDC0_TXIDLE 0xF000ULL /* tx idle enables (per lane) */
-#define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL /* rx detect enables (per lane) */
-#define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL /* L1 Power down; use with RXDETECT,
- Otherwise not used on IB side */
+/* tx idle enables (per lane) */
+#define INFINIPATH_SERDC0_TXIDLE 0xF000ULL
+/* rx detect enables (per lane) */
+#define INFINIPATH_SERDC0_RXDETECT_EN 0xF0000ULL
+/* L1 Power down; use with RXDETECT, Otherwise not used on IB side */
+#define INFINIPATH_SERDC0_L1PWR_DN 0xF0ULL
/* kr_xgxsconfig bits */
#define INFINIPATH_XGXS_RESET 0x7ULL
@@ -390,12 +396,13 @@ struct ipath_kregs {
ipath_kreg kr_txintmemsize;
ipath_kreg kr_xgxsconfig;
ipath_kreg kr_ibpllcfg;
- /* use these two (and the following N ports) only with ipath_k*_kreg64_port();
- * not *kreg64() */
+ /* use these two (and the following N ports) only with
+ * ipath_k*_kreg64_port(); not *kreg64() */
ipath_kreg kr_rcvhdraddr;
ipath_kreg kr_rcvhdrtailaddr;
- /* remaining registers are not present on all types of infinipath chips */
+ /* remaining registers are not present on all types of infinipath
+ chips */
ipath_kreg kr_rcvpktledcnt;
ipath_kreg kr_pcierbuftestreg0;
ipath_kreg kr_pcierbuftestreg1;
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index f232e77b78e..eb81424b3c5 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -531,19 +531,12 @@ int ipath_post_rc_send(struct ipath_qp *qp, struct ib_send_wr *wr)
}
wqe->wr.num_sge = j;
qp->s_head = next;
- /*
- * Wake up the send tasklet if the QP is not waiting
- * for an RNR timeout.
- */
- next = qp->s_rnr_timeout;
spin_unlock_irqrestore(&qp->s_lock, flags);
- if (next == 0) {
- if (qp->ibqp.qp_type == IB_QPT_UC)
- ipath_do_uc_send((unsigned long) qp);
- else
- ipath_do_rc_send((unsigned long) qp);
- }
+ if (qp->ibqp.qp_type == IB_QPT_UC)
+ ipath_do_uc_send((unsigned long) qp);
+ else
+ ipath_do_rc_send((unsigned long) qp);
ret = 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
index 32acd8048b4..f323791cc49 100644
--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -711,10 +711,22 @@ static struct attribute_group dev_attr_group = {
* enters diag mode. A device reset is quite likely to crash the
* machine entirely, so we don't want to normally make it
* available.
+ *
+ * Called with ipath_mutex held.
*/
int ipath_expose_reset(struct device *dev)
{
- return device_create_file(dev, &dev_attr_reset);
+ static int exposed;
+ int ret;
+
+ if (!exposed) {
+ ret = device_create_file(dev, &dev_attr_reset);
+ exposed = 1;
+ }
+ else
+ ret = 0;
+
+ return ret;
}
int ipath_driver_create_group(struct device_driver *drv)
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
index 01cfb30ee16..e606daf8321 100644
--- a/drivers/infiniband/hw/ipath/ipath_ud.c
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -46,8 +46,10 @@
* This is called from ipath_post_ud_send() to forward a WQE addressed
* to the same HCA.
*/
-static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
- u32 length, struct ib_send_wr *wr, struct ib_wc *wc)
+static void ipath_ud_loopback(struct ipath_qp *sqp,
+ struct ipath_sge_state *ss,
+ u32 length, struct ib_send_wr *wr,
+ struct ib_wc *wc)
{
struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
struct ipath_qp *qp;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index 8d2558a01f3..cb9e387c301 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -449,7 +449,6 @@ static void ipath_ib_timer(void *arg)
{
struct ipath_ibdev *dev = (struct ipath_ibdev *) arg;
struct ipath_qp *resend = NULL;
- struct ipath_qp *rnr = NULL;
struct list_head *last;
struct ipath_qp *qp;
unsigned long flags;
@@ -465,32 +464,18 @@ static void ipath_ib_timer(void *arg)
last = &dev->pending[dev->pending_index];
while (!list_empty(last)) {
qp = list_entry(last->next, struct ipath_qp, timerwait);
- if (last->next == LIST_POISON1 ||
- last->next != &qp->timerwait ||
- qp->timerwait.prev != last) {
- INIT_LIST_HEAD(last);
- } else {
- list_del(&qp->timerwait);
- qp->timerwait.prev = (struct list_head *) resend;
- resend = qp;
- atomic_inc(&qp->refcount);
- }
+ list_del(&qp->timerwait);
+ qp->timer_next = resend;
+ resend = qp;
+ atomic_inc(&qp->refcount);
}
last = &dev->rnrwait;
if (!list_empty(last)) {
qp = list_entry(last->next, struct ipath_qp, timerwait);
if (--qp->s_rnr_timeout == 0) {
do {
- if (last->next == LIST_POISON1 ||
- last->next != &qp->timerwait ||
- qp->timerwait.prev != last) {
- INIT_LIST_HEAD(last);
- break;
- }
list_del(&qp->timerwait);
- qp->timerwait.prev =
- (struct list_head *) rnr;
- rnr = qp;
+ tasklet_hi_schedule(&qp->s_task);
if (list_empty(last))
break;
qp = list_entry(last->next, struct ipath_qp,
@@ -530,8 +515,7 @@ static void ipath_ib_timer(void *arg)
spin_unlock_irqrestore(&dev->pending_lock, flags);
/* XXX What if timer fires again while this is running? */
- for (qp = resend; qp != NULL;
- qp = (struct ipath_qp *) qp->timerwait.prev) {
+ for (qp = resend; qp != NULL; qp = qp->timer_next) {
struct ib_wc wc;
spin_lock_irqsave(&qp->s_lock, flags);
@@ -545,9 +529,6 @@ static void ipath_ib_timer(void *arg)
if (atomic_dec_and_test(&qp->refcount))
wake_up(&qp->wait);
}
- for (qp = rnr; qp != NULL;
- qp = (struct ipath_qp *) qp->timerwait.prev)
- tasklet_hi_schedule(&qp->s_task);
}
/**
@@ -556,9 +537,9 @@ static void ipath_ib_timer(void *arg)
*
* This is called from ipath_intr() at interrupt level when a PIO buffer is
* available after ipath_verbs_send() returned an error that no buffers were
- * available. Return 0 if we consumed all the PIO buffers and we still have
+ * available. Return 1 if we consumed all the PIO buffers and we still have
* QPs waiting for buffers (for now, just do a tasklet_hi_schedule and
- * return one).
+ * return zero).
*/
static int ipath_ib_piobufavail(void *arg)
{
@@ -579,7 +560,7 @@ static int ipath_ib_piobufavail(void *arg)
spin_unlock_irqrestore(&dev->pending_lock, flags);
bail:
- return 1;
+ return 0;
}
static int ipath_query_device(struct ib_device *ibdev,
@@ -1159,7 +1140,7 @@ static ssize_t show_stats(struct class_device *cdev, char *buf)
len = sprintf(buf,
"RC resends %d\n"
- "RC QACKs %d\n"
+ "RC no QACK %d\n"
"RC ACKs %d\n"
"RC SEQ NAKs %d\n"
"RC RDMA seq %d\n"
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index fcafbc7c9e7..4f8d59300e9 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -282,7 +282,8 @@ struct ipath_srq {
*/
struct ipath_qp {
struct ib_qp ibqp;
- struct ipath_qp *next; /* link list for QPN hash table */
+ struct ipath_qp *next; /* link list for QPN hash table */
+ struct ipath_qp *timer_next; /* link list for ipath_ib_timer() */
struct list_head piowait; /* link for wait PIO buf */
struct list_head timerwait; /* link for waiting for timeouts */
struct ib_ah_attr remote_ah_attr;
diff --git a/drivers/infiniband/hw/ipath/ips_common.h b/drivers/infiniband/hw/ipath/ips_common.h
index 410a764dfce..ab7cbbbfd03 100644
--- a/drivers/infiniband/hw/ipath/ips_common.h
+++ b/drivers/infiniband/hw/ipath/ips_common.h
@@ -95,7 +95,7 @@ struct ether_header {
__u8 seq_num;
__le32 len;
/* MUST be of word size due to PIO write requirements */
- __u32 csum;
+ __le32 csum;
__le16 csum_offset;
__le16 flags;
__u16 first_2_bytes;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 565a24b1756..a2eae8a3016 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -306,7 +306,7 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port,
goto out;
}
- memcpy(gid->raw + 8, out_mad->data + (index % 8) * 16, 8);
+ memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
out:
kfree(in_mad);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a34e3d91d9e..ba325f16d07 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -403,6 +403,27 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
case EVIOCGID:
if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
return -EFAULT;
+ return 0;
+
+ case EVIOCGREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (put_user(dev->rep[REP_DELAY], ip))
+ return -EFAULT;
+ if (put_user(dev->rep[REP_PERIOD], ip + 1))
+ return -EFAULT;
+ return 0;
+
+ case EVIOCSREP:
+ if (!test_bit(EV_REP, dev->evbit))
+ return -ENOSYS;
+ if (get_user(u, ip))
+ return -EFAULT;
+ if (get_user(v, ip + 1))
+ return -EFAULT;
+
+ input_event(dev, EV_REP, REP_DELAY, u);
+ input_event(dev, EV_REP, REP_PERIOD, v);
return 0;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a935abeffff..3038c268917 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -155,6 +155,9 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
if (code > SND_MAX || !test_bit(code, dev->sndbit))
return;
+ if (!!test_bit(code, dev->snd) != !!value)
+ change_bit(code, dev->snd);
+
if (dev->event) dev->event(dev, type, code, value);
break;
@@ -286,19 +289,19 @@ static struct input_device_id *input_match_device(struct input_device_id *id, st
for (; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
- if (id->id.bustype != dev->id.bustype)
+ if (id->bustype != dev->id.bustype)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
- if (id->id.vendor != dev->id.vendor)
+ if (id->vendor != dev->id.vendor)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
- if (id->id.product != dev->id.product)
+ if (id->product != dev->id.product)
continue;
if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)
- if (id->id.version != dev->id.version)
+ if (id->version != dev->id.version)
continue;
MATCH_BIT(evbit, EV_MAX);
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
index bc61cf8cfc6..1d238a9d52d 100644
--- a/drivers/input/keyboard/spitzkbd.c
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -53,8 +53,8 @@ static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */
0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */
KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */
- SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
- SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */
+ SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */
+ SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */
SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */
KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */
};
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 4b415d9b012..36cd2e07fce 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -273,6 +273,18 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] = {
{ KE_END, 0 }
};
+static struct key_entry keymap_fujitsu_n3510[] = {
+ { KE_KEY, 0x11, KEY_PROG1 },
+ { KE_KEY, 0x12, KEY_PROG2 },
+ { KE_KEY, 0x36, KEY_WWW },
+ { KE_KEY, 0x31, KEY_MAIL },
+ { KE_KEY, 0x71, KEY_STOPCD },
+ { KE_KEY, 0x72, KEY_PLAYPAUSE },
+ { KE_KEY, 0x74, KEY_REWIND },
+ { KE_KEY, 0x78, KEY_FORWARD },
+ { KE_END, 0 }
+};
+
static struct key_entry keymap_wistron_ms2141[] = {
{ KE_KEY, 0x11, KEY_PROG1 },
{ KE_KEY, 0x12, KEY_PROG2 },
@@ -323,6 +335,24 @@ static struct dmi_system_id dmi_ids[] = {
},
{
.callback = dmi_matched,
+ .ident = "Fujitsu-Siemens Amilo M7400",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "),
+ },
+ .driver_data = keymap_fs_amilo_pro_v2000
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Fujitsu N3510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "N3510"),
+ },
+ .driver_data = keymap_fujitsu_n3510
+ },
+ {
+ .callback = dmi_matched,
.ident = "Acer Aspire 1500",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 32d70ed8f41..136321a2cfd 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -302,8 +302,10 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
* Check if this is a new device announcement (0xAA 0x00)
*/
if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) {
- if (psmouse->pktcnt == 1)
+ if (psmouse->pktcnt == 1) {
+ psmouse->last = jiffies;
goto out;
+ }
if (psmouse->packet[1] == PSMOUSE_RET_ID) {
__psmouse_set_state(psmouse, PSMOUSE_IGNORE);
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index 9a922164425..cc21914fbc7 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -67,14 +67,14 @@ static inline int i8042_platform_init(void)
* On some platforms touching the i8042 data register region can do really
* bad things. Because of this the region is always reserved on such boxes.
*/
-#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC64)
+#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) && !defined(CONFIG_PPC_MERGE)
if (!request_region(I8042_DATA_REG, 16, "i8042"))
return -EBUSY;
#endif
i8042_reset = 1;
-#if defined(CONFIG_PPC64)
+#if defined(CONFIG_PPC_MERGE)
if (check_legacy_ioport(I8042_DATA_REG))
return -EBUSY;
if (!request_region(I8042_DATA_REG, 16, "i8042"))
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 46d1fec2cfd..1494175ac6f 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -2,6 +2,8 @@
* ADS7846 based touchscreen and sensor driver
*
* Copyright (c) 2005 David Brownell
+ * Copyright (c) 2006 Nokia Corporation
+ * Various changes: Imre Deak <imre.deak@nokia.com>
*
* Using code from:
* - corgi_ts.c
@@ -34,17 +36,25 @@
/*
- * This code has been lightly tested on an ads7846.
+ * This code has been tested on an ads7846 / N770 device.
* Support for ads7843 and ads7845 has only been stubbed in.
*
- * Not yet done: investigate the values reported. Are x/y/pressure
- * event values sane enough for X11? How accurate are the temperature
- * and voltage readings? (System-specific calibration should support
+ * Not yet done: How accurate are the temperature and voltage
+ * readings? (System-specific calibration should support
* accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
*
+ * IRQ handling needs a workaround because of a shortcoming in handling
+ * edge triggered IRQs on some platforms like the OMAP1/2. These
+ * platforms don't handle the ARM lazy IRQ disabling properly, thus we
+ * have to maintain our own SW IRQ disabled status. This should be
+ * removed as soon as the affected platform's IRQ handling is fixed.
+ *
* app note sbaa036 talks in more detail about accurate sampling...
* that ought to help in situations like LCDs inducing noise (which
* can also be helped by using synch signals) and more generally.
+ * This driver tries to utilize the measures described in the app
+ * note. The strength of filtering can be set in the board-* specific
+ * files.
*/
#define TS_POLL_PERIOD msecs_to_jiffies(10)
@@ -61,6 +71,7 @@ struct ts_event {
__be16 x;
__be16 y;
__be16 z1, z2;
+ int ignore;
};
struct ads7846 {
@@ -71,12 +82,23 @@ struct ads7846 {
u16 model;
u16 vref_delay_usecs;
u16 x_plate_ohms;
+ u16 pressure_max;
- u8 read_x, read_y, read_z1, read_z2;
+ u8 read_x, read_y, read_z1, read_z2, pwrdown;
+ u16 dummy; /* for the pwrdown read */
struct ts_event tc;
- struct spi_transfer xfer[8];
- struct spi_message msg;
+ struct spi_transfer xfer[10];
+ struct spi_message msg[5];
+ struct spi_message *last_msg;
+ int msg_idx;
+ int read_cnt;
+ int read_rep;
+ int last_read;
+
+ u16 debounce_max;
+ u16 debounce_tol;
+ u16 debounce_rep;
spinlock_t lock;
struct timer_list timer; /* P: lock */
@@ -84,6 +106,9 @@ struct ads7846 {
unsigned pending:1; /* P: lock */
// FIXME remove "irq_disabled"
unsigned irq_disabled:1; /* P: lock */
+ unsigned disabled:1;
+
+ int (*get_pendown_state)(void);
};
/* leave chip selected when we're done, for quicker re-select? */
@@ -125,7 +150,9 @@ struct ads7846 {
#define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON)
#define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON)
#define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON)
-#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */
+
+#define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON)
+#define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */
/* single-ended samples need to first power up reference voltage;
* we leave both ADC and VREF powered
@@ -152,6 +179,15 @@ struct ser_req {
struct spi_transfer xfer[6];
};
+static void ads7846_enable(struct ads7846 *ts);
+static void ads7846_disable(struct ads7846 *ts);
+
+static int device_suspended(struct device *dev)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ return dev->power.power_state.event != PM_EVENT_ON || ts->disabled;
+}
+
static int ads7846_read12_ser(struct device *dev, unsigned command)
{
struct spi_device *spi = to_spi_device(dev);
@@ -164,7 +200,7 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
if (!req)
return -ENOMEM;
- INIT_LIST_HEAD(&req->msg.transfers);
+ spi_message_init(&req->msg);
/* activate reference, so it has time to settle; */
req->ref_on = REF_ON;
@@ -204,8 +240,10 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
for (i = 0; i < 6; i++)
spi_message_add_tail(&req->xfer[i], &req->msg);
+ ts->irq_disabled = 1;
disable_irq(spi->irq);
status = spi_sync(spi, &req->msg);
+ ts->irq_disabled = 0;
enable_irq(spi->irq);
if (req->msg.status)
@@ -233,6 +271,52 @@ SHOW(temp1)
SHOW(vaux)
SHOW(vbatt)
+static int is_pen_down(struct device *dev)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+
+ return ts->pendown;
+}
+
+static ssize_t ads7846_pen_down_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", is_pen_down(dev));
+}
+
+static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
+
+static ssize_t ads7846_disable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", ts->disabled);
+}
+
+static ssize_t ads7846_disable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ads7846 *ts = dev_get_drvdata(dev);
+ char *endp;
+ int i;
+
+ i = simple_strtoul(buf, &endp, 10);
+ spin_lock_irq(&ts->lock);
+
+ if (i)
+ ads7846_disable(ts);
+ else
+ ads7846_enable(ts);
+
+ spin_unlock_irq(&ts->lock);
+
+ return count;
+}
+
+static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
+
/*--------------------------------------------------------------------------*/
/*
@@ -264,7 +348,7 @@ static void ads7846_rx(void *ads)
if (x == MAX_12BIT)
x = 0;
- if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
+ if (likely(x && z1 && !device_suspended(&ts->spi->dev))) {
/* compute touch pressure resistance using equation #2 */
Rt = z2;
Rt -= z1;
@@ -275,6 +359,14 @@ static void ads7846_rx(void *ads)
} else
Rt = 0;
+ /* Sample found inconsistent by debouncing or pressure is beyond
+ * the maximum. Don't report it to user space, repeat at least
+ * once more the measurement */
+ if (ts->tc.ignore || Rt > ts->pressure_max) {
+ mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+ return;
+ }
+
/* NOTE: "pendown" is inferred from pressure; we don't rely on
* being able to check nPENIRQ status, or "friendly" trigger modes
* (both-edges is much better than just-falling or low-level).
@@ -296,11 +388,13 @@ static void ads7846_rx(void *ads)
if (Rt) {
input_report_abs(input_dev, ABS_X, x);
input_report_abs(input_dev, ABS_Y, y);
- input_report_abs(input_dev, ABS_PRESSURE, Rt);
sync = 1;
}
- if (sync)
+
+ if (sync) {
+ input_report_abs(input_dev, ABS_PRESSURE, Rt);
input_sync(input_dev);
+ }
#ifdef VERBOSE
if (Rt || ts->pendown)
@@ -308,80 +402,138 @@ static void ads7846_rx(void *ads)
x, y, Rt, Rt ? "" : " UP");
#endif
- /* don't retrigger while we're suspended */
spin_lock_irqsave(&ts->lock, flags);
ts->pendown = (Rt != 0);
- ts->pending = 0;
+ mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
- if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) {
- if (ts->pendown)
- mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
- else if (ts->irq_disabled) {
- ts->irq_disabled = 0;
- enable_irq(ts->spi->irq);
+ spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void ads7846_debounce(void *ads)
+{
+ struct ads7846 *ts = ads;
+ struct spi_message *m;
+ struct spi_transfer *t;
+ int val;
+ int status;
+
+ m = &ts->msg[ts->msg_idx];
+ t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+ val = (*(u16 *)t->rx_buf) >> 3;
+ if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
+ /* Repeat it, if this was the first read or the read
+ * wasn't consistent enough. */
+ if (ts->read_cnt < ts->debounce_max) {
+ ts->last_read = val;
+ ts->read_cnt++;
+ } else {
+ /* Maximum number of debouncing reached and still
+ * not enough number of consistent readings. Abort
+ * the whole sample, repeat it in the next sampling
+ * period.
+ */
+ ts->tc.ignore = 1;
+ ts->read_cnt = 0;
+ /* Last message will contain ads7846_rx() as the
+ * completion function.
+ */
+ m = ts->last_msg;
}
+ /* Start over collecting consistent readings. */
+ ts->read_rep = 0;
+ } else {
+ if (++ts->read_rep > ts->debounce_rep) {
+ /* Got a good reading for this coordinate,
+ * go for the next one. */
+ ts->tc.ignore = 0;
+ ts->msg_idx++;
+ ts->read_cnt = 0;
+ ts->read_rep = 0;
+ m++;
+ } else
+ /* Read more values that are consistent. */
+ ts->read_cnt++;
}
-
- spin_unlock_irqrestore(&ts->lock, flags);
+ status = spi_async(ts->spi, m);
+ if (status)
+ dev_err(&ts->spi->dev, "spi_async --> %d\n",
+ status);
}
static void ads7846_timer(unsigned long handle)
{
struct ads7846 *ts = (void *)handle;
int status = 0;
- unsigned long flags;
+
+ spin_lock_irq(&ts->lock);
+
+ if (unlikely(ts->msg_idx && !ts->pendown)) {
+ /* measurment cycle ended */
+ if (!device_suspended(&ts->spi->dev)) {
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+ }
+ ts->pending = 0;
+ ts->msg_idx = 0;
+ } else {
+ /* pen is still down, continue with the measurement */
+ ts->msg_idx = 0;
+ status = spi_async(ts->spi, &ts->msg[0]);
+ if (status)
+ dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
+ }
+
+ spin_unlock_irq(&ts->lock);
+}
+
+static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
+{
+ struct ads7846 *ts = handle;
+ unsigned long flags;
spin_lock_irqsave(&ts->lock, flags);
- if (!ts->pending) {
- ts->pending = 1;
+ if (likely(ts->get_pendown_state())) {
if (!ts->irq_disabled) {
+ /* REVISIT irq logic for many ARM chips has cloned a
+ * bug wherein disabling an irq in its handler won't
+ * work;(it's disabled lazily, and too late to work.
+ * until all their irq logic is fixed, we must shadow
+ * that state here.
+ */
ts->irq_disabled = 1;
disable_irq(ts->spi->irq);
+ ts->pending = 1;
+ mod_timer(&ts->timer, jiffies);
}
- status = spi_async(ts->spi, &ts->msg);
- if (status)
- dev_err(&ts->spi->dev, "spi_async --> %d\n",
- status);
}
spin_unlock_irqrestore(&ts->lock, flags);
-}
-static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
-{
- ads7846_timer((unsigned long) handle);
return IRQ_HANDLED;
}
/*--------------------------------------------------------------------------*/
-static int
-ads7846_suspend(struct spi_device *spi, pm_message_t message)
+/* Must be called with ts->lock held */
+static void ads7846_disable(struct ads7846 *ts)
{
- struct ads7846 *ts = dev_get_drvdata(&spi->dev);
- unsigned long flags;
+ if (ts->disabled)
+ return;
- spin_lock_irqsave(&ts->lock, flags);
-
- spi->dev.power.power_state = message;
+ ts->disabled = 1;
/* are we waiting for IRQ, or polling? */
- if (!ts->pendown) {
- if (!ts->irq_disabled) {
- ts->irq_disabled = 1;
- disable_irq(ts->spi->irq);
- }
+ if (!ts->pending) {
+ ts->irq_disabled = 1;
+ disable_irq(ts->spi->irq);
} else {
- /* polling; force a final SPI completion;
- * that will clean things up neatly
+ /* the timer will run at least once more, and
+ * leave everything in a clean state, IRQ disabled
*/
- if (!ts->pending)
- mod_timer(&ts->timer, jiffies);
-
- while (ts->pendown || ts->pending) {
- spin_unlock_irqrestore(&ts->lock, flags);
- udelay(10);
- spin_lock_irqsave(&ts->lock, flags);
+ while (ts->pending) {
+ spin_unlock_irq(&ts->lock);
+ msleep(1);
+ spin_lock_irq(&ts->lock);
}
}
@@ -389,17 +541,45 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message)
* leave it that way after every request
*/
- spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+/* Must be called with ts->lock held */
+static void ads7846_enable(struct ads7846 *ts)
+{
+ if (!ts->disabled)
+ return;
+
+ ts->disabled = 0;
+ ts->irq_disabled = 0;
+ enable_irq(ts->spi->irq);
+}
+
+static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
+{
+ struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+
+ spin_lock_irq(&ts->lock);
+
+ spi->dev.power.power_state = message;
+ ads7846_disable(ts);
+
+ spin_unlock_irq(&ts->lock);
+
return 0;
+
}
static int ads7846_resume(struct spi_device *spi)
{
struct ads7846 *ts = dev_get_drvdata(&spi->dev);
- ts->irq_disabled = 0;
- enable_irq(ts->spi->irq);
+ spin_lock_irq(&ts->lock);
+
spi->dev.power.power_state = PMSG_ON;
+ ads7846_enable(ts);
+
+ spin_unlock_irq(&ts->lock);
+
return 0;
}
@@ -408,6 +588,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
struct ads7846 *ts;
struct input_dev *input_dev;
struct ads7846_platform_data *pdata = spi->dev.platform_data;
+ struct spi_message *m;
struct spi_transfer *x;
int err;
@@ -428,6 +609,11 @@ static int __devinit ads7846_probe(struct spi_device *spi)
return -EINVAL;
}
+ if (pdata->get_pendown_state == NULL) {
+ dev_dbg(&spi->dev, "no get_pendown_state function?\n");
+ return -EINVAL;
+ }
+
/* We'd set the wordsize to 12 bits ... except that some controllers
* will then treat the 8 bit command words as 12 bits (and drop the
* four MSBs of the 12 bit result). Result: inputs must be shifted
@@ -451,9 +637,21 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->timer.data = (unsigned long) ts;
ts->timer.function = ads7846_timer;
+ spin_lock_init(&ts->lock);
+
ts->model = pdata->model ? : 7846;
ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+ ts->pressure_max = pdata->pressure_max ? : ~0;
+ if (pdata->debounce_max) {
+ ts->debounce_max = pdata->debounce_max;
+ ts->debounce_tol = pdata->debounce_tol;
+ ts->debounce_rep = pdata->debounce_rep;
+ if (ts->debounce_rep > ts->debounce_max + 1)
+ ts->debounce_rep = ts->debounce_max - 1;
+ } else
+ ts->debounce_tol = ~0;
+ ts->get_pendown_state = pdata->get_pendown_state;
snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
@@ -477,60 +675,100 @@ static int __devinit ads7846_probe(struct spi_device *spi)
/* set up the transfers to read touchscreen state; this assumes we
* use formula #2 for pressure, not #3.
*/
- INIT_LIST_HEAD(&ts->msg.transfers);
+ m = &ts->msg[0];
x = ts->xfer;
+ spi_message_init(m);
+
/* y- still on; turn on only y+ (and ADC) */
ts->read_y = READ_Y;
x->tx_buf = &ts->read_y;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
x->rx_buf = &ts->tc.y;
x->len = 2;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
+
+ m++;
+ spi_message_init(m);
+
+ /* turn y- off, x+ on, then leave in lowpower */
+ x++;
+ ts->read_x = READ_X;
+ x->tx_buf = &ts->read_x;
+ x->len = 1;
+ spi_message_add_tail(x, m);
+
+ x++;
+ x->rx_buf = &ts->tc.x;
+ x->len = 2;
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
/* turn y+ off, x- on; we'll use formula #2 */
if (ts->model == 7846) {
+ m++;
+ spi_message_init(m);
+
x++;
ts->read_z1 = READ_Z1;
x->tx_buf = &ts->read_z1;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
x->rx_buf = &ts->tc.z1;
x->len = 2;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
+
+ m++;
+ spi_message_init(m);
x++;
ts->read_z2 = READ_Z2;
x->tx_buf = &ts->read_z2;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
x->rx_buf = &ts->tc.z2;
x->len = 2;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
+
+ m->complete = ads7846_debounce;
+ m->context = ts;
}
- /* turn y- off, x+ on, then leave in lowpower */
+ /* power down */
+ m++;
+ spi_message_init(m);
+
x++;
- ts->read_x = READ_X;
- x->tx_buf = &ts->read_x;
+ ts->pwrdown = PWRDOWN;
+ x->tx_buf = &ts->pwrdown;
x->len = 1;
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
x++;
- x->rx_buf = &ts->tc.x;
+ x->rx_buf = &ts->dummy;
x->len = 2;
CS_CHANGE(*x);
- spi_message_add_tail(x, &ts->msg);
+ spi_message_add_tail(x, m);
- ts->msg.complete = ads7846_rx;
- ts->msg.context = ts;
+ m->complete = ads7846_rx;
+ m->context = ts;
+
+ ts->last_msg = m;
if (request_irq(spi->irq, ads7846_irq,
SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
@@ -559,13 +797,27 @@ static int __devinit ads7846_probe(struct spi_device *spi)
device_create_file(&spi->dev, &dev_attr_vbatt);
device_create_file(&spi->dev, &dev_attr_vaux);
+ device_create_file(&spi->dev, &dev_attr_pen_down);
+
+ device_create_file(&spi->dev, &dev_attr_disable);
+
err = input_register_device(input_dev);
if (err)
- goto err_free_irq;
+ goto err_remove_attr;
return 0;
- err_free_irq:
+ err_remove_attr:
+ device_remove_file(&spi->dev, &dev_attr_disable);
+ device_remove_file(&spi->dev, &dev_attr_pen_down);
+ if (ts->model == 7846) {
+ device_remove_file(&spi->dev, &dev_attr_temp1);
+ device_remove_file(&spi->dev, &dev_attr_temp0);
+ }
+ if (ts->model != 7845)
+ device_remove_file(&spi->dev, &dev_attr_vbatt);
+ device_remove_file(&spi->dev, &dev_attr_vaux);
+
free_irq(spi->irq, ts);
err_free_mem:
input_free_device(input_dev);
@@ -577,20 +829,24 @@ static int __devexit ads7846_remove(struct spi_device *spi)
{
struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+ input_unregister_device(ts->input);
+
ads7846_suspend(spi, PMSG_SUSPEND);
- free_irq(ts->spi->irq, ts);
- if (ts->irq_disabled)
- enable_irq(ts->spi->irq);
+ device_remove_file(&spi->dev, &dev_attr_disable);
+ device_remove_file(&spi->dev, &dev_attr_pen_down);
if (ts->model == 7846) {
- device_remove_file(&spi->dev, &dev_attr_temp0);
device_remove_file(&spi->dev, &dev_attr_temp1);
+ device_remove_file(&spi->dev, &dev_attr_temp0);
}
if (ts->model != 7845)
device_remove_file(&spi->dev, &dev_attr_vbatt);
device_remove_file(&spi->dev, &dev_attr_vaux);
- input_unregister_device(ts->input);
+ free_irq(ts->spi->irq, ts);
+ /* suspend left the IRQ disabled */
+ enable_irq(ts->spi->irq);
+
kfree(ts);
dev_dbg(&spi->dev, "unregistered touchscreen\n");
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 1042987856f..5013703db0e 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -17,7 +17,7 @@
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <asm/irq.h>
+//#include <asm/irq.h>
#include <asm/arch/sharpsl.h>
#include <asm/arch/hardware.h>
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 6081941de1b..4070eff6f0f 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -315,10 +315,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
if (r1_bio->bios[mirror] == bio)
break;
- if (error == -ENOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
+ if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags);
set_bit(R1BIO_BarrierRetry, &r1_bio->state);
r1_bio->mddev->barriers_work = 0;
+ /* Don't rdev_dec_pending in this branch - keep it for the retry */
} else {
/*
* this branch is our 'one mirror IO has finished' event handler:
@@ -365,6 +366,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
}
}
}
+ rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
}
/*
*
@@ -374,11 +376,9 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
if (atomic_dec_and_test(&r1_bio->remaining)) {
if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
reschedule_retry(r1_bio);
- /* Don't dec_pending yet, we want to hold
- * the reference over the retry
- */
goto out;
}
+ /* it really is the end of this request */
if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
/* free extra copy of the data pages */
int i = bio->bi_vcnt;
@@ -393,8 +393,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
md_write_end(r1_bio->mddev);
raid_end_bio_io(r1_bio);
}
-
- rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
out:
if (to_put)
bio_put(to_put);
@@ -753,18 +751,24 @@ static int make_request(request_queue_t *q, struct bio * bio)
const int rw = bio_data_dir(bio);
int do_barriers;
- if (unlikely(!mddev->barriers_work && bio_barrier(bio))) {
- bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
- return 0;
- }
-
/*
* Register the new request and wait if the reconstruction
* thread has put up a bar for new requests.
* Continue immediately if no resync is active currently.
+ * We test barriers_work *after* md_write_start as md_write_start
+ * may cause the first superblock write, and that will check out
+ * if barriers work.
*/
+
md_write_start(mddev, bio); /* wait on superblock update early */
+ if (unlikely(!mddev->barriers_work && bio_barrier(bio))) {
+ if (rw == WRITE)
+ md_write_end(mddev);
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
wait_barrier(conf);
disk_stat_inc(mddev->gendisk, ios[rw]);
@@ -1404,10 +1408,11 @@ static void raid1d(mddev_t *mddev)
unplug = 1;
} else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
/* some requests in the r1bio were BIO_RW_BARRIER
- * requests which failed with -ENOTSUPP. Hohumm..
+ * requests which failed with -EOPNOTSUPP. Hohumm..
* Better resubmit without the barrier.
* We know which devices to resubmit for, because
* all others have had their bios[] entry cleared.
+ * We already have a nr_pending reference on these rdevs.
*/
int i;
clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 617012bc107..1440935414e 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1407,43 +1407,54 @@ static void raid10d(mddev_t *mddev)
if (s > (PAGE_SIZE>>9))
s = PAGE_SIZE >> 9;
+ rcu_read_lock();
do {
int d = r10_bio->devs[sl].devnum;
- rdev = conf->mirrors[d].rdev;
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
- test_bit(In_sync, &rdev->flags) &&
- sync_page_io(rdev->bdev,
- r10_bio->devs[sl].addr +
- sect + rdev->data_offset,
- s<<9,
- conf->tmppage, READ))
- success = 1;
- else {
- sl++;
- if (sl == conf->copies)
- sl = 0;
+ test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+ success = sync_page_io(rdev->bdev,
+ r10_bio->devs[sl].addr +
+ sect + rdev->data_offset,
+ s<<9,
+ conf->tmppage, READ);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
+ if (success)
+ break;
}
+ sl++;
+ if (sl == conf->copies)
+ sl = 0;
} while (!success && sl != r10_bio->read_slot);
+ rcu_read_unlock();
if (success) {
int start = sl;
/* write it back and re-read */
+ rcu_read_lock();
while (sl != r10_bio->read_slot) {
int d;
if (sl==0)
sl = conf->copies;
sl--;
d = r10_bio->devs[sl].devnum;
- rdev = conf->mirrors[d].rdev;
- atomic_add(s, &rdev->corrected_errors);
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+ atomic_add(s, &rdev->corrected_errors);
if (sync_page_io(rdev->bdev,
r10_bio->devs[sl].addr +
sect + rdev->data_offset,
s<<9, conf->tmppage, WRITE) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
}
}
sl = start;
@@ -1453,17 +1464,22 @@ static void raid10d(mddev_t *mddev)
sl = conf->copies;
sl--;
d = r10_bio->devs[sl].devnum;
- rdev = conf->mirrors[d].rdev;
+ rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
if (sync_page_io(rdev->bdev,
r10_bio->devs[sl].addr +
sect + rdev->data_offset,
s<<9, conf->tmppage, READ) == 0)
/* Well, this device is dead */
md_error(mddev, rdev);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
}
}
+ rcu_read_unlock();
} else {
/* Cannot read from anywhere -- bye bye array */
md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev);
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index f9d87b86492..320b3d9384b 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -616,7 +616,7 @@ static struct snd_kcontrol_new snd_cx88_capture_volume = {
* Only boards with eeprom and byte 1 at eeprom=1 have it
*/
-static struct pci_device_id cx88_audio_pci_tbl[] = {
+static struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
{0, }
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 6061c2d101a..88f0eef9cf3 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -621,9 +621,6 @@ static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct at91mci_host *host = mmc_priv(mmc);
unsigned long at91_master_clock = clk_get_rate(mci_clk);
- DBG("Clock %uHz, busmode %u, powermode %u, Vdd %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
-
if (host)
host->bus_mode = ios->bus_mode;
else
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c
index c0326bbc5f2..914d62b2406 100644
--- a/drivers/mmc/au1xmmc.c
+++ b/drivers/mmc/au1xmmc.c
@@ -720,10 +720,6 @@ static void au1xmmc_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
{
struct au1xmmc_host *host = mmc_priv(mmc);
- DBG("set_ios (power=%u, clock=%uHz, vdd=%u, mode=%u)\n",
- host->id, ios->power_mode, ios->clock, ios->vdd,
- ios->bus_mode);
-
if (ios->power_mode == MMC_POWER_OFF)
au1xmmc_set_power(host, 0);
else if (ios->power_mode == MMC_POWER_ON) {
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index ffb7f55d346..79358e223f5 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -102,6 +102,7 @@ struct imxmci_host {
#define IMXMCI_PEND_CPU_DATA_b 5
#define IMXMCI_PEND_CARD_XCHG_b 6
#define IMXMCI_PEND_SET_INIT_b 7
+#define IMXMCI_PEND_STARTED_b 8
#define IMXMCI_PEND_IRQ_m (1 << IMXMCI_PEND_IRQ_b)
#define IMXMCI_PEND_DMA_END_m (1 << IMXMCI_PEND_DMA_END_b)
@@ -111,6 +112,7 @@ struct imxmci_host {
#define IMXMCI_PEND_CPU_DATA_m (1 << IMXMCI_PEND_CPU_DATA_b)
#define IMXMCI_PEND_CARD_XCHG_m (1 << IMXMCI_PEND_CARD_XCHG_b)
#define IMXMCI_PEND_SET_INIT_m (1 << IMXMCI_PEND_SET_INIT_b)
+#define IMXMCI_PEND_STARTED_m (1 << IMXMCI_PEND_STARTED_b)
static void imxmci_stop_clock(struct imxmci_host *host)
{
@@ -131,23 +133,52 @@ static void imxmci_stop_clock(struct imxmci_host *host)
dev_dbg(mmc_dev(host->mmc), "imxmci_stop_clock blocked, no luck\n");
}
-static void imxmci_start_clock(struct imxmci_host *host)
+static int imxmci_start_clock(struct imxmci_host *host)
{
- int i = 0;
+ unsigned int trials = 0;
+ unsigned int delay_limit = 128;
+ unsigned long flags;
+
MMC_STR_STP_CLK &= ~STR_STP_CLK_STOP_CLK;
- while(i < 0x1000) {
- if(!(i & 0x7f))
- MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
- if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN) {
- /* Check twice before cut */
+ clear_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
+
+ /*
+ * Command start of the clock, this usually succeeds in less
+ * then 6 delay loops, but during card detection (low clockrate)
+ * it takes up to 5000 delay loops and sometimes fails for the first time
+ */
+ MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+
+ do {
+ unsigned int delay = delay_limit;
+
+ while(delay--){
if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
- return;
+ /* Check twice before cut */
+ if(MMC_STATUS & STATUS_CARD_BUS_CLK_RUN)
+ return 0;
+
+ if(test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+ return 0;
}
- i++;
- }
- dev_dbg(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+ local_irq_save(flags);
+ /*
+ * Ensure, that request is not doubled under all possible circumstances.
+ * It is possible, that cock running state is missed, because some other
+ * IRQ or schedule delays this function execution and the clocks has
+ * been already stopped by other means (response processing, SDHC HW)
+ */
+ if(!test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events))
+ MMC_STR_STP_CLK |= STR_STP_CLK_START_CLK;
+ local_irq_restore(flags);
+
+ } while(++trials<256);
+
+ dev_err(mmc_dev(host->mmc), "imxmci_start_clock blocked, no luck\n");
+
+ return -1;
}
static void imxmci_softreset(void)
@@ -498,7 +529,7 @@ static int imxmci_data_done(struct imxmci_host *host, unsigned int stat)
data_error = imxmci_finish_data(host, stat);
- if (host->req->stop && (data_error == MMC_ERR_NONE)) {
+ if (host->req->stop) {
imxmci_stop_clock(host);
imxmci_start_cmd(host, host->req->stop, 0);
} else {
@@ -622,6 +653,7 @@ static irqreturn_t imxmci_irq(int irq, void *devid, struct pt_regs *regs)
atomic_set(&host->stuck_timeout, 0);
host->status_reg = stat;
set_bit(IMXMCI_PEND_IRQ_b, &host->pending_events);
+ set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
tasklet_schedule(&host->tasklet);
return IRQ_RETVAL(handled);;
@@ -775,10 +807,6 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct imxmci_host *host = mmc_priv(mmc);
int prescaler;
- dev_dbg(mmc_dev(host->mmc), "clock %u power %u vdd %u width %u\n",
- ios->clock, ios->power_mode, ios->vdd,
- (ios->bus_width==MMC_BUS_WIDTH_4)?4:1);
-
if( ios->bus_width==MMC_BUS_WIDTH_4 ) {
host->actual_bus_width = MMC_BUS_WIDTH_4;
imx_gpio_mode(PB11_PF_SD_DAT3);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index da6ddd910fc..1ca2c8b9c9b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -59,21 +59,23 @@ static const unsigned int tacc_mant[] = {
/**
- * mmc_request_done - finish processing an MMC command
- * @host: MMC host which completed command
- * @mrq: MMC request which completed
+ * mmc_request_done - finish processing an MMC request
+ * @host: MMC host which completed request
+ * @mrq: MMC request which request
*
* MMC drivers should call this function when they have completed
- * their processing of a command. This should be called before the
- * data part of the command has completed.
+ * their processing of a request.
*/
void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
{
struct mmc_command *cmd = mrq->cmd;
- int err = mrq->cmd->error;
- pr_debug("MMC: req done (%02x): %d: %08x %08x %08x %08x\n",
- cmd->opcode, err, cmd->resp[0], cmd->resp[1],
- cmd->resp[2], cmd->resp[3]);
+ int err = cmd->error;
+
+ pr_debug("%s: req done (CMD%u): %d/%d/%d: %08x %08x %08x %08x\n",
+ mmc_hostname(host), cmd->opcode, err,
+ mrq->data ? mrq->data->error : 0,
+ mrq->stop ? mrq->stop->error : 0,
+ cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
if (err && cmd->retries) {
cmd->retries--;
@@ -97,8 +99,9 @@ EXPORT_SYMBOL(mmc_request_done);
void
mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
- pr_debug("MMC: starting cmd %02x arg %08x flags %08x\n",
- mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags);
+ pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
+ mmc_hostname(host), mrq->cmd->opcode,
+ mrq->cmd->arg, mrq->cmd->flags);
WARN_ON(host->card_busy == NULL);
@@ -312,6 +315,18 @@ void mmc_release_host(struct mmc_host *host)
EXPORT_SYMBOL(mmc_release_host);
+static inline void mmc_set_ios(struct mmc_host *host)
+{
+ struct mmc_ios *ios = &host->ios;
+
+ pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+ mmc_hostname(host), ios->clock, ios->bus_mode,
+ ios->power_mode, ios->chip_select, ios->vdd,
+ ios->bus_width);
+
+ host->ops->set_ios(host, ios);
+}
+
static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
{
int err;
@@ -364,7 +379,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
}
}
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
return MMC_ERR_NONE;
}
@@ -415,7 +430,7 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
ocr = 3 << bit;
host->ios.vdd = bit;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
} else {
ocr = 0;
}
@@ -549,6 +564,7 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
} else {
@@ -583,6 +599,7 @@ static void mmc_decode_csd(struct mmc_card *card)
csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
}
@@ -666,7 +683,7 @@ static void mmc_idle_cards(struct mmc_host *host)
struct mmc_command cmd;
host->ios.chip_select = MMC_CS_HIGH;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(1);
@@ -679,7 +696,7 @@ static void mmc_idle_cards(struct mmc_host *host)
mmc_delay(1);
host->ios.chip_select = MMC_CS_DONTCARE;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(1);
}
@@ -704,13 +721,13 @@ static void mmc_power_up(struct mmc_host *host)
host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_UP;
host->ios.bus_width = MMC_BUS_WIDTH_1;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(1);
host->ios.clock = host->f_min;
host->ios.power_mode = MMC_POWER_ON;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_delay(2);
}
@@ -723,7 +740,7 @@ static void mmc_power_off(struct mmc_host *host)
host->ios.chip_select = MMC_CS_DONTCARE;
host->ios.power_mode = MMC_POWER_OFF;
host->ios.bus_width = MMC_BUS_WIDTH_1;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
}
static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
@@ -971,7 +988,8 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host)
if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)
max_dtr = card->csd.max_dtr;
- pr_debug("MMC: selected %d.%03dMHz transfer rate\n",
+ pr_debug("%s: selected %d.%03dMHz transfer rate\n",
+ mmc_hostname(host),
max_dtr / 1000000, (max_dtr / 1000) % 1000);
return max_dtr;
@@ -1046,7 +1064,7 @@ static void mmc_setup(struct mmc_host *host)
} else {
host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
host->ios.clock = host->f_min;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
/*
* We should remember the OCR mask from the existing
@@ -1082,7 +1100,7 @@ static void mmc_setup(struct mmc_host *host)
* Ok, now switch to push-pull mode.
*/
host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
mmc_read_csds(host);
@@ -1128,7 +1146,7 @@ static void mmc_rescan(void *data)
* attached cards and the host support.
*/
host->ios.clock = mmc_calculate_clock(host);
- host->ops->set_ios(host, &host->ios);
+ mmc_set_ios(host);
}
mmc_release_host(host);
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 8eb2a2ede64..06bd1f4cb9b 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -187,6 +187,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
brq.cmd.opcode = MMC_WRITE_BLOCK;
brq.data.flags |= MMC_DATA_WRITE;
brq.data.blocks = 1;
+
+ /*
+ * Scale up the timeout by the r2w factor
+ */
+ brq.data.timeout_ns <<= card->csd.r2w_factor;
+ brq.data.timeout_clks <<= card->csd.r2w_factor;
}
if (brq.data.blocks > 1) {
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c
index df7e861e2fc..da8e4d7339c 100644
--- a/drivers/mmc/mmci.c
+++ b/drivers/mmc/mmci.c
@@ -402,9 +402,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct mmci_host *host = mmc_priv(mmc);
u32 clk = 0, pwr = 0;
- DBG(host, "clock %uHz busmode %u powermode %u Vdd %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->vdd);
-
if (ios->clock) {
if (ios->clock >= host->mclk) {
clk = MCI_CLK_BYPASS;
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c
index eb42cb34942..f97b472085c 100644
--- a/drivers/mmc/pxamci.c
+++ b/drivers/mmc/pxamci.c
@@ -198,7 +198,6 @@ static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd,
static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
{
- pr_debug("PXAMCI: request done\n");
host->mrq = NULL;
host->cmd = NULL;
host->data = NULL;
@@ -291,7 +290,7 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
pxamci_disable_irq(host, DATA_TRAN_DONE);
host->data = NULL;
- if (host->mrq->stop && data->error == MMC_ERR_NONE) {
+ if (host->mrq->stop) {
pxamci_stop_clock(host);
pxamci_start_cmd(host, host->mrq->stop, 0);
} else {
@@ -309,12 +308,10 @@ static irqreturn_t pxamci_irq(int irq, void *devid, struct pt_regs *regs)
ireg = readl(host->base + MMC_I_REG);
- pr_debug("PXAMCI: irq %08x\n", ireg);
-
if (ireg) {
unsigned stat = readl(host->base + MMC_STAT);
- pr_debug("PXAMCI: stat %08x\n", stat);
+ pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat);
if (ireg & END_CMD_RES)
handled |= pxamci_cmd_done(host, stat);
@@ -368,10 +365,6 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct pxamci_host *host = mmc_priv(mmc);
- pr_debug("pxamci_set_ios: clock %u power %u vdd %u.%02u\n",
- ios->clock, ios->power_mode, ios->vdd / 100,
- ios->vdd % 100);
-
if (ios->clock) {
unsigned int clk = CLOCKRATE / ios->clock;
if (CLOCKRATE / clk > ios->clock)
@@ -397,7 +390,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->cmdat |= CMDAT_INIT;
}
- pr_debug("pxamci_set_ios: clkrt = %x cmdat = %x\n",
+ pr_debug("PXAMCI: clkrt = %x cmdat = %x\n",
host->clkrt, host->cmdat);
}
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index bdbfca05002..b0053280ff2 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -570,10 +570,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_lock_irqsave(&host->lock, flags);
- DBG("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
- ios->vdd, ios->bus_width);
-
/*
* Reset the chip on each power off.
* Should clear out any weird states.
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 511f7b0b31d..39b3d97f891 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -931,10 +931,6 @@ static void wbsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct wbsd_host *host = mmc_priv(mmc);
u8 clk, setup, pwr;
- DBGF("clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
- ios->clock, ios->bus_mode, ios->power_mode, ios->chip_select,
- ios->vdd, ios->bus_width);
-
spin_lock_bh(&host->lock);
/*
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 9788b1ef2e7..f7235c9bc42 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -106,6 +106,7 @@
* 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings.
* 0.52: 20 Jan 2006: Add MSI/MSIX support.
* 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
+ * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -117,7 +118,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.53"
+#define FORCEDETH_VERSION "0.54"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -710,6 +711,72 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
}
}
+static int using_multi_irqs(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+ ((np->msi_flags & NV_MSI_X_ENABLED) &&
+ ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1)))
+ return 0;
+ else
+ return 1;
+}
+
+static void nv_enable_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
+ } else {
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ }
+}
+
+static void nv_disable_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
+ } else {
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+ }
+}
+
+/* In MSIX mode, a write to irqmask behaves as XOR */
+static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask)
+{
+ u8 __iomem *base = get_hwbase(dev);
+
+ writel(mask, base + NvRegIrqMask);
+}
+
+static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+
+ if (np->msi_flags & NV_MSI_X_ENABLED) {
+ writel(mask, base + NvRegIrqMask);
+ } else {
+ if (np->msi_flags & NV_MSI_ENABLED)
+ writel(0, base + NvRegMSIIrqMask);
+ writel(0, base + NvRegIrqMask);
+ }
+}
+
#define MII_READ (-1)
/* mii_rw: read/write a register on the PHY.
*
@@ -1019,24 +1086,25 @@ static void nv_do_rx_refill(unsigned long data)
struct net_device *dev = (struct net_device *) data;
struct fe_priv *np = netdev_priv(dev);
-
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
} else {
disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
if (nv_alloc_rx(dev)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- enable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
} else {
enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
}
@@ -1668,15 +1736,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
* guessed, there is probably a simpler approach.
* Changing the MTU is a rare event, it shouldn't matter.
*/
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
- } else {
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
- disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
- }
+ nv_disable_irq(dev);
spin_lock_bh(&dev->xmit_lock);
spin_lock(&np->lock);
/* stop engines */
@@ -1709,15 +1769,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
nv_start_tx(dev);
spin_unlock(&np->lock);
spin_unlock_bh(&dev->xmit_lock);
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- enable_irq(dev->irq);
- } else {
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
- enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
- }
+ nv_enable_irq(dev);
}
return 0;
}
@@ -2108,16 +2160,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
if (!(events & np->irqmask))
break;
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_tx_done(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
if (events & (NVREG_IRQ_TX_ERR)) {
dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
dev->name, events);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask);
pci_push(base);
@@ -2127,7 +2179,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2157,14 +2209,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
nv_rx_process(dev);
if (nv_alloc_rx(dev)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
if (!np->in_shutdown)
mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
pci_push(base);
@@ -2174,7 +2226,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2203,14 +2255,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
break;
if (events & NVREG_IRQ_LINK) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_link_irq(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
}
if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
nv_linkchange(dev);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
np->link_timeout = jiffies + LINK_TIMEOUT;
}
if (events & (NVREG_IRQ_UNKNOWN)) {
@@ -2218,7 +2270,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
dev->name, events);
}
if (i > max_interrupt_work) {
- spin_lock(&np->lock);
+ spin_lock_irq(&np->lock);
/* disable interrupts on the nic */
writel(NVREG_IRQ_OTHER, base + NvRegIrqMask);
pci_push(base);
@@ -2228,7 +2280,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
mod_timer(&np->nic_poll, jiffies + POLL_WAIT);
}
printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i);
- spin_unlock(&np->lock);
+ spin_unlock_irq(&np->lock);
break;
}
@@ -2251,10 +2303,11 @@ static void nv_do_nic_poll(unsigned long data)
* nv_nic_irq because that may decide to do otherwise
*/
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
- disable_irq(dev->irq);
+ if (!using_multi_irqs(dev)) {
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ disable_irq(dev->irq);
mask = np->irqmask;
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
@@ -2277,11 +2330,12 @@ static void nv_do_nic_poll(unsigned long data)
writel(mask, base + NvRegIrqMask);
pci_push(base);
- if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
- ((np->msi_flags & NV_MSI_X_ENABLED) &&
- ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+ if (!using_multi_irqs(dev)) {
nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL);
- enable_irq(dev->irq);
+ if (np->msi_flags & NV_MSI_X_ENABLED)
+ enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+ else
+ enable_irq(dev->irq);
} else {
if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL);
@@ -2628,6 +2682,113 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
}
+static int nv_request_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ u8 __iomem *base = get_hwbase(dev);
+ int ret = 1;
+ int i;
+
+ if (np->msi_flags & NV_MSI_X_CAPABLE) {
+ for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+ np->msi_x_entry[i].entry = i;
+ }
+ if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
+ np->msi_flags |= NV_MSI_X_ENABLED;
+ if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
+ /* Request irq for rx handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_err;
+ }
+ /* Request irq for tx handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_free_rx;
+ }
+ /* Request irq for link and timer handling */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_free_tx;
+ }
+ /* map interrupts to their respective vector */
+ writel(0, base + NvRegMSIXMap0);
+ writel(0, base + NvRegMSIXMap1);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
+ set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
+ } else {
+ /* Request irq for all interrupts */
+ if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ goto out_err;
+ }
+
+ /* map interrupts to vector 0 */
+ writel(0, base + NvRegMSIXMap0);
+ writel(0, base + NvRegMSIXMap1);
+ }
+ }
+ }
+ if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
+ if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
+ np->msi_flags |= NV_MSI_ENABLED;
+ if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
+ printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+ pci_disable_msi(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_ENABLED;
+ goto out_err;
+ }
+
+ /* map interrupts to vector 0 */
+ writel(0, base + NvRegMSIMap0);
+ writel(0, base + NvRegMSIMap1);
+ /* enable msi vector 0 */
+ writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
+ }
+ }
+ if (ret != 0) {
+ if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
+ goto out_err;
+ }
+
+ return 0;
+out_free_tx:
+ free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
+out_free_rx:
+ free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
+out_err:
+ return 1;
+}
+
+static void nv_free_irq(struct net_device *dev)
+{
+ struct fe_priv *np = get_nvpriv(dev);
+ int i;
+
+ if (np->msi_flags & NV_MSI_X_ENABLED) {
+ for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+ free_irq(np->msi_x_entry[i].vector, dev);
+ }
+ pci_disable_msix(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_X_ENABLED;
+ } else {
+ free_irq(np->pci_dev->irq, dev);
+ if (np->msi_flags & NV_MSI_ENABLED) {
+ pci_disable_msi(np->pci_dev);
+ np->msi_flags &= ~NV_MSI_ENABLED;
+ }
+ }
+}
+
static int nv_open(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
@@ -2720,12 +2881,16 @@ static int nv_open(struct net_device *dev)
udelay(10);
writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState);
- writel(0, base + NvRegIrqMask);
+ nv_disable_hw_interrupts(dev, np->irqmask);
pci_push(base);
writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
pci_push(base);
+ if (nv_request_irq(dev)) {
+ goto out_drain;
+ }
+
if (np->msi_flags & NV_MSI_X_CAPABLE) {
for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
np->msi_x_entry[i].entry = i;
@@ -2799,7 +2964,7 @@ static int nv_open(struct net_device *dev)
}
/* ask for interrupts */
- writel(np->irqmask, base + NvRegIrqMask);
+ nv_enable_hw_interrupts(dev, np->irqmask);
spin_lock_irq(&np->lock);
writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
@@ -2843,7 +3008,6 @@ static int nv_close(struct net_device *dev)
{
struct fe_priv *np = netdev_priv(dev);
u8 __iomem *base;
- int i;
spin_lock_irq(&np->lock);
np->in_shutdown = 1;
@@ -2861,31 +3025,13 @@ static int nv_close(struct net_device *dev)
/* disable interrupts on the nic or we will lock up */
base = get_hwbase(dev);
- if (np->msi_flags & NV_MSI_X_ENABLED) {
- writel(np->irqmask, base + NvRegIrqMask);
- } else {
- if (np->msi_flags & NV_MSI_ENABLED)
- writel(0, base + NvRegMSIIrqMask);
- writel(0, base + NvRegIrqMask);
- }
+ nv_disable_hw_interrupts(dev, np->irqmask);
pci_push(base);
dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name);
spin_unlock_irq(&np->lock);
- if (np->msi_flags & NV_MSI_X_ENABLED) {
- for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
- free_irq(np->msi_x_entry[i].vector, dev);
- }
- pci_disable_msix(np->pci_dev);
- np->msi_flags &= ~NV_MSI_X_ENABLED;
- } else {
- free_irq(np->pci_dev->irq, dev);
- if (np->msi_flags & NV_MSI_ENABLED) {
- pci_disable_msi(np->pci_dev);
- np->msi_flags &= ~NV_MSI_ENABLED;
- }
- }
+ nv_free_irq(dev);
drain_ring(dev);
@@ -2974,20 +3120,18 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (id->driver_data & DEV_HAS_HIGH_DMA) {
/* packet format 3: supports 40-bit addressing */
np->desc_ver = DESC_VER_3;
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
pci_name(pci_dev));
} else {
- if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
- printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
- pci_name(pci_dev));
- goto out_relreg;
- } else {
- dev->features |= NETIF_F_HIGHDMA;
- printk(KERN_INFO "forcedeth: using HIGHDMA\n");
- }
+ dev->features |= NETIF_F_HIGHDMA;
+ printk(KERN_INFO "forcedeth: using HIGHDMA\n");
+ }
+ if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
+ printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
+ pci_name(pci_dev));
}
- np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
/* packet format 2: supports jumbo frames */
np->desc_ver = DESC_VER_2;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 79a8fbcf5f9..0d5fccc984b 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -582,7 +582,6 @@ static int __init setup_adapter(int card_base, int type, int n)
INIT_WORK(&priv->rx_work, rx_bh, priv);
dev->priv = priv;
sprintf(dev->name, "dmascc%i", 2 * n + i);
- SET_MODULE_OWNER(dev);
dev->base_addr = card_base;
dev->irq = irq;
dev->open = scc_open;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 6ace0e914fd..5927784df3f 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1550,7 +1550,6 @@ static unsigned char ax25_nocall[AX25_ADDR_LEN] =
static void scc_net_setup(struct net_device *dev)
{
- SET_MODULE_OWNER(dev);
dev->tx_queue_len = 16; /* should be enough... */
dev->open = scc_net_open;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index fe22479eb20..b49884048ca 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -1098,7 +1098,6 @@ static void yam_setup(struct net_device *dev)
dev->base_addr = yp->iobase;
dev->irq = yp->irq;
- SET_MODULE_OWNER(dev);
dev->open = yam_open;
dev->stop = yam_close;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index ea62a3e7d58..411f4d809c4 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1419,6 +1419,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
mv643xx_eth_update_pscr(dev, &cmd);
mv643xx_set_settings(dev, &cmd);
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
err = register_netdev(dev);
if (err)
goto out;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 73e271e59c6..beeb612be98 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.56"
-#define DRV_MODULE_RELDATE "Apr 1, 2006"
+#define DRV_MODULE_VERSION "3.57"
+#define DRV_MODULE_RELDATE "Apr 28, 2006"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -974,6 +974,8 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
return err;
}
+static void tg3_link_report(struct tg3 *);
+
/* This will reset the tigon3 PHY if there is no valid
* link unless the FORCE argument is non-zero.
*/
@@ -987,6 +989,11 @@ static int tg3_phy_reset(struct tg3 *tp)
if (err != 0)
return -EBUSY;
+ if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
+ netif_carrier_off(tp->dev);
+ tg3_link_report(tp);
+ }
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
@@ -1023,6 +1030,12 @@ out:
tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2);
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
}
+ else if (tp->tg3_flags2 & TG3_FLG2_PHY_JITTER_BUG) {
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+ tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+ tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+ }
/* Set Extended packet length bit (bit 14) on all chips that */
/* support jumbo frames */
if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
@@ -3531,7 +3544,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
return IRQ_RETVAL(0);
}
-static int tg3_init_hw(struct tg3 *);
+static int tg3_init_hw(struct tg3 *, int);
static int tg3_halt(struct tg3 *, int, int);
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3567,7 +3580,7 @@ static void tg3_reset_task(void *_data)
tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
@@ -4042,7 +4055,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
tg3_set_mtu(dev, tp, new_mtu);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 0);
tg3_netif_start(tp);
@@ -5719,9 +5732,23 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
if (!netif_running(dev))
return 0;
- spin_lock_bh(&tp->lock);
- __tg3_set_mac_addr(tp);
- spin_unlock_bh(&tp->lock);
+ if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+ /* Reset chip so that ASF can re-init any MAC addresses it
+ * needs.
+ */
+ tg3_netif_stop(tp);
+ tg3_full_lock(tp, 1);
+
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+ tg3_init_hw(tp, 0);
+
+ tg3_netif_start(tp);
+ tg3_full_unlock(tp);
+ } else {
+ spin_lock_bh(&tp->lock);
+ __tg3_set_mac_addr(tp);
+ spin_unlock_bh(&tp->lock);
+ }
return 0;
}
@@ -5771,7 +5798,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
}
/* tp->lock is held. */
-static int tg3_reset_hw(struct tg3 *tp)
+static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
{
u32 val, rdmac_mode;
int i, err, limit;
@@ -5786,7 +5813,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tg3_abort_hw(tp, 1);
}
- if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+ if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && reset_phy)
tg3_phy_reset(tp);
err = tg3_chip_reset(tp);
@@ -6327,7 +6354,7 @@ static int tg3_reset_hw(struct tg3 *tp)
tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
}
- err = tg3_setup_phy(tp, 1);
+ err = tg3_setup_phy(tp, reset_phy);
if (err)
return err;
@@ -6400,7 +6427,7 @@ static int tg3_reset_hw(struct tg3 *tp)
/* Called at device open time to get the chip ready for
* packet processing. Invoked with tp->lock held.
*/
-static int tg3_init_hw(struct tg3 *tp)
+static int tg3_init_hw(struct tg3 *tp, int reset_phy)
{
int err;
@@ -6413,7 +6440,7 @@ static int tg3_init_hw(struct tg3 *tp)
tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0);
- err = tg3_reset_hw(tp);
+ err = tg3_reset_hw(tp, reset_phy);
out:
return err;
@@ -6683,7 +6710,7 @@ static int tg3_test_msi(struct tg3 *tp)
tg3_full_lock(tp, 1);
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- err = tg3_init_hw(tp);
+ err = tg3_init_hw(tp, 1);
tg3_full_unlock(tp);
@@ -6748,7 +6775,7 @@ static int tg3_open(struct net_device *dev)
tg3_full_lock(tp, 0);
- err = tg3_init_hw(tp);
+ err = tg3_init_hw(tp, 1);
if (err) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
@@ -7839,7 +7866,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
if (netif_running(dev)) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
}
@@ -7884,7 +7911,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
if (netif_running(dev)) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
}
@@ -8522,7 +8549,7 @@ static int tg3_test_loopback(struct tg3 *tp)
if (!netif_running(tp->dev))
return TG3_LOOPBACK_FAILED;
- tg3_reset_hw(tp);
+ tg3_reset_hw(tp, 1);
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
@@ -8596,7 +8623,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
if (netif_running(dev)) {
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tg3_netif_start(tp);
}
@@ -9377,7 +9404,7 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
if ((page_off == 0) || (i == 0))
nvram_cmd |= NVRAM_CMD_FIRST;
- else if (page_off == (tp->nvram_pagesize - 4))
+ if (page_off == (tp->nvram_pagesize - 4))
nvram_cmd |= NVRAM_CMD_LAST;
if (i == (len - 4))
@@ -10353,10 +10380,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
- if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787))
- tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
+ tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
+ else
+ tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
+ }
tp->coalesce_mode = 0;
if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
@@ -11569,7 +11599,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
tg3_full_lock(tp, 0);
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
@@ -11603,7 +11633,7 @@ static int tg3_resume(struct pci_dev *pdev)
tg3_full_lock(tp, 0);
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
- tg3_init_hw(tp);
+ tg3_init_hw(tp, 1);
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 8c8b987d125..0e29b885d44 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2215,6 +2215,7 @@ struct tg3 {
#define TG3_FLG2_HW_TSO_2 0x08000000
#define TG3_FLG2_HW_TSO (TG3_FLG2_HW_TSO_1 | TG3_FLG2_HW_TSO_2)
#define TG3_FLG2_1SHOT_MSI 0x10000000
+#define TG3_FLG2_PHY_JITTER_BUG 0x20000000
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 6a23964c131..a6dc53b4250 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -129,6 +129,7 @@
- Massive clean-up
- Rewrite PHY, media handling (remove options, full_duplex, backoff)
- Fix Tx engine race for good
+ - Craig Brind: Zero padded aligned buffers for short packets.
*/
@@ -1326,7 +1327,12 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
rp->stats.tx_dropped++;
return 0;
}
+
+ /* Padding is not copied and so must be redone. */
skb_copy_and_csum_dev(skb, rp->tx_buf[entry]);
+ if (skb->len < ETH_ZLEN)
+ memset(rp->tx_buf[entry] + skb->len, 0,
+ ETH_ZLEN - skb->len);
rp->tx_skbuff_dma[entry] = 0;
rp->tx_ring[entry].addr = cpu_to_le32(rp->tx_bufs_dma +
(rp->tx_buf[entry] -
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index b1e3e6179e5..6c9ad92747f 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -58,7 +58,7 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
unsigned long data;
ssize_t ret;
- if (count < sizeof(unsigned long))
+ if (count != sizeof(unsigned int) && count < sizeof(unsigned long))
return -EINVAL;
add_wait_queue(&rtc->irq_queue, &wait);
@@ -90,11 +90,16 @@ rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
if (ret == 0) {
/* Check for any data updates */
if (rtc->ops->read_callback)
- data = rtc->ops->read_callback(rtc->class_dev.dev, data);
-
- ret = put_user(data, (unsigned long __user *)buf);
- if (ret == 0)
- ret = sizeof(unsigned long);
+ data = rtc->ops->read_callback(rtc->class_dev.dev,
+ data);
+
+ if (sizeof(int) != sizeof(long) &&
+ count == sizeof(unsigned int))
+ ret = put_user(data, (unsigned int __user *)buf) ?:
+ sizeof(unsigned int);
+ else
+ ret = put_user(data, (unsigned long __user *)buf) ?:
+ sizeof(unsigned long);
}
return ret;
}
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index a23ec54989f..2bc8aad4721 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -178,9 +178,9 @@ static int sa1100_rtc_open(struct device *dev)
return 0;
fail_pi:
- free_irq(IRQ_RTCAlrm, NULL);
+ free_irq(IRQ_RTCAlrm, dev);
fail_ai:
- free_irq(IRQ_RTC1Hz, NULL);
+ free_irq(IRQ_RTC1Hz, dev);
fail_ui:
return ret;
}
@@ -295,7 +295,7 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
- seq_printf(seq, "trim/divider\t: 0x%08x\n", RTTR);
+ seq_printf(seq, "trim/divider\t: 0x%08lx\n", RTTR);
seq_printf(seq, "alarm_IRQ\t: %s\n",
(RTSR & RTSR_ALE) ? "yes" : "no" );
seq_printf(seq, "update_IRQ\t: %s\n",
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index b3c6e790779..cb14642d97a 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -8014,7 +8014,6 @@ static int (*qeth_old_arp_constructor) (struct neighbour *);
static struct neigh_ops arp_direct_ops_template = {
.family = AF_INET,
- .destructor = NULL,
.solicit = NULL,
.error_report = NULL,
.output = dev_queue_xmit,
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 5ae14803091..f99e55308b3 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
+#include <linux/time.h>
#include <asm/lowcore.h>
@@ -363,7 +364,7 @@ s390_revalidate_registers(struct mci *mci)
}
#define MAX_IPD_COUNT 29
-#define MAX_IPD_TIME (5 * 60 * 100 * 1000) /* 5 minutes */
+#define MAX_IPD_TIME (5 * 60 * USEC_PER_SEC) /* 5 minutes */
/*
* machine check handler.
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 3e7302692db..a480a3742d4 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -446,7 +446,9 @@ config SCSI_DPT_I2O
config SCSI_ADVANSYS
tristate "AdvanSys SCSI support"
- depends on (ISA || EISA || PCI) && SCSI && BROKEN
+ depends on SCSI
+ depends on ISA || EISA || PCI
+ depends on BROKEN || X86_32
help
This is a driver for all SCSI host adapters manufactured by
AdvanSys. It is documented in the kernel source in
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 28b93057b60..2a419634b25 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -2051,7 +2051,7 @@ STATIC ASC_DCNT AscGetMaxDmaCount(ushort);
#define ADV_VADDR_TO_U32 virt_to_bus
#define ADV_U32_TO_VADDR bus_to_virt
-#define AdvPortAddr ulong /* Virtual memory address size */
+#define AdvPortAddr void __iomem * /* Virtual memory address size */
/*
* Define Adv Library required memory access macros.
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 73c8a088c16..3b35cb77953 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -5,11 +5,20 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
*
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
*/
#ifndef CPM_UART_H
#define CPM_UART_H
#include <linux/config.h>
+#include <linux/platform_device.h>
+#include <linux/fs_uart_pd.h>
#if defined(CONFIG_CPM2)
#include "cpm_uart_cpm2.h"
@@ -26,14 +35,14 @@
#define FLAG_SMC 0x00000002
#define FLAG_CONSOLE 0x00000001
-#define UART_SMC1 0
-#define UART_SMC2 1
-#define UART_SCC1 2
-#define UART_SCC2 3
-#define UART_SCC3 4
-#define UART_SCC4 5
+#define UART_SMC1 fsid_smc1_uart
+#define UART_SMC2 fsid_smc2_uart
+#define UART_SCC1 fsid_scc1_uart
+#define UART_SCC2 fsid_scc2_uart
+#define UART_SCC3 fsid_scc3_uart
+#define UART_SCC4 fsid_scc4_uart
-#define UART_NR 6
+#define UART_NR fs_uart_nr
#define RX_NUM_FIFO 4
#define RX_BUF_SIZE 32
@@ -64,6 +73,7 @@ struct uart_cpm_port {
uint dp_addr;
void *mem_addr;
dma_addr_t dma_addr;
+ u32 mem_size;
/* helpers */
int baud;
int bits;
@@ -90,4 +100,38 @@ void scc2_lineif(struct uart_cpm_port *pinfo);
void scc3_lineif(struct uart_cpm_port *pinfo);
void scc4_lineif(struct uart_cpm_port *pinfo);
+/*
+ virtual to phys transtalion
+*/
+static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo)
+{
+ int offset;
+ u32 val = (u32)addr;
+ /* sane check */
+ if (likely((val >= (u32)pinfo->mem_addr)) &&
+ (val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
+ offset = val - (u32)pinfo->mem_addr;
+ return pinfo->dma_addr+offset;
+ }
+ /* something nasty happened */
+ BUG();
+ return 0;
+}
+
+static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo)
+{
+ int offset;
+ u32 val = addr;
+ /* sane check */
+ if (likely((val >= pinfo->dma_addr) &&
+ (val<(pinfo->dma_addr + pinfo->mem_size)))) {
+ offset = val - (u32)pinfo->dma_addr;
+ return (void*)(pinfo->mem_addr+offset);
+ }
+ /* something nasty happened */
+ BUG();
+ return 0;
+}
+
+
#endif /* CPM_UART_H */
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b7bf4c698a4..969f9490043 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -12,7 +12,8 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
- * (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
+ * (C) 2005-2006 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,6 +42,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/dma-mapping.h>
+#include <linux/fs_uart_pd.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -60,7 +62,7 @@
/* Track which ports are configured as uarts */
int cpm_uart_port_map[UART_NR];
/* How many ports did we config as uarts */
-int cpm_uart_nr;
+int cpm_uart_nr = 0;
/**************************************************************/
@@ -71,18 +73,51 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
/**************************************************************/
-static inline unsigned long cpu2cpm_addr(void *addr)
+
+/* Place-holder for board-specific stuff */
+struct platform_device* __attribute__ ((weak)) __init
+early_uart_get_pdev(int index)
+{
+ return NULL;
+}
+
+
+static void cpm_uart_count(void)
{
- if ((unsigned long)addr >= CPM_ADDR)
- return (unsigned long)addr;
- return virt_to_bus(addr);
+ cpm_uart_nr = 0;
+#ifdef CONFIG_SERIAL_CPM_SMC1
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SMC2
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC1
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC2
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC3
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
+#endif
+#ifdef CONFIG_SERIAL_CPM_SCC4
+ cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
+#endif
}
-static inline void *cpm2cpu_addr(unsigned long addr)
+/* Get UART number by its id */
+static int cpm_uart_id2nr(int id)
{
- if (addr >= CPM_ADDR)
- return (void *)addr;
- return bus_to_virt(addr);
+ int i;
+ if (id < UART_NR) {
+ for (i=0; i<UART_NR; i++) {
+ if (cpm_uart_port_map[i] == id)
+ return i;
+ }
+ }
+
+ /* not found or invalid argument */
+ return -1;
}
/*
@@ -258,7 +293,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
}
/* get pointer */
- cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
/* loop through the buffer */
while (i-- > 0) {
@@ -438,7 +473,11 @@ static void cpm_uart_shutdown(struct uart_port *port)
}
/* Shut them really down and reinit buffer descriptors */
- cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+ if (IS_SMC(pinfo))
+ cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+ else
+ cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
+
cpm_uart_initbd(pinfo);
}
}
@@ -601,7 +640,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
/* Pick next descriptor and fill from buffer */
bdp = pinfo->tx_cur;
- p = cpm2cpu_addr(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
*p++ = port->x_char;
bdp->cbd_datlen = 1;
@@ -628,7 +667,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
count = 0;
- p = cpm2cpu_addr(bdp->cbd_bufaddr);
+ p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
while (count < pinfo->tx_fifosize) {
*p++ = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -677,12 +716,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr;
bdp = pinfo->rx_cur = pinfo->rx_bd_base;
for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
mem_addr += pinfo->rx_fifosize;
}
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
/* Set the physical address of the host memory
@@ -692,12 +731,12 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
bdp = pinfo->tx_cur = pinfo->tx_bd_base;
for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_INTRPT;
mem_addr += pinfo->tx_fifosize;
}
- bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+ bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
}
@@ -829,14 +868,6 @@ static int cpm_uart_request_port(struct uart_port *port)
if (pinfo->flags & FLAG_CONSOLE)
return 0;
- /*
- * Setup any port IO, connect any baud rate generators,
- * etc. This is expected to be handled by board
- * dependant code
- */
- if (pinfo->set_lineif)
- pinfo->set_lineif(pinfo);
-
if (IS_SMC(pinfo)) {
pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -988,6 +1019,58 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
},
};
+int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
+{
+ struct resource *r;
+ struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
+ int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */
+ struct uart_cpm_port *pinfo;
+ int line;
+ u32 mem, pram;
+
+ line = cpm_uart_id2nr(idx);
+ if(line < 0) {
+ printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
+ return -1;
+ }
+
+ pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
+
+ pinfo->brg = pdata->brg;
+
+ if (!is_con) {
+ pinfo->port.line = line;
+ pinfo->port.flags = UPF_BOOT_AUTOCONF;
+ }
+
+ if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
+ return -EINVAL;
+ mem = r->start;
+
+ if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
+ return -EINVAL;
+ pram = r->start;
+
+ if(idx > fsid_smc2_uart) {
+ pinfo->sccp = (scc_t *)mem;
+ pinfo->sccup = (scc_uart_t *)pram;
+ } else {
+ pinfo->smcp = (smc_t *)mem;
+ pinfo->smcup = (smc_uart_t *)pram;
+ }
+ pinfo->tx_nrfifos = pdata->tx_num_fifo;
+ pinfo->tx_fifosize = pdata->tx_buf_size;
+
+ pinfo->rx_nrfifos = pdata->rx_num_fifo;
+ pinfo->rx_fifosize = pdata->rx_buf_size;
+
+ pinfo->port.uartclk = pdata->uart_clk;
+ pinfo->port.mapbase = (unsigned long)mem;
+ pinfo->port.irq = platform_get_irq(pdev, 0);
+
+ return 0;
+}
+
#ifdef CONFIG_SERIAL_CPM_CONSOLE
/*
* Print a string to the serial port trying not to disturb
@@ -1027,7 +1110,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
* If the buffer address is in the CPM DPRAM, don't
* convert it.
*/
- cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
*cp = *s;
@@ -1044,7 +1127,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
while ((bdp->cbd_sc & BD_SC_READY) != 0)
;
- cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+ cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
*cp = 13;
bdp->cbd_datlen = 1;
@@ -1067,9 +1150,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
pinfo->tx_cur = (volatile cbd_t *) bdp;
}
-/*
- * Setup console. Be careful is called early !
- */
+
static int __init cpm_uart_console_setup(struct console *co, char *options)
{
struct uart_port *port;
@@ -1080,9 +1161,27 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
int flow = 'n';
int ret;
+ struct fs_uart_platform_info *pdata;
+ struct platform_device* pdev = early_uart_get_pdev(co->index);
+
port =
(struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
pinfo = (struct uart_cpm_port *)port;
+ if (!pdev) {
+ pr_info("cpm_uart: console: compat mode\n");
+ /* compatibility - will be cleaned up */
+ cpm_uart_init_portdesc();
+
+ if (pinfo->set_lineif)
+ pinfo->set_lineif(pinfo);
+ } else {
+ pdata = pdev->dev.platform_data;
+ if (pdata)
+ if (pdata->init_ioports)
+ pdata->init_ioports();
+
+ cpm_uart_drv_get_platform_data(pdev, 1);
+ }
pinfo->flags |= FLAG_CONSOLE;
@@ -1097,14 +1196,6 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
baud = 9600;
}
- /*
- * Setup any port IO, connect any baud rate generators,
- * etc. This is expected to be handled by board
- * dependant code
- */
- if (pinfo->set_lineif)
- pinfo->set_lineif(pinfo);
-
if (IS_SMC(pinfo)) {
pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -1143,11 +1234,8 @@ static struct console cpm_scc_uart_console = {
int __init cpm_uart_console_init(void)
{
- int ret = cpm_uart_init_portdesc();
-
- if (!ret)
- register_console(&cpm_scc_uart_console);
- return ret;
+ register_console(&cpm_scc_uart_console);
+ return 0;
}
console_initcall(cpm_uart_console_init);
@@ -1165,44 +1253,129 @@ static struct uart_driver cpm_reg = {
.minor = SERIAL_CPM_MINOR,
.cons = CPM_UART_CONSOLE,
};
-
-static int __init cpm_uart_init(void)
+static int cpm_uart_drv_probe(struct device *dev)
{
- int ret, i;
-
- printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n");
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fs_uart_platform_info *pdata;
+ int ret = -ENODEV;
-#ifndef CONFIG_SERIAL_CPM_CONSOLE
- ret = cpm_uart_init_portdesc();
- if (ret)
+ if(!pdev) {
+ printk(KERN_ERR"CPM UART: platform data missing!\n");
return ret;
-#endif
+ }
- cpm_reg.nr = cpm_uart_nr;
- ret = uart_register_driver(&cpm_reg);
+ pdata = pdev->dev.platform_data;
+ pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
- if (ret)
+ if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
return ret;
- for (i = 0; i < cpm_uart_nr; i++) {
- int con = cpm_uart_port_map[i];
- cpm_uart_ports[con].port.line = i;
- cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
- uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
- }
+ if (pdata->init_ioports)
+ pdata->init_ioports();
- return ret;
+ ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
+
+ return ret;
}
-static void __exit cpm_uart_exit(void)
+static int cpm_uart_drv_remove(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
+
+ pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",
+ cpm_uart_id2nr(pdata->fs_no));
+
+ uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
+ return 0;
+}
+
+static struct device_driver cpm_smc_uart_driver = {
+ .name = "fsl-cpm-smc:uart",
+ .bus = &platform_bus_type,
+ .probe = cpm_uart_drv_probe,
+ .remove = cpm_uart_drv_remove,
+};
+
+static struct device_driver cpm_scc_uart_driver = {
+ .name = "fsl-cpm-scc:uart",
+ .bus = &platform_bus_type,
+ .probe = cpm_uart_drv_probe,
+ .remove = cpm_uart_drv_remove,
+};
+
+/*
+ This is supposed to match uart devices on platform bus,
+ */
+static int match_is_uart (struct device* dev, void* data)
+{
+ struct platform_device* pdev = container_of(dev, struct platform_device, dev);
+ int ret = 0;
+ /* this was setfunc as uart */
+ if(strstr(pdev->name,":uart")) {
+ ret = 1;
+ }
+ return ret;
+}
+
+
+static int cpm_uart_init(void) {
+
+ int ret;
int i;
+ struct device *dev;
+ printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n");
+
+ /* lookup the bus for uart devices */
+ dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart);
+
+ /* There are devices on the bus - all should be OK */
+ if (dev) {
+ cpm_uart_count();
+ cpm_reg.nr = cpm_uart_nr;
+
+ if (!(ret = uart_register_driver(&cpm_reg))) {
+ if ((ret = driver_register(&cpm_smc_uart_driver))) {
+ uart_unregister_driver(&cpm_reg);
+ return ret;
+ }
+ if ((ret = driver_register(&cpm_scc_uart_driver))) {
+ driver_unregister(&cpm_scc_uart_driver);
+ uart_unregister_driver(&cpm_reg);
+ }
+ }
+ } else {
+ /* No capable platform devices found - falling back to legacy mode */
+ pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n");
+ pr_info(
+ "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n");
+#ifndef CONFIG_SERIAL_CPM_CONSOLE
+ ret = cpm_uart_init_portdesc();
+ if (ret)
+ return ret;
+#endif
+
+ cpm_reg.nr = cpm_uart_nr;
+ ret = uart_register_driver(&cpm_reg);
+
+ if (ret)
+ return ret;
+
+ for (i = 0; i < cpm_uart_nr; i++) {
+ int con = cpm_uart_port_map[i];
+ cpm_uart_ports[con].port.line = i;
+ cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
+ uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
+ }
- for (i = 0; i < cpm_uart_nr; i++) {
- int con = cpm_uart_port_map[i];
- uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port);
}
+ return ret;
+}
+static void __exit cpm_uart_exit(void)
+{
+ driver_unregister(&cpm_scc_uart_driver);
+ driver_unregister(&cpm_smc_uart_driver);
uart_unregister_driver(&cpm_reg);
}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index d789ee55cbb..17406a05ce1 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -8,6 +8,8 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
+ * (C) 2006 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -81,58 +83,11 @@ void cpm_line_cr_cmd(int line, int cmd)
void smc1_lineif(struct uart_cpm_port *pinfo)
{
- volatile cpm8xx_t *cp = cpmp;
-
- (void)cp; /* fix warning */
-#if defined (CONFIG_MPC885ADS)
- /* Enable SMC1 transceivers */
- {
- cp->cp_pepar |= 0x000000c0;
- cp->cp_pedir &= ~0x000000c0;
- cp->cp_peso &= ~0x00000040;
- cp->cp_peso |= 0x00000080;
- }
-#elif defined (CONFIG_MPC86XADS)
- unsigned int iobits = 0x000000c0;
-
- if (!pinfo->is_portb) {
- cp->cp_pbpar |= iobits;
- cp->cp_pbdir &= ~iobits;
- cp->cp_pbodr &= ~iobits;
- } else {
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
- }
-#endif
pinfo->brg = 1;
}
void smc2_lineif(struct uart_cpm_port *pinfo)
{
- volatile cpm8xx_t *cp = cpmp;
-
- (void)cp; /* fix warning */
-#if defined (CONFIG_MPC885ADS)
- cp->cp_pepar |= 0x00000c00;
- cp->cp_pedir &= ~0x00000c00;
- cp->cp_peso &= ~0x00000400;
- cp->cp_peso |= 0x00000800;
-#elif defined (CONFIG_MPC86XADS)
- unsigned int iobits = 0x00000c00;
-
- if (!pinfo->is_portb) {
- cp->cp_pbpar |= iobits;
- cp->cp_pbdir &= ~iobits;
- cp->cp_pbodr &= ~iobits;
- } else {
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
- ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
- }
-
-#endif
-
pinfo->brg = 2;
}
@@ -191,7 +146,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
/* was hostalloc but changed cause it blows away the */
/* large tlb mapping when pinning the kernel area */
mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
- dma_addr = 0;
+ dma_addr = (u32)mem_addr;
} else
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
GFP_KERNEL);
@@ -204,8 +159,9 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
}
pinfo->dp_addr = dp_offset;
- pinfo->mem_addr = mem_addr;
- pinfo->dma_addr = dma_addr;
+ pinfo->mem_addr = mem_addr; /* virtual address*/
+ pinfo->dma_addr = dma_addr; /* physical address*/
+ pinfo->mem_size = memsz;
pinfo->rx_buf = mem_addr;
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index fd9e53ed3fe..4b2de08f46d 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -8,6 +8,8 @@
*
* Copyright (C) 2004 Freescale Semiconductor, Inc.
* (C) 2004 Intracom, S.A.
+ * (C) 2006 MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -142,14 +144,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
* be supported in a sane fashion.
*/
#ifndef CONFIG_STX_GP3
-#ifdef CONFIG_MPC8560_ADS
- volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
- io->iop_ppard |= 0x00000018;
- io->iop_psord &= ~0x00000008; /* Rx */
- io->iop_psord &= ~0x00000010; /* Tx */
- io->iop_pdird &= ~0x00000008; /* Rx */
- io->iop_pdird |= 0x00000010; /* Tx */
-#else
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
io->iop_pparb |= 0x008b0000;
io->iop_pdirb |= 0x00880000;
@@ -157,7 +151,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
io->iop_pdirb &= ~0x00030000;
io->iop_psorb &= ~0x00030000;
#endif
-#endif
cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
pinfo->brg = 2;
@@ -218,8 +211,10 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
- if (is_con)
+ if (is_con) {
mem_addr = alloc_bootmem(memsz);
+ dma_addr = mem_addr;
+ }
else
mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
GFP_KERNEL);
@@ -234,6 +229,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
pinfo->dp_addr = dp_offset;
pinfo->mem_addr = mem_addr;
pinfo->dma_addr = dma_addr;
+ pinfo->mem_size = memsz;
pinfo->rx_buf = mem_addr;
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index c3b7a6673e9..d202eb4f384 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -45,6 +45,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
+#include <asm/arch/imx-uart.h>
/* We've been assigned a range on the "Low-density serial ports" major */
#define SERIAL_IMX_MAJOR 204
@@ -73,7 +74,8 @@ struct imx_port {
struct uart_port port;
struct timer_list timer;
unsigned int old_status;
- int txirq,rxirq,rtsirq;
+ int txirq,rxirq,rtsirq;
+ int have_rtscts:1;
};
/*
@@ -491,8 +493,12 @@ imx_set_termios(struct uart_port *port, struct termios *termios,
ucr2 = UCR2_SRST | UCR2_IRTS;
if (termios->c_cflag & CRTSCTS) {
- ucr2 &= ~UCR2_IRTS;
- ucr2 |= UCR2_CTSC;
+ if( sport->have_rtscts ) {
+ ucr2 &= ~UCR2_IRTS;
+ ucr2 |= UCR2_CTSC;
+ } else {
+ termios->c_cflag &= ~CRTSCTS;
+ }
}
if (termios->c_cflag & CSTOPB)
@@ -719,27 +725,6 @@ static void __init imx_init_ports(void)
imx_ports[i].timer.function = imx_timeout;
imx_ports[i].timer.data = (unsigned long)&imx_ports[i];
}
-
- imx_gpio_mode(PC9_PF_UART1_CTS);
- imx_gpio_mode(PC10_PF_UART1_RTS);
- imx_gpio_mode(PC11_PF_UART1_TXD);
- imx_gpio_mode(PC12_PF_UART1_RXD);
- imx_gpio_mode(PB28_PF_UART2_CTS);
- imx_gpio_mode(PB29_PF_UART2_RTS);
-
- imx_gpio_mode(PB30_PF_UART2_TXD);
- imx_gpio_mode(PB31_PF_UART2_RXD);
-
-#if 0 /* We don't need these, on the mx1 the _modem_ side of the uart
- * is implemented.
- */
- imx_gpio_mode(PD7_AF_UART2_DTR);
- imx_gpio_mode(PD8_AF_UART2_DCD);
- imx_gpio_mode(PD9_AF_UART2_RI);
- imx_gpio_mode(PD10_AF_UART2_DSR);
-#endif
-
-
}
#ifdef CONFIG_SERIAL_IMX_CONSOLE
@@ -932,7 +917,14 @@ static int serial_imx_resume(struct platform_device *dev)
static int serial_imx_probe(struct platform_device *dev)
{
+ struct imxuart_platform_data *pdata;
+
imx_ports[dev->id].port.dev = &dev->dev;
+
+ pdata = (struct imxuart_platform_data *)dev->dev.platform_data;
+ if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS))
+ imx_ports[dev->id].have_rtscts = 1;
+
uart_add_one_port(&imx_reg, &imx_ports[dev->id].port);
platform_set_drvdata(dev, &imx_ports[dev->id]);
return 0;
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index 0b49ff78efc..501316b198e 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -678,7 +678,7 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
/* Track PCI-device specific data */
pci_set_drvdata(pdev, idd);
down_write(&ioc3_devices_rwsem);
- list_add(&idd->list, &ioc3_devices);
+ list_add_tail(&idd->list, &ioc3_devices);
idd->id = ioc3_counter++;
up_write(&ioc3_devices_rwsem);
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index 67140a5804f..cdeff909403 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -310,7 +310,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
pci_set_drvdata(idd->idd_pdev, idd);
mutex_lock(&ioc4_mutex);
- list_add(&idd->idd_list, &ioc4_devices);
+ list_add_tail(&idd->idd_list, &ioc4_devices);
/* Add this IOC4 to all submodules */
list_for_each_entry(is, &ioc4_submodules, is_list) {
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index b367de30b98..600d3e0e08b 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1920,1925 +1920,3 @@ module_exit(au1200fb_cleanup);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-/*
- * BRIEF MODULE DESCRIPTION
- * Au1200 LCD Driver.
- *
- * Copyright 2004-2005 AMD
- * Author: AMD
- *
- * Based on:
- * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
- * Created 28 Dec 1997 by Geert Uytterhoeven
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ctype.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/mach-au1x00/au1000.h>
-#include "au1200fb.h"
-
-#ifdef CONFIG_PM
-#include <asm/mach-au1x00/au1xxx_pm.h>
-#endif
-
-#ifndef CONFIG_FB_AU1200_DEVS
-#define CONFIG_FB_AU1200_DEVS 4
-#endif
-
-#define DRIVER_NAME "au1200fb"
-#define DRIVER_DESC "LCD controller driver for AU1200 processors"
-
-#define DEBUG 1
-
-#define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg)
-#define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg)
-#define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg)
-
-#if DEBUG
-#define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg)
-#else
-#define print_dbg(f, arg...) do {} while (0)
-#endif
-
-
-#define AU1200_LCD_FB_IOCTL 0x46FF
-
-#define AU1200_LCD_SET_SCREEN 1
-#define AU1200_LCD_GET_SCREEN 2
-#define AU1200_LCD_SET_WINDOW 3
-#define AU1200_LCD_GET_WINDOW 4
-#define AU1200_LCD_SET_PANEL 5
-#define AU1200_LCD_GET_PANEL 6
-
-#define SCREEN_SIZE (1<< 1)
-#define SCREEN_BACKCOLOR (1<< 2)
-#define SCREEN_BRIGHTNESS (1<< 3)
-#define SCREEN_COLORKEY (1<< 4)
-#define SCREEN_MASK (1<< 5)
-
-struct au1200_lcd_global_regs_t {
- unsigned int flags;
- unsigned int xsize;
- unsigned int ysize;
- unsigned int backcolor;
- unsigned int brightness;
- unsigned int colorkey;
- unsigned int mask;
- unsigned int panel_choice;
- char panel_desc[80];
-
-};
-
-#define WIN_POSITION (1<< 0)
-#define WIN_ALPHA_COLOR (1<< 1)
-#define WIN_ALPHA_MODE (1<< 2)
-#define WIN_PRIORITY (1<< 3)
-#define WIN_CHANNEL (1<< 4)
-#define WIN_BUFFER_FORMAT (1<< 5)
-#define WIN_COLOR_ORDER (1<< 6)
-#define WIN_PIXEL_ORDER (1<< 7)
-#define WIN_SIZE (1<< 8)
-#define WIN_COLORKEY_MODE (1<< 9)
-#define WIN_DOUBLE_BUFFER_MODE (1<< 10)
-#define WIN_RAM_ARRAY_MODE (1<< 11)
-#define WIN_BUFFER_SCALE (1<< 12)
-#define WIN_ENABLE (1<< 13)
-
-struct au1200_lcd_window_regs_t {
- unsigned int flags;
- unsigned int xpos;
- unsigned int ypos;
- unsigned int alpha_color;
- unsigned int alpha_mode;
- unsigned int priority;
- unsigned int channel;
- unsigned int buffer_format;
- unsigned int color_order;
- unsigned int pixel_order;
- unsigned int xsize;
- unsigned int ysize;
- unsigned int colorkey_mode;
- unsigned int double_buffer_mode;
- unsigned int ram_array_mode;
- unsigned int xscale;
- unsigned int yscale;
- unsigned int enable;
-};
-
-
-struct au1200_lcd_iodata_t {
- unsigned int subcmd;
- struct au1200_lcd_global_regs_t global;
- struct au1200_lcd_window_regs_t window;
-};
-
-#if defined(__BIG_ENDIAN)
-#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11
-#else
-#define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00
-#endif
-#define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565
-
-/* Private, per-framebuffer management information (independent of the panel itself) */
-struct au1200fb_device {
- struct fb_info fb_info; /* FB driver info record */
-
- int plane;
- unsigned char* fb_mem; /* FrameBuffer memory map */
- unsigned int fb_len;
- dma_addr_t fb_phys;
-};
-
-static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS];
-/********************************************************************/
-
-/* LCD controller restrictions */
-#define AU1200_LCD_MAX_XRES 1280
-#define AU1200_LCD_MAX_YRES 1024
-#define AU1200_LCD_MAX_BPP 32
-#define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */
-#define AU1200_LCD_NBR_PALETTE_ENTRIES 256
-
-/* Default number of visible screen buffer to allocate */
-#define AU1200FB_NBR_VIDEO_BUFFERS 1
-
-/********************************************************************/
-
-static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR;
-static int window_index = 2; /* default is zero */
-static int panel_index = 2; /* default is zero */
-static struct window_settings *win;
-static struct panel_settings *panel;
-static int noblanking = 1;
-static int nohwcursor = 0;
-
-struct window_settings {
- unsigned char name[64];
- uint32 mode_backcolor;
- uint32 mode_colorkey;
- uint32 mode_colorkeymsk;
- struct {
- int xres;
- int yres;
- int xpos;
- int ypos;
- uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */
- uint32 mode_winenable;
- } w[4];
-};
-
-#if defined(__BIG_ENDIAN)
-#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00
-#else
-#define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01
-#endif
-
-extern int board_au1200fb_panel_init (void);
-extern int board_au1200fb_panel_shutdown (void);
-
-#ifdef CONFIG_PM
-int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
- au1xxx_request_t request, void *data);
-au1xxx_power_dev_t *LCD_pm_dev;
-#endif
-
-/*
- * Default window configurations
- */
-static struct window_settings windows[] = {
- { /* Index 0 */
- "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
- /* mode_backcolor */ 0x006600ff,
- /* mode_colorkey,msk*/ 0, 0,
- {
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP,
- /* mode_winenable*/ LCD_WINENABLE_WEN0,
- },
- {
- /* xres, yres, xpos, ypos */ 100, 100, 100, 100,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP |
- LCD_WINCTRL1_PIPE,
- /* mode_winenable*/ LCD_WINENABLE_WEN1,
- },
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP,
- /* mode_winenable*/ 0,
- },
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP |
- LCD_WINCTRL1_PIPE,
- /* mode_winenable*/ 0,
- },
- },
- },
-
- { /* Index 1 */
- "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
- /* mode_backcolor */ 0x006600ff,
- /* mode_colorkey,msk*/ 0, 0,
- {
- {
- /* xres, yres, xpos, ypos */ 320, 240, 5, 5,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP |
- LCD_WINCTRL1_PO_00,
- /* mode_winenable*/ LCD_WINENABLE_WEN0,
- },
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565
- | LCD_WINCTRL1_PO_16BPP,
- /* mode_winenable*/ 0,
- },
- {
- /* xres, yres, xpos, ypos */ 100, 100, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP |
- LCD_WINCTRL1_PIPE,
- /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
- },
- {
- /* xres, yres, xpos, ypos */ 200, 25, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP |
- LCD_WINCTRL1_PIPE,
- /* mode_winenable*/ 0,
- },
- },
- },
- { /* Index 2 */
- "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx",
- /* mode_backcolor */ 0x006600ff,
- /* mode_colorkey,msk*/ 0, 0,
- {
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP,
- /* mode_winenable*/ LCD_WINENABLE_WEN0,
- },
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP,
- /* mode_winenable*/ 0,
- },
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP |
- LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE,
- /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/,
- },
- {
- /* xres, yres, xpos, ypos */ 0, 0, 0, 0,
- /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 |
- LCD_WINCTRL1_PO_16BPP |
- LCD_WINCTRL1_PIPE,
- /* mode_winenable*/ 0,
- },
- },
- },
- /* Need VGA 640 @ 24bpp, @ 32bpp */
- /* Need VGA 800 @ 24bpp, @ 32bpp */
- /* Need VGA 1024 @ 24bpp, @ 32bpp */
-};
-
-/*
- * Controller configurations for various panels.
- */
-
-struct panel_settings
-{
- const char name[25]; /* Full name <vendor>_<model> */
-
- struct fb_monspecs monspecs; /* FB monitor specs */
-
- /* panel timings */
- uint32 mode_screen;
- uint32 mode_horztiming;
- uint32 mode_verttiming;
- uint32 mode_clkcontrol;
- uint32 mode_pwmdiv;
- uint32 mode_pwmhi;
- uint32 mode_outmask;
- uint32 mode_fifoctrl;
- uint32 mode_toyclksrc;
- uint32 mode_backlight;
- uint32 mode_auxpll;
- int (*device_init)(void);
- int (*device_shutdown)(void);
-#define Xres min_xres
-#define Yres min_yres
- u32 min_xres; /* Minimum horizontal resolution */
- u32 max_xres; /* Maximum horizontal resolution */
- u32 min_yres; /* Minimum vertical resolution */
- u32 max_yres; /* Maximum vertical resolution */
-};
-
-/********************************************************************/
-/* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */
-
-/* List of panels known to work with the AU1200 LCD controller.
- * To add a new panel, enter the same specifications as the
- * Generic_TFT one, and MAKE SURE that it doesn't conflicts
- * with the controller restrictions. Restrictions are:
- *
- * STN color panels: max_bpp <= 12
- * STN mono panels: max_bpp <= 4
- * TFT panels: max_bpp <= 16
- * max_xres <= 800
- * max_yres <= 600
- */
-static struct panel_settings known_lcd_panels[] =
-{
- [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */
- .name = "QVGA_320x240",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = LCD_SCREEN_SX_N(320) |
- LCD_SCREEN_SY_N(240),
- .mode_horztiming = 0x00c4623b,
- .mode_verttiming = 0x00502814,
- .mode_clkcontrol = 0x00020002, /* /4=24Mhz */
- .mode_pwmdiv = 0x00000000,
- .mode_pwmhi = 0x00000000,
- .mode_outmask = 0x00FFFFFF,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
- 320, 320,
- 240, 240,
- },
-
- [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */
- .name = "VGA_640x480",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = 0x13f9df80,
- .mode_horztiming = 0x003c5859,
- .mode_verttiming = 0x00741201,
- .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
- .mode_pwmdiv = 0x00000000,
- .mode_pwmhi = 0x00000000,
- .mode_outmask = 0x00FFFFFF,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
- 640, 480,
- 640, 480,
- },
-
- [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */
- .name = "SVGA_800x600",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = 0x18fa5780,
- .mode_horztiming = 0x00dc7e77,
- .mode_verttiming = 0x00584805,
- .mode_clkcontrol = 0x00020000, /* /2=48Mhz */
- .mode_pwmdiv = 0x00000000,
- .mode_pwmhi = 0x00000000,
- .mode_outmask = 0x00FFFFFF,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
- 800, 800,
- 600, 600,
- },
-
- [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */
- .name = "XVGA_1024x768",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = 0x1ffaff80,
- .mode_horztiming = 0x007d0e57,
- .mode_verttiming = 0x00740a01,
- .mode_clkcontrol = 0x000A0000, /* /1 */
- .mode_pwmdiv = 0x00000000,
- .mode_pwmhi = 0x00000000,
- .mode_outmask = 0x00FFFFFF,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 6, /* 72MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
- 1024, 1024,
- 768, 768,
- },
-
- [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */
- .name = "XVGA_1280x1024",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = 0x27fbff80,
- .mode_horztiming = 0x00cdb2c7,
- .mode_verttiming = 0x00600002,
- .mode_clkcontrol = 0x000A0000, /* /1 */
- .mode_pwmdiv = 0x00000000,
- .mode_pwmhi = 0x00000000,
- .mode_outmask = 0x00FFFFFF,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 10, /* 120MHz AUXPLL */
- .device_init = NULL,
- .device_shutdown = NULL,
- 1280, 1280,
- 1024, 1024,
- },
-
- [5] = { /* Samsung 1024x768 TFT */
- .name = "Samsung_1024x768_TFT",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = 0x1ffaff80,
- .mode_horztiming = 0x018cc677,
- .mode_verttiming = 0x00241217,
- .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */
- .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */
- .mode_pwmhi = 0x03400000, /* SCB 0x0 */
- .mode_outmask = 0x00FFFFFF,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
- 1024, 1024,
- 768, 768,
- },
-
- [6] = { /* Toshiba 640x480 TFT */
- .name = "Toshiba_640x480_TFT",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = LCD_SCREEN_SX_N(640) |
- LCD_SCREEN_SY_N(480),
- .mode_horztiming = LCD_HORZTIMING_HPW_N(96) |
- LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51),
- .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
- LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32),
- .mode_clkcontrol = 0x00000000, /* /4=24Mhz */
- .mode_pwmdiv = 0x8000063f,
- .mode_pwmhi = 0x03400000,
- .mode_outmask = 0x00fcfcfc,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
- 640, 480,
- 640, 480,
- },
-
- [7] = { /* Sharp 320x240 TFT */
- .name = "Sharp_320x240_TFT",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 12500,
- .hfmax = 20000,
- .vfmin = 38,
- .vfmax = 81,
- .dclkmin = 4500000,
- .dclkmax = 6800000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = LCD_SCREEN_SX_N(320) |
- LCD_SCREEN_SY_N(240),
- .mode_horztiming = LCD_HORZTIMING_HPW_N(60) |
- LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2),
- .mode_verttiming = LCD_VERTTIMING_VPW_N(2) |
- LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5),
- .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/
- .mode_pwmdiv = 0x8000063f,
- .mode_pwmhi = 0x03400000,
- .mode_outmask = 0x00fcfcfc,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
- 320, 320,
- 240, 240,
- },
-
- [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */
- .name = "Toppoly_TD070WGCB2",
- .monspecs = {
- .modedb = NULL,
- .modedb_len = 0,
- .hfmin = 30000,
- .hfmax = 70000,
- .vfmin = 60,
- .vfmax = 60,
- .dclkmin = 6000000,
- .dclkmax = 28000000,
- .input = FB_DISP_RGB,
- },
- .mode_screen = LCD_SCREEN_SX_N(856) |
- LCD_SCREEN_SY_N(480),
- .mode_horztiming = LCD_HORZTIMING_HND2_N(43) |
- LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114),
- .mode_verttiming = LCD_VERTTIMING_VND2_N(20) |
- LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4),
- .mode_clkcontrol = 0x00020001, /* /4=24Mhz */
- .mode_pwmdiv = 0x8000063f,
- .mode_pwmhi = 0x03400000,
- .mode_outmask = 0x00fcfcfc,
- .mode_fifoctrl = 0x2f2f2f2f,
- .mode_toyclksrc = 0x00000004, /* AUXPLL directly */
- .mode_backlight = 0x00000000,
- .mode_auxpll = 8, /* 96MHz AUXPLL */
- .device_init = board_au1200fb_panel_init,
- .device_shutdown = board_au1200fb_panel_shutdown,
- 856, 856,
- 480, 480,
- },
-};
-
-#define NUM_PANELS (ARRAY_SIZE(known_lcd_panels))
-
-/********************************************************************/
-
-#ifdef CONFIG_PM
-static int set_brightness(unsigned int brightness)
-{
- unsigned int hi1, divider;
-
- /* limit brightness pwm duty to >= 30/1600 */
- if (brightness < 30) {
- brightness = 30;
- }
- divider = (lcd->pwmdiv & 0x3FFFF) + 1;
- hi1 = (lcd->pwmhi >> 16) + 1;
- hi1 = (((brightness & 0xFF) + 1) * divider >> 8);
- lcd->pwmhi &= 0xFFFF;
- lcd->pwmhi |= (hi1 << 16);
-
- return brightness;
-}
-#endif /* CONFIG_PM */
-
-static int winbpp (unsigned int winctrl1)
-{
- int bits = 0;
-
- /* how many bits are needed for each pixel format */
- switch (winctrl1 & LCD_WINCTRL1_FRM) {
- case LCD_WINCTRL1_FRM_1BPP:
- bits = 1;
- break;
- case LCD_WINCTRL1_FRM_2BPP:
- bits = 2;
- break;
- case LCD_WINCTRL1_FRM_4BPP:
- bits = 4;
- break;
- case LCD_WINCTRL1_FRM_8BPP:
- bits = 8;
- break;
- case LCD_WINCTRL1_FRM_12BPP:
- case LCD_WINCTRL1_FRM_16BPP655:
- case LCD_WINCTRL1_FRM_16BPP565:
- case LCD_WINCTRL1_FRM_16BPP556:
- case LCD_WINCTRL1_FRM_16BPPI1555:
- case LCD_WINCTRL1_FRM_16BPPI5551:
- case LCD_WINCTRL1_FRM_16BPPA1555:
- case LCD_WINCTRL1_FRM_16BPPA5551:
- bits = 16;
- break;
- case LCD_WINCTRL1_FRM_24BPP:
- case LCD_WINCTRL1_FRM_32BPP:
- bits = 32;
- break;
- }
-
- return bits;
-}
-
-static int fbinfo2index (struct fb_info *fb_info)
-{
- int i;
-
- for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) {
- if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info))
- return i;
- }
- printk("au1200fb: ERROR: fbinfo2index failed!\n");
- return -1;
-}
-
-static int au1200_setlocation (struct au1200fb_device *fbdev, int plane,
- int xpos, int ypos)
-{
- uint32 winctrl0, winctrl1, winenable, fb_offset = 0;
- int xsz, ysz;
-
- /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */
-
- winctrl0 = lcd->window[plane].winctrl0;
- winctrl1 = lcd->window[plane].winctrl1;
- winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);
- winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);
-
- /* Check for off-screen adjustments */
- xsz = win->w[plane].xres;
- ysz = win->w[plane].yres;
- if ((xpos + win->w[plane].xres) > panel->Xres) {
- /* Off-screen to the right */
- xsz = panel->Xres - xpos; /* off by 1 ??? */
- /*printk("off screen right\n");*/
- }
-
- if ((ypos + win->w[plane].yres) > panel->Yres) {
- /* Off-screen to the bottom */
- ysz = panel->Yres - ypos; /* off by 1 ??? */
- /*printk("off screen bottom\n");*/
- }
-
- if (xpos < 0) {
- /* Off-screen to the left */
- xsz = win->w[plane].xres + xpos;
- fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);
- xpos = 0;
- /*printk("off screen left\n");*/
- }
-
- if (ypos < 0) {
- /* Off-screen to the top */
- ysz = win->w[plane].yres + ypos;
- /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */
- ypos = 0;
- /*printk("off screen top\n");*/
- }
-
- /* record settings */
- win->w[plane].xpos = xpos;
- win->w[plane].ypos = ypos;
-
- xsz -= 1;
- ysz -= 1;
- winctrl0 |= (xpos << 21);
- winctrl0 |= (ypos << 10);
- winctrl1 |= (xsz << 11);
- winctrl1 |= (ysz << 0);
-
- /* Disable the window while making changes, then restore WINEN */
- winenable = lcd->winenable & (1 << plane);
- au_sync();
- lcd->winenable &= ~(1 << plane);
- lcd->window[plane].winctrl0 = winctrl0;
- lcd->window[plane].winctrl1 = winctrl1;
- lcd->window[plane].winbuf0 =
- lcd->window[plane].winbuf1 = fbdev->fb_phys;
- lcd->window[plane].winbufctrl = 0; /* select winbuf0 */
- lcd->winenable |= winenable;
- au_sync();
-
- return 0;
-}
-
-static void au1200_setpanel (struct panel_settings *newpanel)
-{
- /*
- * Perform global setup/init of LCD controller
- */
- uint32 winenable;
-
- /* Make sure all windows disabled */
- winenable = lcd->winenable;
- lcd->winenable = 0;
- au_sync();
- /*
- * Ensure everything is disabled before reconfiguring
- */
- if (lcd->screen & LCD_SCREEN_SEN) {
- /* Wait for vertical sync period */
- lcd->intstatus = LCD_INT_SS;
- while ((lcd->intstatus & LCD_INT_SS) == 0) {
- au_sync();
- }
-
- lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/
-
- do {
- lcd->intstatus = lcd->intstatus; /*clear interrupts*/
- au_sync();
- /*wait for controller to shut down*/
- } while ((lcd->intstatus & LCD_INT_SD) == 0);
-
- /* Call shutdown of current panel (if up) */
- /* this must occur last, because if an external clock is driving
- the controller, the clock cannot be turned off before first
- shutting down the controller.
- */
- if (panel->device_shutdown != NULL)
- panel->device_shutdown();
- }
-
- /* Newpanel == NULL indicates a shutdown operation only */
- if (newpanel == NULL)
- return;
-
- panel = newpanel;
-
- printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);
-
- /*
- * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)
- */
- if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))
- {
- uint32 sys_clksrc;
- au_writel(panel->mode_auxpll, SYS_AUXPLL);
- sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f;
- sys_clksrc |= panel->mode_toyclksrc;
- au_writel(sys_clksrc, SYS_CLKSRC);
- }
-
- /*
- * Configure panel timings
- */
- lcd->screen = panel->mode_screen;
- lcd->horztiming = panel->mode_horztiming;
- lcd->verttiming = panel->mode_verttiming;
- lcd->clkcontrol = panel->mode_clkcontrol;
- lcd->pwmdiv = panel->mode_pwmdiv;
- lcd->pwmhi = panel->mode_pwmhi;
- lcd->outmask = panel->mode_outmask;
- lcd->fifoctrl = panel->mode_fifoctrl;
- au_sync();
-
- /* fixme: Check window settings to make sure still valid
- * for new geometry */
-#if 0
- au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos);
- au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos);
- au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos);
- au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos);
-#endif
- lcd->winenable = winenable;
-
- /*
- * Re-enable screen now that it is configured
- */
- lcd->screen |= LCD_SCREEN_SEN;
- au_sync();
-
- /* Call init of panel */
- if (panel->device_init != NULL) panel->device_init();
-
- /* FIX!!!! not appropriate on panel change!!! Global setup/init */
- lcd->intenable = 0;
- lcd->intstatus = ~0;
- lcd->backcolor = win->mode_backcolor;
-
- /* Setup Color Key - FIX!!! */
- lcd->colorkey = win->mode_colorkey;
- lcd->colorkeymsk = win->mode_colorkeymsk;
-
- /* Setup HWCursor - FIX!!! Need to support this eventually */
- lcd->hwc.cursorctrl = 0;
- lcd->hwc.cursorpos = 0;
- lcd->hwc.cursorcolor0 = 0;
- lcd->hwc.cursorcolor1 = 0;
- lcd->hwc.cursorcolor2 = 0;
- lcd->hwc.cursorcolor3 = 0;
-
-
-#if 0
-#define D(X) printk("%25s: %08X\n", #X, X)
- D(lcd->screen);
- D(lcd->horztiming);
- D(lcd->verttiming);
- D(lcd->clkcontrol);
- D(lcd->pwmdiv);
- D(lcd->pwmhi);
- D(lcd->outmask);
- D(lcd->fifoctrl);
- D(lcd->window[0].winctrl0);
- D(lcd->window[0].winctrl1);
- D(lcd->window[0].winctrl2);
- D(lcd->window[0].winbuf0);
- D(lcd->window[0].winbuf1);
- D(lcd->window[0].winbufctrl);
- D(lcd->window[1].winctrl0);
- D(lcd->window[1].winctrl1);
- D(lcd->window[1].winctrl2);
- D(lcd->window[1].winbuf0);
- D(lcd->window[1].winbuf1);
- D(lcd->window[1].winbufctrl);
- D(lcd->window[2].winctrl0);
- D(lcd->window[2].winctrl1);
- D(lcd->window[2].winctrl2);
- D(lcd->window[2].winbuf0);
- D(lcd->window[2].winbuf1);
- D(lcd->window[2].winbufctrl);
- D(lcd->window[3].winctrl0);
- D(lcd->window[3].winctrl1);
- D(lcd->window[3].winctrl2);
- D(lcd->window[3].winbuf0);
- D(lcd->window[3].winbuf1);
- D(lcd->window[3].winbufctrl);
- D(lcd->winenable);
- D(lcd->intenable);
- D(lcd->intstatus);
- D(lcd->backcolor);
- D(lcd->winenable);
- D(lcd->colorkey);
- D(lcd->colorkeymsk);
- D(lcd->hwc.cursorctrl);
- D(lcd->hwc.cursorpos);
- D(lcd->hwc.cursorcolor0);
- D(lcd->hwc.cursorcolor1);
- D(lcd->hwc.cursorcolor2);
- D(lcd->hwc.cursorcolor3);
-#endif
-}
-
-static void au1200_setmode(struct au1200fb_device *fbdev)
-{
- int plane = fbdev->plane;
- /* Window/plane setup */
- lcd->window[plane].winctrl1 = ( 0
- | LCD_WINCTRL1_PRI_N(plane)
- | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */
- ) ;
-
- au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos);
-
- lcd->window[plane].winctrl2 = ( 0
- | LCD_WINCTRL2_CKMODE_00
- | LCD_WINCTRL2_DBM
- | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)
- | LCD_WINCTRL2_SCX_1
- | LCD_WINCTRL2_SCY_1
- ) ;
- lcd->winenable |= win->w[plane].mode_winenable;
- au_sync();
-}
-
-
-/* Inline helpers */
-
-/*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
-/*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/
-
-#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)
-
-/* Bitfields format supported by the controller. */
-static struct fb_bitfield rgb_bitfields[][4] = {
- /* Red, Green, Blue, Transp */
- [LCD_WINCTRL1_FRM_16BPP655 >> 25] =
- { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-
- [LCD_WINCTRL1_FRM_16BPP565 >> 25] =
- { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-
- [LCD_WINCTRL1_FRM_16BPP556 >> 25] =
- { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },
-
- [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =
- { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },
-
- [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =
- { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },
-
- [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =
- { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },
-
- [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =
- { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },
-
- [LCD_WINCTRL1_FRM_24BPP >> 25] =
- { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },
-
- [LCD_WINCTRL1_FRM_32BPP >> 25] =
- { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Helpers */
-
-static void au1200fb_update_fbinfo(struct fb_info *fbi)
-{
- /* FIX!!!! This also needs to take the window pixel format into account!!! */
-
- /* Update var-dependent FB info */
- if (panel_is_color(panel)) {
- if (fbi->var.bits_per_pixel <= 8) {
- /* palettized */
- fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- fbi->fix.line_length = fbi->var.xres_virtual /
- (8/fbi->var.bits_per_pixel);
- } else {
- /* non-palettized */
- fbi->fix.visual = FB_VISUAL_TRUECOLOR;
- fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);
- }
- } else {
- /* mono FIX!!! mono 8 and 4 bits */
- fbi->fix.visual = FB_VISUAL_MONO10;
- fbi->fix.line_length = fbi->var.xres_virtual / 8;
- }
-
- fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;
- print_dbg("line length: %d\n", fbi->fix.line_length);
- print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* AU1200 framebuffer driver */
-
-/* fb_check_var
- * Validate var settings with hardware restrictions and modify it if necessary
- */
-static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *fbi)
-{
- struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
- u32 pixclock;
- int screen_size, plane;
-
- plane = fbdev->plane;
-
- /* Make sure that the mode respect all LCD controller and
- * panel restrictions. */
- var->xres = win->w[plane].xres;
- var->yres = win->w[plane].yres;
-
- /* No need for virtual resolution support */
- var->xres_virtual = var->xres;
- var->yres_virtual = var->yres;
-
- var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);
-
- screen_size = var->xres_virtual * var->yres_virtual;
- if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);
- else screen_size /= (8/var->bits_per_pixel);
-
- if (fbdev->fb_len < screen_size)
- return -EINVAL; /* Virtual screen is to big, abort */
-
- /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */
- /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel
- * clock can only be obtain by dividing this value by an even integer.
- * Fallback to a slower pixel clock if necessary. */
- pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
- pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2));
-
- if (AU1200_LCD_MAX_CLK % pixclock) {
- int diff = AU1200_LCD_MAX_CLK % pixclock;
- pixclock -= diff;
- }
-
- var->pixclock = KHZ2PICOS(pixclock/1000);
-#if 0
- if (!panel_is_active(panel)) {
- int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;
-
- if (!panel_is_color(panel)
- && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {
- /* STN 8bit mono panel support is up to 6MHz pixclock */
- var->pixclock = KHZ2PICOS(6000);
- } else if (!pcd) {
- /* Other STN panel support is up to 12MHz */
- var->pixclock = KHZ2PICOS(12000);
- }
- }
-#endif
- /* Set bitfield accordingly */
- switch (var->bits_per_pixel) {
- case 16:
- {
- /* 16bpp True color.
- * These must be set to MATCH WINCTRL[FORM] */
- int idx;
- idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
- var->red = rgb_bitfields[idx][0];
- var->green = rgb_bitfields[idx][1];
- var->blue = rgb_bitfields[idx][2];
- var->transp = rgb_bitfields[idx][3];
- break;
- }
-
- case 32:
- {
- /* 32bpp True color.
- * These must be set to MATCH WINCTRL[FORM] */
- int idx;
- idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;
- var->red = rgb_bitfields[idx][0];
- var->green = rgb_bitfields[idx][1];
- var->blue = rgb_bitfields[idx][2];
- var->transp = rgb_bitfields[idx][3];
- break;
- }
- default:
- print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/* fb_set_par
- * Set hardware with var settings. This will enable the controller with a
- * specific mode, normally validated with the fb_check_var method
- */
-static int au1200fb_fb_set_par(struct fb_info *fbi)
-{
- struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;
-
- au1200fb_update_fbinfo(fbi);
- au1200_setmode(fbdev);
-
- return 0;
-}
-
-/* fb_setcolreg
- * Set color in LCD palette.
- */
-static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *fbi)
-{
- volatile u32 *palette = lcd->palette;
- u32 value;
-
- if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))
- return -EINVAL;
-
- if (fbi->var.grayscale) {
- /* Convert color to grayscale */
- red = green = blue =
- (19595 * red + 38470 * green + 7471 * blue) >> 16;
- }
-
- if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {
- /* Place color in the pseudopalette */
- if (regno > 16)
- return -EINVAL;
-
- palette = (u32*) fbi->pseudo_palette;
-
- red >>= (16 - fbi->var.red.length);
- green >>= (16 - fbi->var.green.length);
- blue >>= (16 - fbi->var.blue.length);
-
- value = (red << fbi->var.red.offset) |
- (green << fbi->var.green.offset)|
- (blue << fbi->var.blue.offset);
- value &= 0xFFFF;
-
- } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {
- /* COLOR TFT PALLETTIZED (use RGB 565) */
- value = (red & 0xF800)|((green >> 5) &
- 0x07E0)|((blue >> 11) & 0x001F);
- value &= 0xFFFF;
-
- } else if (0 /*panel_is_color(fbdev->panel)*/) {
- /* COLOR STN MODE */
- value = 0x1234;
- value &= 0xFFF;
- } else {
- /* MONOCHROME MODE */
- value = (green >> 12) & 0x000F;
- value &= 0xF;
- }
-
- palette[regno] = value;
-
- return 0;
-}
-
-/* fb_blank
- * Blank the screen. Depending on the mode, the screen will be
- * activated with the backlight color, or desactivated
- */
-static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi)
-{
- /* Short-circuit screen blanking */
- if (noblanking)
- return 0;
-
- switch (blank_mode) {
-
- case FB_BLANK_UNBLANK:
- case FB_BLANK_NORMAL:
- /* printk("turn on panel\n"); */
- au1200_setpanel(panel);
- break;
- case FB_BLANK_VSYNC_SUSPEND:
- case FB_BLANK_HSYNC_SUSPEND:
- case FB_BLANK_POWERDOWN:
- /* printk("turn off panel\n"); */
- au1200_setpanel(NULL);
- break;
- default:
- break;
-
- }
-
- /* FB_BLANK_NORMAL is a soft blank */
- return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;
-}
-
-/* fb_mmap
- * Map video memory in user space. We don't use the generic fb_mmap
- * method mainly to allow the use of the TLB streaming flag (CCA=6)
- */
-static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-
-{
- unsigned int len;
- unsigned long start=0, off;
- struct au1200fb_device *fbdev = (struct au1200fb_device *) info;
-
-#ifdef CONFIG_PM
- au1xxx_pm_access(LCD_pm_dev);
-#endif
-
- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
- return -EINVAL;
- }
-
- start = fbdev->fb_phys & PAGE_MASK;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);
-
- off = vma->vm_pgoff << PAGE_SHIFT;
-
- if ((vma->vm_end - vma->vm_start + off) > len) {
- return -EINVAL;
- }
-
- off += start;
- vma->vm_pgoff = off >> PAGE_SHIFT;
-
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */
-
- vma->vm_flags |= VM_IO;
-
- return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
-
- return 0;
-}
-
-static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
-{
-
- unsigned int hi1, divider;
-
- /* SCREEN_SIZE: user cannot reset size, must switch panel choice */
-
- if (pdata->flags & SCREEN_BACKCOLOR)
- lcd->backcolor = pdata->backcolor;
-
- if (pdata->flags & SCREEN_BRIGHTNESS) {
-
- // limit brightness pwm duty to >= 30/1600
- if (pdata->brightness < 30) {
- pdata->brightness = 30;
- }
- divider = (lcd->pwmdiv & 0x3FFFF) + 1;
- hi1 = (lcd->pwmhi >> 16) + 1;
- hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);
- lcd->pwmhi &= 0xFFFF;
- lcd->pwmhi |= (hi1 << 16);
- }
-
- if (pdata->flags & SCREEN_COLORKEY)
- lcd->colorkey = pdata->colorkey;
-
- if (pdata->flags & SCREEN_MASK)
- lcd->colorkeymsk = pdata->mask;
- au_sync();
-}
-
-static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata)
-{
- unsigned int hi1, divider;
-
- pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;
- pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;
-
- pdata->backcolor = lcd->backcolor;
- pdata->colorkey = lcd->colorkey;
- pdata->mask = lcd->colorkeymsk;
-
- // brightness
- hi1 = (lcd->pwmhi >> 16) + 1;
- divider = (lcd->pwmdiv & 0x3FFFF) + 1;
- pdata->brightness = ((hi1 << 8) / divider) - 1;
- au_sync();
-}
-
-static void set_window(unsigned int plane,
- struct au1200_lcd_window_regs_t *pdata)
-{
- unsigned int val, bpp;
-
- /* Window control register 0 */
- if (pdata->flags & WIN_POSITION) {
- val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |
- LCD_WINCTRL0_OY);
- val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);
- val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);
- lcd->window[plane].winctrl0 = val;
- }
- if (pdata->flags & WIN_ALPHA_COLOR) {
- val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);
- val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);
- lcd->window[plane].winctrl0 = val;
- }
- if (pdata->flags & WIN_ALPHA_MODE) {
- val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);
- val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);
- lcd->window[plane].winctrl0 = val;
- }
-
- /* Window control register 1 */
- if (pdata->flags & WIN_PRIORITY) {
- val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);
- val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);
- lcd->window[plane].winctrl1 = val;
- }
- if (pdata->flags & WIN_CHANNEL) {
- val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);
- val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);
- lcd->window[plane].winctrl1 = val;
- }
- if (pdata->flags & WIN_BUFFER_FORMAT) {
- val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);
- val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);
- lcd->window[plane].winctrl1 = val;
- }
- if (pdata->flags & WIN_COLOR_ORDER) {
- val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);
- val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);
- lcd->window[plane].winctrl1 = val;
- }
- if (pdata->flags & WIN_PIXEL_ORDER) {
- val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);
- val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);
- lcd->window[plane].winctrl1 = val;
- }
- if (pdata->flags & WIN_SIZE) {
- val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |
- LCD_WINCTRL1_SZY);
- val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);
- val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);
- lcd->window[plane].winctrl1 = val;
- /* program buffer line width */
- bpp = winbpp(val) / 8;
- val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);
- val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);
- lcd->window[plane].winctrl2 = val;
- }
-
- /* Window control register 2 */
- if (pdata->flags & WIN_COLORKEY_MODE) {
- val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);
- val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);
- lcd->window[plane].winctrl2 = val;
- }
- if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {
- val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);
- val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);
- lcd->window[plane].winctrl2 = val;
- }
- if (pdata->flags & WIN_RAM_ARRAY_MODE) {
- val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);
- val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);
- lcd->window[plane].winctrl2 = val;
- }
-
- /* Buffer line width programmed with WIN_SIZE */
-
- if (pdata->flags & WIN_BUFFER_SCALE) {
- val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |
- LCD_WINCTRL2_SCY);
- val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);
- val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);
- lcd->window[plane].winctrl2 = val;
- }
-
- if (pdata->flags & WIN_ENABLE) {
- val = lcd->winenable;
- val &= ~(1<<plane);
- val |= (pdata->enable & 1) << plane;
- lcd->winenable = val;
- }
- au_sync();
-}
-
-static void get_window(unsigned int plane,
- struct au1200_lcd_window_regs_t *pdata)
-{
- /* Window control register 0 */
- pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;
- pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;
- pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;
- pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;
-
- /* Window control register 1 */
- pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;
- pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;
- pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;
- pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;
- pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22;
- pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1;
- pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1;
-
- /* Window control register 2 */
- pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24;
- pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23;
- pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21;
-
- pdata->enable = (lcd->winenable >> plane) & 1;
- au_sync();
-}
-
-static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd,
- unsigned long arg)
-{
- int plane;
- int val;
-
-#ifdef CONFIG_PM
- au1xxx_pm_access(LCD_pm_dev);
-#endif
-
- plane = fbinfo2index(info);
- print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane);
-
- if (cmd == AU1200_LCD_FB_IOCTL) {
- struct au1200_lcd_iodata_t iodata;
-
- if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata)))
- return -EFAULT;
-
- print_dbg("FB IOCTL called\n");
-
- switch (iodata.subcmd) {
- case AU1200_LCD_SET_SCREEN:
- print_dbg("AU1200_LCD_SET_SCREEN\n");
- set_global(cmd, &iodata.global);
- break;
-
- case AU1200_LCD_GET_SCREEN:
- print_dbg("AU1200_LCD_GET_SCREEN\n");
- get_global(cmd, &iodata.global);
- break;
-
- case AU1200_LCD_SET_WINDOW:
- print_dbg("AU1200_LCD_SET_WINDOW\n");
- set_window(plane, &iodata.window);
- break;
-
- case AU1200_LCD_GET_WINDOW:
- print_dbg("AU1200_LCD_GET_WINDOW\n");
- get_window(plane, &iodata.window);
- break;
-
- case AU1200_LCD_SET_PANEL:
- print_dbg("AU1200_LCD_SET_PANEL\n");
- if ((iodata.global.panel_choice >= 0) &&
- (iodata.global.panel_choice <
- NUM_PANELS))
- {
- struct panel_settings *newpanel;
- panel_index = iodata.global.panel_choice;
- newpanel = &known_lcd_panels[panel_index];
- au1200_setpanel(newpanel);
- }
- break;
-
- case AU1200_LCD_GET_PANEL:
- print_dbg("AU1200_LCD_GET_PANEL\n");
- iodata.global.panel_choice = panel_index;
- break;
-
- default:
- return -EINVAL;
- }
-
- val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata));
- if (val) {
- print_dbg("error: could not copy %d bytes\n", val);
- return -EFAULT;
- }
- }
-
- return 0;
-}
-
-
-static struct fb_ops au1200fb_fb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = au1200fb_fb_check_var,
- .fb_set_par = au1200fb_fb_set_par,
- .fb_setcolreg = au1200fb_fb_setcolreg,
- .fb_blank = au1200fb_fb_blank,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
- .fb_sync = NULL,
- .fb_ioctl = au1200fb_ioctl,
- .fb_mmap = au1200fb_fb_mmap,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs)
-{
- /* Nothing to do for now, just clear any pending interrupt */
- lcd->intstatus = lcd->intstatus;
- au_sync();
-
- return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* AU1200 LCD device probe helpers */
-
-static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev)
-{
- struct fb_info *fbi = &fbdev->fb_info;
- int bpp;
-
- memset(fbi, 0, sizeof(struct fb_info));
- fbi->fbops = &au1200fb_fb_ops;
-
- bpp = winbpp(win->w[fbdev->plane].mode_winctrl1);
-
- /* Copy monitor specs from panel data */
- /* fixme: we're setting up LCD controller windows, so these dont give a
- damn as to what the monitor specs are (the panel itself does, but that
- isnt done here...so maybe need a generic catchall monitor setting??? */
- memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs));
-
- /* We first try the user mode passed in argument. If that failed,
- * or if no one has been specified, we default to the first mode of the
- * panel list. Note that after this call, var data will be set */
- if (!fb_find_mode(&fbi->var,
- fbi,
- NULL, /* drv_info.opt_mode, */
- fbi->monspecs.modedb,
- fbi->monspecs.modedb_len,
- fbi->monspecs.modedb,
- bpp)) {
-
- print_err("Cannot find valid mode for panel %s", panel->name);
- return -EFAULT;
- }
-
- fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
- if (!fbi->pseudo_palette) {
- return -ENOMEM;
- }
- memset(fbi->pseudo_palette, 0, sizeof(u32) * 16);
-
- if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
- print_err("Fail to allocate colormap (%d entries)",
- AU1200_LCD_NBR_PALETTE_ENTRIES);
- kfree(fbi->pseudo_palette);
- return -EFAULT;
- }
-
- strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id));
- fbi->fix.smem_start = fbdev->fb_phys;
- fbi->fix.smem_len = fbdev->fb_len;
- fbi->fix.type = FB_TYPE_PACKED_PIXELS;
- fbi->fix.xpanstep = 0;
- fbi->fix.ypanstep = 0;
- fbi->fix.mmio_start = 0;
- fbi->fix.mmio_len = 0;
- fbi->fix.accel = FB_ACCEL_NONE;
-
- fbi->screen_base = (char __iomem *) fbdev->fb_mem;
-
- au1200fb_update_fbinfo(fbi);
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* AU1200 LCD controller device driver */
-
-static int au1200fb_drv_probe(struct device *dev)
-{
- struct au1200fb_device *fbdev;
- unsigned long page;
- int bpp, plane, ret;
-
- if (!dev)
- return -EINVAL;
-
- for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
- bpp = winbpp(win->w[plane].mode_winctrl1);
- if (win->w[plane].xres == 0)
- win->w[plane].xres = panel->Xres;
- if (win->w[plane].yres == 0)
- win->w[plane].yres = panel->Yres;
-
- fbdev = &_au1200fb_devices[plane];
- memset(fbdev, 0, sizeof(struct au1200fb_device));
- fbdev->plane = plane;
-
- /* Allocate the framebuffer to the maximum screen size */
- fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
-
- fbdev->fb_mem = dma_alloc_noncoherent(dev,
- PAGE_ALIGN(fbdev->fb_len),
- &fbdev->fb_phys, GFP_KERNEL);
- if (!fbdev->fb_mem) {
- print_err("fail to allocate frambuffer (size: %dK))",
- fbdev->fb_len / 1024);
- return -ENOMEM;
- }
-
- /*
- * Set page reserved so that mmap will work. This is necessary
- * since we'll be remapping normal memory.
- */
- for (page = (unsigned long)fbdev->fb_phys;
- page < PAGE_ALIGN((unsigned long)fbdev->fb_phys +
- fbdev->fb_len);
- page += PAGE_SIZE) {
- SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */
- }
- print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
- print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024);
-
- /* Init FB data */
- if ((ret = au1200fb_init_fbinfo(fbdev)) < 0)
- goto failed;
-
- /* Register new framebuffer */
- if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) {
- print_err("cannot register new framebuffer");
- goto failed;
- }
-
- au1200fb_fb_set_par(&fbdev->fb_info);
-
-#if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
- if (plane == 0)
- if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) {
- /* Start display and show logo on boot */
- fb_set_cmap(&fbdev->fb_info.cmap,
- &fbdev->fb_info);
-
- fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR);
- }
-#endif
- }
-
- /* Now hook interrupt too */
- if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq,
- SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) {
- print_err("fail to request interrupt line %d (err: %d)",
- AU1200_LCD_INT, ret);
- goto failed;
- }
-
- return 0;
-
-failed:
- /* NOTE: This only does the current plane/window that failed; others are still active */
- if (fbdev->fb_mem)
- dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
- fbdev->fb_mem, fbdev->fb_phys);
- if (fbdev->fb_info.cmap.len != 0)
- fb_dealloc_cmap(&fbdev->fb_info.cmap);
- if (fbdev->fb_info.pseudo_palette)
- kfree(fbdev->fb_info.pseudo_palette);
- if (plane == 0)
- free_irq(AU1200_LCD_INT, (void*)dev);
- return ret;
-}
-
-static int au1200fb_drv_remove(struct device *dev)
-{
- struct au1200fb_device *fbdev;
- int plane;
-
- if (!dev)
- return -ENODEV;
-
- /* Turn off the panel */
- au1200_setpanel(NULL);
-
- for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)
- {
- fbdev = &_au1200fb_devices[plane];
-
- /* Clean up all probe data */
- unregister_framebuffer(&fbdev->fb_info);
- if (fbdev->fb_mem)
- dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len),
- fbdev->fb_mem, fbdev->fb_phys);
- if (fbdev->fb_info.cmap.len != 0)
- fb_dealloc_cmap(&fbdev->fb_info.cmap);
- if (fbdev->fb_info.pseudo_palette)
- kfree(fbdev->fb_info.pseudo_palette);
- }
-
- free_irq(AU1200_LCD_INT, (void *)dev);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level)
-{
- /* TODO */
- return 0;
-}
-
-static int au1200fb_drv_resume(struct device *dev, u32 level)
-{
- /* TODO */
- return 0;
-}
-#endif /* CONFIG_PM */
-
-static struct device_driver au1200fb_driver = {
- .name = "au1200-lcd",
- .bus = &platform_bus_type,
- .probe = au1200fb_drv_probe,
- .remove = au1200fb_drv_remove,
-#ifdef CONFIG_PM
- .suspend = au1200fb_drv_suspend,
- .resume = au1200fb_drv_resume,
-#endif
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* Kernel driver */
-
-static void au1200fb_setup(void)
-{
- char* options = NULL;
- char* this_opt;
- int num_panels = ARRAY_SIZE(known_lcd_panels);
- int panel_idx = -1;
-
- fb_get_options(DRIVER_NAME, &options);
-
- if (options) {
- while ((this_opt = strsep(&options,",")) != NULL) {
- /* Panel option - can be panel name,
- * "bs" for board-switch, or number/index */
- if (!strncmp(this_opt, "panel:", 6)) {
- int i;
- long int li;
- char *endptr;
- this_opt += 6;
- /* First check for index, which allows
- * to short circuit this mess */
- li = simple_strtol(this_opt, &endptr, 0);
- if (*endptr == '\0') {
- panel_idx = (int)li;
- }
- else if (strcmp(this_opt, "bs") == 0) {
- extern int board_au1200fb_panel(void);
- panel_idx = board_au1200fb_panel();
- }
-
- else
- for (i = 0; i < num_panels; i++) {
- if (!strcmp(this_opt, known_lcd_panels[i].name)) {
- panel_idx = i;
- break;
- }
- }
-
- if ((panel_idx < 0) || (panel_idx >= num_panels)) {
- print_warn("Panel %s not supported!", this_opt);
- }
- else
- panel_index = panel_idx;
- }
-
- else if (strncmp(this_opt, "nohwcursor", 10) == 0) {
- nohwcursor = 1;
- }
-
- /* Unsupported option */
- else {
- print_warn("Unsupported option \"%s\"", this_opt);
- }
- }
- }
-}
-
-#ifdef CONFIG_PM
-static int au1200fb_pm_callback(au1xxx_power_dev_t *dev,
- au1xxx_request_t request, void *data) {
- int retval = -1;
- unsigned int d = 0;
- unsigned int brightness = 0;
-
- if (request == AU1XXX_PM_SLEEP) {
- board_au1200fb_panel_shutdown();
- }
- else if (request == AU1XXX_PM_WAKEUP) {
- if(dev->prev_state == SLEEP_STATE)
- {
- int plane;
- au1200_setpanel(panel);
- for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) {
- struct au1200fb_device *fbdev;
- fbdev = &_au1200fb_devices[plane];
- au1200fb_fb_set_par(&fbdev->fb_info);
- }
- }
-
- d = *((unsigned int*)data);
- if(d <=10) brightness = 26;
- else if(d<=20) brightness = 51;
- else if(d<=30) brightness = 77;
- else if(d<=40) brightness = 102;
- else if(d<=50) brightness = 128;
- else if(d<=60) brightness = 153;
- else if(d<=70) brightness = 179;
- else if(d<=80) brightness = 204;
- else if(d<=90) brightness = 230;
- else brightness = 255;
- set_brightness(brightness);
- } else if (request == AU1XXX_PM_GETSTATUS) {
- return dev->cur_state;
- } else if (request == AU1XXX_PM_ACCESS) {
- if (dev->cur_state != SLEEP_STATE)
- return retval;
- else {
- au1200_setpanel(panel);
- }
- } else if (request == AU1XXX_PM_IDLE) {
- } else if (request == AU1XXX_PM_CLEANUP) {
- }
-
- return retval;
-}
-#endif
-
-static int __init au1200fb_init(void)
-{
- print_info("" DRIVER_DESC "");
-
- /* Setup driver with options */
- au1200fb_setup();
-
- /* Point to the panel selected */
- panel = &known_lcd_panels[panel_index];
- win = &windows[window_index];
-
- printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name);
- printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name);
-
- /* Kickstart the panel, the framebuffers/windows come soon enough */
- au1200_setpanel(panel);
-
- #ifdef CONFIG_PM
- LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL);
- if ( LCD_pm_dev == NULL)
- printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n");
- else
- printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n");
- #endif
-
- return driver_register(&au1200fb_driver);
-}
-
-static void __exit au1200fb_cleanup(void)
-{
- driver_unregister(&au1200fb_driver);
-}
-
-module_init(au1200fb_init);
-module_exit(au1200fb_cleanup);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/fs/block_dev.c b/fs/block_dev.c
index af88c43043d..f5958f413bd 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1104,6 +1104,8 @@ const struct file_operations def_blk_fops = {
.readv = generic_file_readv,
.writev = generic_file_write_nolock,
.sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
};
int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
diff --git a/fs/compat.c b/fs/compat.c
index 2e32bd34047..970888aad84 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1317,6 +1317,26 @@ out:
return ret;
}
+asmlinkage long
+compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
+ unsigned int nr_segs, unsigned int flags)
+{
+ unsigned i;
+ struct iovec *iov;
+ if (nr_segs > UIO_MAXIOV)
+ return -EINVAL;
+ iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
+ for (i = 0; i < nr_segs; i++) {
+ struct compat_iovec v;
+ if (get_user(v.iov_base, &iov32[i].iov_base) ||
+ get_user(v.iov_len, &iov32[i].iov_len) ||
+ put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
+ put_user(v.iov_len, &iov[i].iov_len))
+ return -EFAULT;
+ }
+ return sys_vmsplice(fd, iov, nr_segs, flags);
+}
+
/*
* Exactly like fs/open.c:sys_open(), except that it doesn't set the
* O_LARGEFILE flag.
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 48ae0339af1..2edd7eec88f 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -711,7 +711,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
* direct blocks blocks
*/
if (num == 0 && blks > 1) {
- current_block = le32_to_cpu(where->key + 1);
+ current_block = le32_to_cpu(where->key) + 1;
for (i = 1; i < blks; i++)
*(where->p + i ) = cpu_to_le32(current_block++);
}
@@ -724,7 +724,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
if (block_i) {
block_i->last_alloc_logical_block = block + blks - 1;
block_i->last_alloc_physical_block =
- le32_to_cpu(where[num].key + blks - 1);
+ le32_to_cpu(where[num].key) + blks - 1;
}
/* We are done with atomic stuff, now do the rest of housekeeping */
@@ -814,11 +814,13 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
/* Simplest case - block found, no allocation needed */
if (!partial) {
- first_block = chain[depth - 1].key;
+ first_block = le32_to_cpu(chain[depth - 1].key);
clear_buffer_new(bh_result);
count++;
/*map more blocks*/
while (count < maxblocks && count <= blocks_to_boundary) {
+ unsigned long blk;
+
if (!verify_chain(chain, partial)) {
/*
* Indirect block might be removed by
@@ -831,8 +833,9 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
count = 0;
break;
}
- if (le32_to_cpu(*(chain[depth-1].p+count) ==
- (first_block + count)))
+ blk = le32_to_cpu(*(chain[depth-1].p + count));
+
+ if (blk == first_block + count)
count++;
else
break;
diff --git a/fs/locks.c b/fs/locks.c
index efad798824d..6f99c0a6f83 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -446,15 +446,14 @@ static struct lock_manager_operations lease_manager_ops = {
*/
static int lease_init(struct file *filp, int type, struct file_lock *fl)
{
+ if (assign_type(fl, type) != 0)
+ return -EINVAL;
+
fl->fl_owner = current->files;
fl->fl_pid = current->tgid;
fl->fl_file = filp;
fl->fl_flags = FL_LEASE;
- if (assign_type(fl, type) != 0) {
- locks_free_lock(fl);
- return -EINVAL;
- }
fl->fl_start = 0;
fl->fl_end = OFFSET_MAX;
fl->fl_ops = NULL;
@@ -466,16 +465,19 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
{
struct file_lock *fl = locks_alloc_lock();
- int error;
+ int error = -ENOMEM;
if (fl == NULL)
- return -ENOMEM;
+ goto out;
error = lease_init(filp, type, fl);
- if (error)
- return error;
+ if (error) {
+ locks_free_lock(fl);
+ fl = NULL;
+ }
+out:
*flp = fl;
- return 0;
+ return error;
}
/* Check if two locks overlap each other.
@@ -1372,6 +1374,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
goto out;
if (my_before != NULL) {
+ *flp = *my_before;
error = lease->fl_lmops->fl_change(my_before, arg);
goto out;
}
diff --git a/fs/pipe.c b/fs/pipe.c
index 7fefb10db8d..5acd8954aaa 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -55,7 +55,8 @@ void pipe_wait(struct pipe_inode_info *pipe)
}
static int
-pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
+pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len,
+ int atomic)
{
unsigned long copy;
@@ -64,8 +65,13 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
iov++;
copy = min_t(unsigned long, len, iov->iov_len);
- if (copy_from_user(to, iov->iov_base, copy))
- return -EFAULT;
+ if (atomic) {
+ if (__copy_from_user_inatomic(to, iov->iov_base, copy))
+ return -EFAULT;
+ } else {
+ if (copy_from_user(to, iov->iov_base, copy))
+ return -EFAULT;
+ }
to += copy;
len -= copy;
iov->iov_base += copy;
@@ -75,7 +81,8 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len)
}
static int
-pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
+pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len,
+ int atomic)
{
unsigned long copy;
@@ -84,8 +91,13 @@ pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
iov++;
copy = min_t(unsigned long, len, iov->iov_len);
- if (copy_to_user(iov->iov_base, from, copy))
- return -EFAULT;
+ if (atomic) {
+ if (__copy_to_user_inatomic(iov->iov_base, from, copy))
+ return -EFAULT;
+ } else {
+ if (copy_to_user(iov->iov_base, from, copy))
+ return -EFAULT;
+ }
from += copy;
len -= copy;
iov->iov_base += copy;
@@ -94,13 +106,52 @@ pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len)
return 0;
}
+/*
+ * Attempt to pre-fault in the user memory, so we can use atomic copies.
+ * Returns the number of bytes not faulted in.
+ */
+static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len)
+{
+ while (!iov->iov_len)
+ iov++;
+
+ while (len > 0) {
+ unsigned long this_len;
+
+ this_len = min_t(unsigned long, len, iov->iov_len);
+ if (fault_in_pages_writeable(iov->iov_base, this_len))
+ break;
+
+ len -= this_len;
+ iov++;
+ }
+
+ return len;
+}
+
+/*
+ * Pre-fault in the user memory, so we can use atomic copies.
+ */
+static void iov_fault_in_pages_read(struct iovec *iov, unsigned long len)
+{
+ while (!iov->iov_len)
+ iov++;
+
+ while (len > 0) {
+ unsigned long this_len;
+
+ this_len = min_t(unsigned long, len, iov->iov_len);
+ fault_in_pages_readable(iov->iov_base, this_len);
+ len -= this_len;
+ iov++;
+ }
+}
+
static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
struct page *page = buf->page;
- buf->flags &= ~PIPE_BUF_FLAG_STOLEN;
-
/*
* If nobody else uses this page, and we don't already have a
* temporary page, let's keep track of it as a one-deep
@@ -112,38 +163,58 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
page_cache_release(page);
}
-static void * anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
+void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf, int atomic)
{
+ if (atomic) {
+ buf->flags |= PIPE_BUF_FLAG_ATOMIC;
+ return kmap_atomic(buf->page, KM_USER0);
+ }
+
return kmap(buf->page);
}
-static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
+void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf, void *map_data)
{
- kunmap(buf->page);
+ if (buf->flags & PIPE_BUF_FLAG_ATOMIC) {
+ buf->flags &= ~PIPE_BUF_FLAG_ATOMIC;
+ kunmap_atomic(map_data, KM_USER0);
+ } else
+ kunmap(buf->page);
}
-static int anon_pipe_buf_steal(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
+int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
{
- buf->flags |= PIPE_BUF_FLAG_STOLEN;
- return 0;
+ struct page *page = buf->page;
+
+ if (page_count(page) == 1) {
+ lock_page(page);
+ return 0;
+ }
+
+ return 1;
}
-static void anon_pipe_buf_get(struct pipe_inode_info *info,
- struct pipe_buffer *buf)
+void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf)
{
page_cache_get(buf->page);
}
+int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
+{
+ return 0;
+}
+
static struct pipe_buf_operations anon_pipe_buf_ops = {
.can_merge = 1,
- .map = anon_pipe_buf_map,
- .unmap = anon_pipe_buf_unmap,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .pin = generic_pipe_buf_pin,
.release = anon_pipe_buf_release,
- .steal = anon_pipe_buf_steal,
- .get = anon_pipe_buf_get,
+ .steal = generic_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
};
static ssize_t
@@ -174,22 +245,33 @@ pipe_readv(struct file *filp, const struct iovec *_iov,
struct pipe_buf_operations *ops = buf->ops;
void *addr;
size_t chars = buf->len;
- int error;
+ int error, atomic;
if (chars > total_len)
chars = total_len;
- addr = ops->map(filp, pipe, buf);
- if (IS_ERR(addr)) {
+ error = ops->pin(pipe, buf);
+ if (error) {
if (!ret)
- ret = PTR_ERR(addr);
+ error = ret;
break;
}
- error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars);
- ops->unmap(pipe, buf);
+
+ atomic = !iov_fault_in_pages_write(iov, chars);
+redo:
+ addr = ops->map(pipe, buf, atomic);
+ error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic);
+ ops->unmap(pipe, buf, addr);
if (unlikely(error)) {
+ /*
+ * Just retry with the slow path if we failed.
+ */
+ if (atomic) {
+ atomic = 0;
+ goto redo;
+ }
if (!ret)
- ret = -EFAULT;
+ ret = error;
break;
}
ret += chars;
@@ -293,21 +375,28 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
int offset = buf->offset + buf->len;
if (ops->can_merge && offset + chars <= PAGE_SIZE) {
+ int error, atomic = 1;
void *addr;
- int error;
- addr = ops->map(filp, pipe, buf);
- if (IS_ERR(addr)) {
- error = PTR_ERR(addr);
+ error = ops->pin(pipe, buf);
+ if (error)
goto out;
- }
+
+ iov_fault_in_pages_read(iov, chars);
+redo1:
+ addr = ops->map(pipe, buf, atomic);
error = pipe_iov_copy_from_user(offset + addr, iov,
- chars);
- ops->unmap(pipe, buf);
+ chars, atomic);
+ ops->unmap(pipe, buf, addr);
ret = error;
do_wakeup = 1;
- if (error)
+ if (error) {
+ if (atomic) {
+ atomic = 0;
+ goto redo1;
+ }
goto out;
+ }
buf->len += chars;
total_len -= chars;
ret = chars;
@@ -330,7 +419,8 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
int newbuf = (pipe->curbuf + bufs) & (PIPE_BUFFERS-1);
struct pipe_buffer *buf = pipe->bufs + newbuf;
struct page *page = pipe->tmp_page;
- int error;
+ char *src;
+ int error, atomic = 1;
if (!page) {
page = alloc_page(GFP_HIGHUSER);
@@ -350,11 +440,27 @@ pipe_writev(struct file *filp, const struct iovec *_iov,
if (chars > total_len)
chars = total_len;
- error = pipe_iov_copy_from_user(kmap(page), iov, chars);
- kunmap(page);
+ iov_fault_in_pages_read(iov, chars);
+redo2:
+ if (atomic)
+ src = kmap_atomic(page, KM_USER0);
+ else
+ src = kmap(page);
+
+ error = pipe_iov_copy_from_user(src, iov, chars,
+ atomic);
+ if (atomic)
+ kunmap_atomic(src, KM_USER0);
+ else
+ kunmap(page);
+
if (unlikely(error)) {
+ if (atomic) {
+ atomic = 0;
+ goto redo2;
+ }
if (!ret)
- ret = -EFAULT;
+ ret = error;
break;
}
ret += chars;
diff --git a/fs/splice.c b/fs/splice.c
index a46ddd28561..a285fd746dc 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -51,7 +51,7 @@ struct splice_pipe_desc {
* addition of remove_mapping(). If success is returned, the caller may
* attempt to reuse this page for another destination.
*/
-static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
+static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
struct page *page = buf->page;
@@ -78,21 +78,19 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
return 1;
}
- buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU;
+ buf->flags |= PIPE_BUF_FLAG_LRU;
return 0;
}
-static void page_cache_pipe_buf_release(struct pipe_inode_info *info,
+static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
page_cache_release(buf->page);
- buf->page = NULL;
- buf->flags &= ~(PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU);
+ buf->flags &= ~PIPE_BUF_FLAG_LRU;
}
-static void *page_cache_pipe_buf_map(struct file *file,
- struct pipe_inode_info *info,
- struct pipe_buffer *buf)
+static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
{
struct page *page = buf->page;
int err;
@@ -118,64 +116,45 @@ static void *page_cache_pipe_buf_map(struct file *file,
}
/*
- * Page is ok afterall, fall through to mapping.
+ * Page is ok afterall, we are done.
*/
unlock_page(page);
}
- return kmap(page);
+ return 0;
error:
unlock_page(page);
- return ERR_PTR(err);
-}
-
-static void page_cache_pipe_buf_unmap(struct pipe_inode_info *info,
- struct pipe_buffer *buf)
-{
- kunmap(buf->page);
-}
-
-static void *user_page_pipe_buf_map(struct file *file,
- struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
-{
- return kmap(buf->page);
-}
-
-static void user_page_pipe_buf_unmap(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
-{
- kunmap(buf->page);
-}
-
-static void page_cache_pipe_buf_get(struct pipe_inode_info *info,
- struct pipe_buffer *buf)
-{
- page_cache_get(buf->page);
+ return err;
}
static struct pipe_buf_operations page_cache_pipe_buf_ops = {
.can_merge = 0,
- .map = page_cache_pipe_buf_map,
- .unmap = page_cache_pipe_buf_unmap,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .pin = page_cache_pipe_buf_pin,
.release = page_cache_pipe_buf_release,
.steal = page_cache_pipe_buf_steal,
- .get = page_cache_pipe_buf_get,
+ .get = generic_pipe_buf_get,
};
static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
- return 1;
+ if (!(buf->flags & PIPE_BUF_FLAG_GIFT))
+ return 1;
+
+ buf->flags |= PIPE_BUF_FLAG_LRU;
+ return generic_pipe_buf_steal(pipe, buf);
}
static struct pipe_buf_operations user_page_pipe_buf_ops = {
.can_merge = 0,
- .map = user_page_pipe_buf_map,
- .unmap = user_page_pipe_buf_unmap,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .pin = generic_pipe_buf_pin,
.release = page_cache_pipe_buf_release,
.steal = user_page_pipe_buf_steal,
- .get = page_cache_pipe_buf_get,
+ .get = generic_pipe_buf_get,
};
/*
@@ -210,6 +189,9 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
buf->offset = spd->partial[page_nr].offset;
buf->len = spd->partial[page_nr].len;
buf->ops = spd->ops;
+ if (spd->flags & SPLICE_F_GIFT)
+ buf->flags |= PIPE_BUF_FLAG_GIFT;
+
pipe->nrbufs++;
page_nr++;
ret += buf->len;
@@ -326,6 +308,12 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
page = find_get_page(mapping, index);
if (!page) {
/*
+ * Make sure the read-ahead engine is notified
+ * about this failure.
+ */
+ handle_ra_miss(mapping, &in->f_ra, index);
+
+ /*
* page didn't exist, allocate one.
*/
page = page_cache_alloc_cold(mapping);
@@ -336,6 +324,8 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
mapping_gfp_mask(mapping));
if (unlikely(error)) {
page_cache_release(page);
+ if (error == -EEXIST)
+ continue;
break;
}
/*
@@ -512,31 +502,21 @@ EXPORT_SYMBOL(generic_file_splice_read);
* Send 'sd->len' bytes to socket from 'sd->file' at position 'sd->pos'
* using sendpage(). Return the number of bytes sent.
*/
-static int pipe_to_sendpage(struct pipe_inode_info *info,
+static int pipe_to_sendpage(struct pipe_inode_info *pipe,
struct pipe_buffer *buf, struct splice_desc *sd)
{
struct file *file = sd->file;
loff_t pos = sd->pos;
- ssize_t ret;
- void *ptr;
- int more;
-
- /*
- * Sub-optimal, but we are limited by the pipe ->map. We don't
- * need a kmap'ed buffer here, we just want to make sure we
- * have the page pinned if the pipe page originates from the
- * page cache.
- */
- ptr = buf->ops->map(file, info, buf);
- if (IS_ERR(ptr))
- return PTR_ERR(ptr);
+ int ret, more;
- more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
+ ret = buf->ops->pin(pipe, buf);
+ if (!ret) {
+ more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
- ret = file->f_op->sendpage(file, buf->page, buf->offset, sd->len,
- &pos, more);
+ ret = file->f_op->sendpage(file, buf->page, buf->offset,
+ sd->len, &pos, more);
+ }
- buf->ops->unmap(info, buf);
return ret;
}
@@ -560,7 +540,7 @@ static int pipe_to_sendpage(struct pipe_inode_info *info,
* SPLICE_F_MOVE isn't set, or we cannot move the page, we simply create
* a new page in the output file page cache and fill/dirty that.
*/
-static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
+static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct splice_desc *sd)
{
struct file *file = sd->file;
@@ -569,15 +549,14 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
unsigned int offset, this_len;
struct page *page;
pgoff_t index;
- char *src;
int ret;
/*
* make sure the data in this buffer is uptodate
*/
- src = buf->ops->map(file, info, buf);
- if (IS_ERR(src))
- return PTR_ERR(src);
+ ret = buf->ops->pin(pipe, buf);
+ if (unlikely(ret))
+ return ret;
index = sd->pos >> PAGE_CACHE_SHIFT;
offset = sd->pos & ~PAGE_CACHE_MASK;
@@ -587,20 +566,25 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
this_len = PAGE_CACHE_SIZE - offset;
/*
- * Reuse buf page, if SPLICE_F_MOVE is set.
+ * Reuse buf page, if SPLICE_F_MOVE is set and we are doing a full
+ * page.
*/
- if (sd->flags & SPLICE_F_MOVE) {
+ if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) {
/*
- * If steal succeeds, buf->page is now pruned from the vm
- * side (LRU and page cache) and we can reuse it. The page
- * will also be looked on successful return.
+ * If steal succeeds, buf->page is now pruned from the
+ * pagecache and we can reuse it. The page will also be
+ * locked on successful return.
*/
- if (buf->ops->steal(info, buf))
+ if (buf->ops->steal(pipe, buf))
goto find_page;
page = buf->page;
- if (add_to_page_cache(page, mapping, index, gfp_mask))
+ if (add_to_page_cache(page, mapping, index, gfp_mask)) {
+ unlock_page(page);
goto find_page;
+ }
+
+ page_cache_get(page);
if (!(buf->flags & PIPE_BUF_FLAG_LRU))
lru_cache_add(page);
@@ -654,40 +638,55 @@ find_page:
}
ret = mapping->a_ops->prepare_write(file, page, offset, offset+this_len);
- if (ret == AOP_TRUNCATED_PAGE) {
+ if (unlikely(ret)) {
+ loff_t isize = i_size_read(mapping->host);
+
+ if (ret != AOP_TRUNCATED_PAGE)
+ unlock_page(page);
page_cache_release(page);
- goto find_page;
- } else if (ret)
+ if (ret == AOP_TRUNCATED_PAGE)
+ goto find_page;
+
+ /*
+ * prepare_write() may have instantiated a few blocks
+ * outside i_size. Trim these off again.
+ */
+ if (sd->pos + this_len > isize)
+ vmtruncate(mapping->host, isize);
+
goto out;
+ }
- if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) {
- char *dst = kmap_atomic(page, KM_USER0);
+ if (buf->page != page) {
+ /*
+ * Careful, ->map() uses KM_USER0!
+ */
+ char *src = buf->ops->map(pipe, buf, 1);
+ char *dst = kmap_atomic(page, KM_USER1);
memcpy(dst + offset, src + buf->offset, this_len);
flush_dcache_page(page);
- kunmap_atomic(dst, KM_USER0);
+ kunmap_atomic(dst, KM_USER1);
+ buf->ops->unmap(pipe, buf, src);
}
ret = mapping->a_ops->commit_write(file, page, offset, offset+this_len);
- if (ret == AOP_TRUNCATED_PAGE) {
+ if (!ret) {
+ /*
+ * Return the number of bytes written and mark page as
+ * accessed, we are now done!
+ */
+ ret = this_len;
+ mark_page_accessed(page);
+ balance_dirty_pages_ratelimited(mapping);
+ } else if (ret == AOP_TRUNCATED_PAGE) {
page_cache_release(page);
goto find_page;
- } else if (ret)
- goto out;
-
- /*
- * Return the number of bytes written.
- */
- ret = this_len;
- mark_page_accessed(page);
- balance_dirty_pages_ratelimited(mapping);
+ }
out:
- if (!(buf->flags & PIPE_BUF_FLAG_STOLEN))
- page_cache_release(page);
-
+ page_cache_release(page);
unlock_page(page);
out_nomem:
- buf->ops->unmap(info, buf);
return ret;
}
@@ -1095,7 +1094,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
*/
static int get_iovec_page_array(const struct iovec __user *iov,
unsigned int nr_vecs, struct page **pages,
- struct partial_page *partial)
+ struct partial_page *partial, int aligned)
{
int buffers = 0, error = 0;
@@ -1135,6 +1134,15 @@ static int get_iovec_page_array(const struct iovec __user *iov,
* in the user pages.
*/
off = (unsigned long) base & ~PAGE_MASK;
+
+ /*
+ * If asked for alignment, the offset must be zero and the
+ * length a multiple of the PAGE_SIZE.
+ */
+ error = -EINVAL;
+ if (aligned && (off || len & ~PAGE_MASK))
+ break;
+
npages = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (npages > PIPE_BUFFERS - buffers)
npages = PIPE_BUFFERS - buffers;
@@ -1150,7 +1158,7 @@ static int get_iovec_page_array(const struct iovec __user *iov,
* Fill this contiguous range into the partial page map.
*/
for (i = 0; i < error; i++) {
- const int plen = min_t(size_t, len, PAGE_SIZE) - off;
+ const int plen = min_t(size_t, len, PAGE_SIZE - off);
partial[buffers].offset = off;
partial[buffers].len = plen;
@@ -1228,7 +1236,8 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
else if (unlikely(!nr_segs))
return 0;
- spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial);
+ spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
+ flags & SPLICE_F_GIFT);
if (spd.nr_pages <= 0)
return spd.nr_pages;
@@ -1336,6 +1345,12 @@ static int link_pipe(struct pipe_inode_info *ipipe,
obuf = opipe->bufs + nbuf;
*obuf = *ibuf;
+ /*
+ * Don't inherit the gift flag, we need to
+ * prevent multiple steals of this page.
+ */
+ obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
+
if (obuf->len > len)
obuf->len = len;
diff --git a/fs/stat.c b/fs/stat.c
index 9948cc1685a..0f282face32 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -261,7 +261,7 @@ asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
return error;
}
-#ifndef __ARCH_WANT_STAT64
+#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
asmlinkage long sys_newfstatat(int dfd, char __user *filename,
struct stat __user *statbuf, int flag)
{
diff --git a/include/asm-arm/arch-aaec2000/debug-macro.S b/include/asm-arm/arch-aaec2000/debug-macro.S
index e4f1fa539a7..7b1fce021d8 100644
--- a/include/asm-arm/arch-aaec2000/debug-macro.S
+++ b/include/asm-arm/arch-aaec2000/debug-macro.S
@@ -9,6 +9,7 @@
* published by the Free Software Foundation.
*/
+#include "hardware.h"
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
index df31313ab07..1eb3503bd16 100644
--- a/include/asm-arm/arch-aaec2000/entry-macro.S
+++ b/include/asm-arm/arch-aaec2000/entry-macro.S
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*
*/
+#include <asm/arch/irqs.h>
.macro disable_fiq
.endm
diff --git a/include/asm-arm/arch-imx/debug-macro.S b/include/asm-arm/arch-imx/debug-macro.S
index 83f552f7bcc..c611871643a 100644
--- a/include/asm-arm/arch-imx/debug-macro.S
+++ b/include/asm-arm/arch-imx/debug-macro.S
@@ -16,7 +16,7 @@
tst \rx, #1 @ MMU enabled?
moveq \rx, #0x00000000 @ physical
movne \rx, #0xe0000000 @ virtual
- orr \rx, \rx, #0x00200000
+ orreq \rx, \rx, #0x00200000 @ physical
orr \rx, \rx, #0x00006000 @ UART1 offset
.endm
diff --git a/include/asm-arm/arch-imx/imx-uart.h b/include/asm-arm/arch-imx/imx-uart.h
new file mode 100644
index 00000000000..3a685e1780e
--- /dev/null
+++ b/include/asm-arm/arch-imx/imx-uart.h
@@ -0,0 +1,10 @@
+#ifndef ASMARM_ARCH_UART_H
+#define ASMARM_ARCH_UART_H
+
+#define IMXUART_HAVE_RTSCTS (1<<0)
+
+struct imxuart_platform_data {
+ unsigned int flags;
+};
+
+#endif
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index 942b622455b..b59520e56fc 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -260,6 +260,12 @@ out:
#endif
+#ifndef CONFIG_PCI
+
+#define __io(v) v
+
+#else
+
/*
* IXP4xx does not have a transparent cpu -> PCI I/O translation
* window. Instead, it has a set of registers that must be tweaked
@@ -578,6 +584,7 @@ __ixp4xx_iowrite32_rep(void __iomem *addr, const void *vaddr, u32 count)
#define ioport_map(port, nr) ((void __iomem*)(port + PIO_OFFSET))
#define ioport_unmap(addr)
+#endif // !CONFIG_PCI
#endif // __ASM_ARM_ARCH_IO_H
diff --git a/include/asm-arm/arch-ixp4xx/memory.h b/include/asm-arm/arch-ixp4xx/memory.h
index ee211d28a3e..af9667b57ab 100644
--- a/include/asm-arm/arch-ixp4xx/memory.h
+++ b/include/asm-arm/arch-ixp4xx/memory.h
@@ -14,7 +14,7 @@
*/
#define PHYS_OFFSET UL(0x00000000)
-#ifndef __ASSEMBLY__
+#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
void ixp4xx_adjust_zones(int node, unsigned long *size, unsigned long *holes);
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index 3e88a2a02a0..a008150abc5 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -24,27 +24,29 @@ typedef struct pxa_dma_desc {
volatile u32 dcmd; /* DCMD value for the current transfer */
} pxa_dma_desc;
+typedef enum {
+ DMA_PRIO_HIGH = 0,
+ DMA_PRIO_MEDIUM = 1,
+ DMA_PRIO_LOW = 2
+} pxa_dma_prio;
+
#if defined(CONFIG_PXA27x)
#define PXA_DMA_CHANNELS 32
-#define PXA_DMA_NBCH(prio) ((prio == DMA_PRIO_LOW) ? 16 : 8)
-typedef enum {
- DMA_PRIO_HIGH = 0,
- DMA_PRIO_MEDIUM = 8,
- DMA_PRIO_LOW = 16
-} pxa_dma_prio;
+#define pxa_for_each_dma_prio(ch, prio) \
+for ( \
+ ch = prio * 4; \
+ ch != (4 << prio) + 16; \
+ ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1) \
+)
#elif defined(CONFIG_PXA25x)
#define PXA_DMA_CHANNELS 16
-#define PXA_DMA_NBCH(prio) ((prio == DMA_PRIO_LOW) ? 8 : 4)
-typedef enum {
- DMA_PRIO_HIGH = 0,
- DMA_PRIO_MEDIUM = 4,
- DMA_PRIO_LOW = 8
-} pxa_dma_prio;
+#define pxa_for_each_dma_prio(ch, prio) \
+ for (ch = prio * 4; ch != (4 << prio); ch++)
#endif
diff --git a/include/asm-arm/bug.h b/include/asm-arm/bug.h
index 7fb02138f58..5ab8216f520 100644
--- a/include/asm-arm/bug.h
+++ b/include/asm-arm/bug.h
@@ -2,6 +2,7 @@
#define _ASMARM_BUG_H
#include <linux/config.h>
+#include <linux/stddef.h>
#ifdef CONFIG_BUG
#ifdef CONFIG_DEBUG_BUGVERBOSE
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index ee8dfea549b..cbf39a56dbe 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -363,7 +363,7 @@
/*
* The following syscalls are obsolete and no longer available for EABI.
*/
-#if defined(__ARM_EABI__)
+#if defined(__ARM_EABI__) && !defined(__KERNEL__)
#undef __NR_time
#undef __NR_umount
#undef __NR_stime
@@ -410,7 +410,8 @@ type name(void) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST() ); \
+ : __SYS_REG_LIST() \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -424,7 +425,8 @@ type name(type1 arg1) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0) ) ); \
+ : __SYS_REG_LIST( "0" (__r0) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -439,7 +441,8 @@ type name(type1 arg1,type2 arg2) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) ); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -456,7 +459,8 @@ type name(type1 arg1,type2 arg2,type3 arg3) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) ); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -474,7 +478,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
__asm__ __volatile__ ( \
__syscall(name) \
: "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) ); \
+ : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -494,7 +499,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
__syscall(name) \
: "=r" (__res_r0) \
: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
- "r" (__r3), "r" (__r4) ) ); \
+ "r" (__r3), "r" (__r4) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
@@ -514,7 +520,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
__syscall(name) \
: "=r" (__res_r0) \
: __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
- "r" (__r3), "r" (__r4), "r" (__r5) ) ); \
+ "r" (__r3), "r" (__r4), "r" (__r5) ) \
+ : "memory" ); \
__res = __res_r0; \
__syscall_return(type,__res); \
}
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 4321483cce5..9fcf0162d85 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -22,6 +22,7 @@
#define PPC_FEATURE_BOOKE 0x00008000
#define PPC_FEATURE_SMT 0x00004000
#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
+#define PPC_FEATURE_ARCH_2_05 0x00001000
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@@ -320,6 +321,11 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
CPU_FTR_MMCRA | CPU_FTR_SMT | \
CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR)
+#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
+ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
+ CPU_FTR_MMCRA | CPU_FTR_SMT | \
+ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
+ CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE)
#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -331,8 +337,8 @@ extern void do_cpu_ftr_fixups(unsigned long offset);
#ifdef __powerpc64__
#define CPU_FTRS_POSSIBLE \
(CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \
- CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_CELL | \
- CPU_FTR_CI_LARGE_PAGE)
+ CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \
+ CPU_FTRS_CELL | CPU_FTR_CI_LARGE_PAGE)
#else
enum {
CPU_FTRS_POSSIBLE =
@@ -376,8 +382,8 @@ enum {
#ifdef __powerpc64__
#define CPU_FTRS_ALWAYS \
(CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \
- CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_CELL & \
- CPU_FTRS_POSSIBLE)
+ CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \
+ CPU_FTRS_CELL & CPU_FTRS_POSSIBLE)
#else
enum {
CPU_FTRS_ALWAYS =
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 68efbea379c..f1c2469b884 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -9,6 +9,9 @@
* 2 of the License, or (at your option) any later version.
*/
+/* Check of existence of legacy devices */
+extern int check_legacy_ioport(unsigned long base_port);
+
#ifndef CONFIG_PPC64
#include <asm-ppc/io.h>
#else
@@ -437,9 +440,6 @@ out:
#define dma_cache_wback(_start,_size) do { } while (0)
#define dma_cache_wback_inv(_start,_size) do { } while (0)
-/* Check of existence of legacy devices */
-extern int check_legacy_ioport(unsigned long base_port);
-
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
diff --git a/include/asm-powerpc/page_64.h b/include/asm-powerpc/page_64.h
index 3fb061bab9e..eab779c2199 100644
--- a/include/asm-powerpc/page_64.h
+++ b/include/asm-powerpc/page_64.h
@@ -101,6 +101,7 @@ extern unsigned int HPAGE_SHIFT;
- (1U << GET_HTLB_AREA(addr))) & 0xffff)
#define ARCH_HAS_HUGEPAGE_ONLY_RANGE
+#define ARCH_HAS_HUGETLB_FREE_PGD_RANGE
#define ARCH_HAS_PREPARE_HUGEPAGE_RANGE
#define ARCH_HAS_SETCLEAR_HUGE_PTE
diff --git a/include/asm-powerpc/pgalloc.h b/include/asm-powerpc/pgalloc.h
index a00ee002cd1..9f0917c6865 100644
--- a/include/asm-powerpc/pgalloc.h
+++ b/include/asm-powerpc/pgalloc.h
@@ -17,11 +17,13 @@ extern kmem_cache_t *pgtable_cache[];
#define PTE_CACHE_NUM 0
#define PMD_CACHE_NUM 1
#define PGD_CACHE_NUM 2
+#define HUGEPTE_CACHE_NUM 3
#else
#define PTE_CACHE_NUM 0
#define PMD_CACHE_NUM 1
#define PUD_CACHE_NUM 1
#define PGD_CACHE_NUM 0
+#define HUGEPTE_CACHE_NUM 2
#endif
/*
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index f431d8b0b65..7cfcff3ef02 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -117,6 +117,7 @@ struct spu {
struct list_head list;
struct list_head sched_list;
int number;
+ int nid;
u32 isrc;
u32 node;
u64 flags;
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
index 1e19cd00af2..87362a05542 100644
--- a/include/asm-powerpc/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -4,6 +4,9 @@
#include <linux/config.h>
+struct sys_device;
+struct device_node;
+
#ifdef CONFIG_NUMA
#include <asm/mmzone.h>
@@ -27,6 +30,8 @@ static inline int node_to_first_cpu(int node)
return first_cpu(tmp);
}
+int of_node_to_nid(struct device_node *device);
+
#define pcibus_to_node(node) (-1)
#define pcibus_to_cpumask(bus) (cpu_online_map)
@@ -57,10 +62,29 @@ static inline int node_to_first_cpu(int node)
extern void __init dump_numa_cpu_topology(void);
+extern int sysfs_add_device_to_node(struct sys_device *dev, int nid);
+extern void sysfs_remove_device_from_node(struct sys_device *dev, int nid);
+
#else
+static inline int of_node_to_nid(struct device_node *device)
+{
+ return 0;
+}
+
static inline void dump_numa_cpu_topology(void) {}
+static inline int sysfs_add_device_to_node(struct sys_device *dev, int nid)
+{
+ return 0;
+}
+
+static inline void sysfs_remove_device_from_node(struct sys_device *dev,
+ int nid)
+{
+}
+
+
#include <asm-generic/topology.h>
#endif /* CONFIG_NUMA */
diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h
index 3872e924cdd..d83fc29c2bb 100644
--- a/include/asm-powerpc/uaccess.h
+++ b/include/asm-powerpc/uaccess.h
@@ -7,6 +7,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <asm/processor.h>
+#include <asm/page.h>
#define VERIFY_READ 0
#define VERIFY_WRITE 1
@@ -179,9 +180,11 @@ do { \
#define __put_user_nocheck(x, ptr, size) \
({ \
long __pu_err; \
- might_sleep(); \
+ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
+ if (!is_kernel_addr((unsigned long)__pu_addr)) \
+ might_sleep(); \
__chk_user_ptr(ptr); \
- __put_user_size((x), (ptr), (size), __pu_err); \
+ __put_user_size((x), __pu_addr, (size), __pu_err); \
__pu_err; \
})
@@ -258,9 +261,11 @@ do { \
({ \
long __gu_err; \
unsigned long __gu_val; \
+ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
__chk_user_ptr(ptr); \
- might_sleep(); \
- __get_user_size(__gu_val, (ptr), (size), __gu_err); \
+ if (!is_kernel_addr((unsigned long)__gu_addr)) \
+ might_sleep(); \
+ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
@@ -270,9 +275,11 @@ do { \
({ \
long __gu_err; \
long long __gu_val; \
+ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
__chk_user_ptr(ptr); \
- might_sleep(); \
- __get_user_size(__gu_val, (ptr), (size), __gu_err); \
+ if (!is_kernel_addr((unsigned long)__gu_addr)) \
+ might_sleep(); \
+ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 34325e29259..908acb44cb8 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -304,8 +304,25 @@
#define __NR_splice 283
#define __NR_tee 284
#define __NR_vmsplice 285
+#define __NR_openat 286
+#define __NR_mkdirat 287
+#define __NR_mknodat 288
+#define __NR_fchownat 289
+#define __NR_futimesat 290
+#ifdef __powerpc64__
+#define __NR_newfstatat 291
+#else
+#define __NR_fstatat64 291
+#endif
+#define __NR_unlinkat 292
+#define __NR_renameat 293
+#define __NR_linkat 294
+#define __NR_symlinkat 295
+#define __NR_readlinkat 296
+#define __NR_fchmodat 297
+#define __NR_faccessat 298
-#define __NR_syscalls 286
+#define __NR_syscalls 299
#ifdef __KERNEL__
#define __NR__exit __NR_exit
@@ -458,6 +475,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
#ifdef CONFIG_PPC64
#define __ARCH_WANT_COMPAT_SYS_TIME
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_NEWFSTATAT
#endif
/*
diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
index 973e6090823..31f362966a5 100644
--- a/include/asm-ppc/commproc.h
+++ b/include/asm-ppc/commproc.h
@@ -35,6 +35,7 @@
#define CPM_CR_INIT_TX ((ushort)0x0002)
#define CPM_CR_HUNT_MODE ((ushort)0x0003)
#define CPM_CR_STOP_TX ((ushort)0x0004)
+#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
#define CPM_CR_RESTART_TX ((ushort)0x0006)
#define CPM_CR_CLOSE_RX_BD ((ushort)0x0007)
#define CPM_CR_SET_GADDR ((ushort)0x0008)
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index b638b87cebe..c70344b9104 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -69,7 +69,7 @@
#define CPM_CR_INIT_TX ((ushort)0x0002)
#define CPM_CR_HUNT_MODE ((ushort)0x0003)
#define CPM_CR_STOP_TX ((ushort)0x0004)
-#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
+#define CPM_CR_GRA_STOP_TX ((ushort)0x0005)
#define CPM_CR_RESTART_TX ((ushort)0x0006)
#define CPM_CR_SET_GADDR ((ushort)0x0008)
#define CPM_CR_START_IDMA ((ushort)0x0009)
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 4b94f7059eb..40f197af650 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -39,6 +39,8 @@
#error "need definition of ppc_sys_devices"
#endif
+#define PPC_SYS_IORESOURCE_FIXUPPED 0x00000001
+
struct ppc_sys_spec {
/* PPC sys is matched via (ID & mask) == value, id could be
* PVR, SVR, IMMR, * etc. */
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 00ad9c754c7..4944c0fb8be 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -237,6 +237,7 @@ do { \
#endif
/* Bit definitions for CCR1. */
+#define CCR1_DPC 0x00000100 /* Disable L1 I-Cache/D-Cache parity checking */
#define CCR1_TCS 0x00000080 /* Timer Clock Select */
/* Bit definitions for the MCSR. */
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 32a48f623e2..f5611a721fb 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -41,7 +41,7 @@
#define __NR_capset 22 /* Linux Specific */
#define __NR_setuid 23 /* Implemented via setreuid in SunOS */
#define __NR_getuid 24 /* Common */
-/* #define __NR_time alias 25 ENOSYS under SunOS */
+#define __NR_vmsplice 25 /* ENOSYS under SunOS */
#define __NR_ptrace 26 /* Common */
#define __NR_alarm 27 /* Implemented via setitimer in SunOS */
#define __NR_sigaltstack 28 /* Common */
diff --git a/include/asm-sparc64/tlbflush.h b/include/asm-sparc64/tlbflush.h
index 9ad5d9c51d4..e3a7c453b50 100644
--- a/include/asm-sparc64/tlbflush.h
+++ b/include/asm-sparc64/tlbflush.h
@@ -22,8 +22,6 @@ extern void flush_tlb_pending(void);
/* Local cpu only. */
extern void __flush_tlb_all(void);
-extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
-
extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
#ifndef CONFIG_SMP
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index ca80e8aca12..68705748bec 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -41,7 +41,7 @@
#define __NR_capset 22 /* Linux Specific */
#define __NR_setuid 23 /* Implemented via setreuid in SunOS */
#define __NR_getuid 24 /* Common */
-/* #define __NR_time alias 25 ENOSYS under SunOS */
+#define __NR_vmsplice 25 /* ENOSYS under SunOS */
#define __NR_ptrace 26 /* Common */
#define __NR_alarm 27 /* Implemented via setitimer in SunOS */
#define __NR_sigaltstack 28 /* Common */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 1c47c59058c..b74c148f14e 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -83,6 +83,7 @@
#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */
#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */
#define AUDIT_CWD 1307 /* Current working directory */
+#define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -145,6 +146,11 @@
#define AUDIT_PERS 10
#define AUDIT_ARCH 11
#define AUDIT_MSGTYPE 12
+#define AUDIT_SE_USER 13 /* security label user */
+#define AUDIT_SE_ROLE 14 /* security label role */
+#define AUDIT_SE_TYPE 15 /* security label type */
+#define AUDIT_SE_SEN 16 /* security label sensitivity label */
+#define AUDIT_SE_CLR 17 /* security label clearance label */
/* These are ONLY useful when checking
* at syscall exit time (AUDIT_AT_EXIT). */
@@ -287,10 +293,10 @@ struct netlink_skb_parms;
/* Public API */
extern int audit_alloc(struct task_struct *task);
extern void audit_free(struct task_struct *task);
-extern void audit_syscall_entry(struct task_struct *task, int arch,
+extern void audit_syscall_entry(int arch,
int major, unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3);
-extern void audit_syscall_exit(struct task_struct *task, int failed, long return_code);
+extern void audit_syscall_exit(int failed, long return_code);
extern void audit_getname(const char *name);
extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags);
@@ -314,7 +320,8 @@ extern void auditsc_get_stamp(struct audit_context *ctx,
struct timespec *t, unsigned int *serial);
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
-extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
+extern int audit_ipc_obj(struct kern_ipc_perm *ipcp);
+extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
extern int audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
@@ -323,8 +330,8 @@ extern int audit_set_macxattr(const char *name);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
-#define audit_syscall_entry(t,ta,a,b,c,d,e) do { ; } while (0)
-#define audit_syscall_exit(t,f,r) do { ; } while (0)
+#define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
+#define audit_syscall_exit(f,r) do { ; } while (0)
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
#define __audit_inode(n,i,f) do { ; } while (0)
@@ -333,7 +340,8 @@ extern int audit_set_macxattr(const char *name);
#define audit_inode_child(d,i,p) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
-#define audit_ipc_perms(q,u,g,m,i) ({ 0; })
+#define audit_ipc_obj(i) ({ 0; })
+#define audit_ipc_set_perm(q,u,g,m,i) ({ 0; })
#define audit_socketcall(n,a) ({ 0; })
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
@@ -366,7 +374,7 @@ extern void audit_log_d_path(struct audit_buffer *ab,
extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int uid, int seq,
- void *data, size_t datasz, uid_t loginuid);
+ void *data, size_t datasz, uid_t loginuid, u32 sid);
#else
#define audit_log(c,g,t,f,...) do { ; } while (0)
#define audit_log_start(c,g,t) ({ NULL; })
diff --git a/include/linux/fs_uart_pd.h b/include/linux/fs_uart_pd.h
new file mode 100644
index 00000000000..f5975126b71
--- /dev/null
+++ b/include/linux/fs_uart_pd.h
@@ -0,0 +1,60 @@
+/*
+ * Platform information definitions for the CPM Uart driver.
+ *
+ * 2006 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef FS_UART_PD_H
+#define FS_UART_PD_H
+
+#include <linux/version.h>
+#include <asm/types.h>
+
+enum fs_uart_id {
+ fsid_smc1_uart,
+ fsid_smc2_uart,
+ fsid_scc1_uart,
+ fsid_scc2_uart,
+ fsid_scc3_uart,
+ fsid_scc4_uart,
+ fs_uart_nr,
+};
+
+static inline int fs_uart_id_scc2fsid(int id)
+{
+ return fsid_scc1_uart + id - 1;
+}
+
+static inline int fs_uart_id_fsid2scc(int id)
+{
+ return id - fsid_scc1_uart + 1;
+}
+
+static inline int fs_uart_id_smc2fsid(int id)
+{
+ return fsid_smc1_uart + id - 1;
+}
+
+static inline int fs_uart_id_fsid2smc(int id)
+{
+ return id - fsid_smc1_uart + 1;
+}
+
+struct fs_uart_platform_info {
+ void(*init_ioports)(void);
+ /* device specific information */
+ int fs_no; /* controller index */
+ u32 uart_clk;
+ u8 tx_num_fifo;
+ u8 tx_buf_size;
+ u8 rx_num_fifo;
+ u8 rx_buf_size;
+ u8 brg;
+};
+
+#endif
diff --git a/include/linux/input.h b/include/linux/input.h
index b0e612dda0c..50e338d2ffd 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -12,8 +12,6 @@
#ifdef __KERNEL__
#include <linux/time.h>
#include <linux/list.h>
-#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#else
#include <sys/time.h>
#include <sys/ioctl.h>
@@ -58,6 +56,8 @@ struct input_absinfo {
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */
+#define EVIOCGREP _IOR('E', 0x03, int[2]) /* get repeat settings */
+#define EVIOCSREP _IOW('E', 0x03, int[2]) /* set repeat settings */
#define EVIOCGKEYCODE _IOR('E', 0x04, int[2]) /* get keycode */
#define EVIOCSKEYCODE _IOW('E', 0x04, int[2]) /* set keycode */
@@ -577,15 +577,15 @@ struct input_absinfo {
* Switch events
*/
-#define SW_0 0x00
-#define SW_1 0x01
-#define SW_2 0x02
-#define SW_3 0x03
-#define SW_4 0x04
-#define SW_5 0x05
-#define SW_6 0x06
-#define SW_7 0x07
-#define SW_MAX 0x0f
+#define SW_0 0x00
+#define SW_1 0x01
+#define SW_2 0x02
+#define SW_3 0x03
+#define SW_4 0x04
+#define SW_5 0x05
+#define SW_6 0x06
+#define SW_7 0x07
+#define SW_MAX 0x0f
/*
* Misc events
@@ -805,52 +805,16 @@ struct ff_effect {
#define FF_MAX 0x7f
-struct input_device_id {
-
- kernel_ulong_t flags;
-
- struct input_id id;
-
- kernel_ulong_t evbit[EV_MAX/BITS_PER_LONG+1];
- kernel_ulong_t keybit[KEY_MAX/BITS_PER_LONG+1];
- kernel_ulong_t relbit[REL_MAX/BITS_PER_LONG+1];
- kernel_ulong_t absbit[ABS_MAX/BITS_PER_LONG+1];
- kernel_ulong_t mscbit[MSC_MAX/BITS_PER_LONG+1];
- kernel_ulong_t ledbit[LED_MAX/BITS_PER_LONG+1];
- kernel_ulong_t sndbit[SND_MAX/BITS_PER_LONG+1];
- kernel_ulong_t ffbit[FF_MAX/BITS_PER_LONG+1];
- kernel_ulong_t swbit[SW_MAX/BITS_PER_LONG+1];
-
- kernel_ulong_t driver_info;
-};
-
-/*
- * Structure for hotplug & device<->driver matching.
- */
-
-#define INPUT_DEVICE_ID_MATCH_BUS 1
-#define INPUT_DEVICE_ID_MATCH_VENDOR 2
-#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
-#define INPUT_DEVICE_ID_MATCH_VERSION 8
-
-#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
-#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
-#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
-#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
-#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
-#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
-#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
-#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
-#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
-
#ifdef __KERNEL__
/*
* In-kernel definitions.
*/
+#include <linux/device.h>
#include <linux/fs.h>
#include <linux/timer.h>
+#include <linux/mod_devicetable.h>
#define NBITS(x) (((x)/BITS_PER_LONG)+1)
#define BIT(x) (1UL<<((x)%BITS_PER_LONG))
@@ -951,9 +915,49 @@ struct input_dev {
};
#define to_input_dev(d) container_of(d, struct input_dev, cdev)
-#define INPUT_DEVICE_ID_MATCH_DEVICE\
+/*
+ * Verify that we are in sync with input_device_id mod_devicetable.h #defines
+ */
+
+#if EV_MAX != INPUT_DEVICE_ID_EV_MAX
+#error "EV_MAX and INPUT_DEVICE_ID_EV_MAX do not match"
+#endif
+
+#if KEY_MAX != INPUT_DEVICE_ID_KEY_MAX
+#error "KEY_MAX and INPUT_DEVICE_ID_KEY_MAX do not match"
+#endif
+
+#if REL_MAX != INPUT_DEVICE_ID_REL_MAX
+#error "REL_MAX and INPUT_DEVICE_ID_REL_MAX do not match"
+#endif
+
+#if ABS_MAX != INPUT_DEVICE_ID_ABS_MAX
+#error "ABS_MAX and INPUT_DEVICE_ID_ABS_MAX do not match"
+#endif
+
+#if MSC_MAX != INPUT_DEVICE_ID_MSC_MAX
+#error "MSC_MAX and INPUT_DEVICE_ID_MSC_MAX do not match"
+#endif
+
+#if LED_MAX != INPUT_DEVICE_ID_LED_MAX
+#error "LED_MAX and INPUT_DEVICE_ID_LED_MAX do not match"
+#endif
+
+#if SND_MAX != INPUT_DEVICE_ID_SND_MAX
+#error "SND_MAX and INPUT_DEVICE_ID_SND_MAX do not match"
+#endif
+
+#if FF_MAX != INPUT_DEVICE_ID_FF_MAX
+#error "FF_MAX and INPUT_DEVICE_ID_FF_MAX do not match"
+#endif
+
+#if SW_MAX != INPUT_DEVICE_ID_SW_MAX
+#error "SW_MAX and INPUT_DEVICE_ID_SW_MAX do not match"
+#endif
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE \
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
-#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION \
(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
struct input_handle;
@@ -1016,7 +1020,8 @@ static inline void input_put_device(struct input_dev *dev)
static inline void input_free_device(struct input_dev *dev)
{
- input_put_device(dev);
+ if (dev)
+ input_put_device(dev);
}
int input_register_device(struct input_dev *);
diff --git a/include/linux/list.h b/include/linux/list.h
index 67258b47e9c..76f05718342 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -619,7 +619,7 @@ static inline void hlist_del_rcu(struct hlist_node *n)
static inline void hlist_del_init(struct hlist_node *n)
{
- if (n->pprev) {
+ if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 30dd978c1ec..991a37382a2 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -28,6 +28,7 @@ struct mmc_csd {
unsigned short cmdclass;
unsigned short tacc_clks;
unsigned int tacc_ns;
+ unsigned int r2w_factor;
unsigned int max_dtr;
unsigned int read_blkbits;
unsigned int write_blkbits;
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 7b08c11ec4c..f6977708585 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -249,4 +249,52 @@ struct i2c_device_id {
__u16 id;
};
+/* Input */
+#define INPUT_DEVICE_ID_EV_MAX 0x1f
+#define INPUT_DEVICE_ID_KEY_MAX 0x1ff
+#define INPUT_DEVICE_ID_REL_MAX 0x0f
+#define INPUT_DEVICE_ID_ABS_MAX 0x3f
+#define INPUT_DEVICE_ID_MSC_MAX 0x07
+#define INPUT_DEVICE_ID_LED_MAX 0x0f
+#define INPUT_DEVICE_ID_SND_MAX 0x07
+#define INPUT_DEVICE_ID_FF_MAX 0x7f
+#define INPUT_DEVICE_ID_SW_MAX 0x0f
+
+#define INPUT_DEVICE_ID_MATCH_BUS 1
+#define INPUT_DEVICE_ID_MATCH_VENDOR 2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
+#define INPUT_DEVICE_ID_MATCH_VERSION 8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT 0x0010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x0020
+#define INPUT_DEVICE_ID_MATCH_RELBIT 0x0040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x0080
+#define INPUT_DEVICE_ID_MATCH_MSCIT 0x0100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x0200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x0400
+#define INPUT_DEVICE_ID_MATCH_FFBIT 0x0800
+#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
+
+struct input_device_id {
+
+ kernel_ulong_t flags;
+
+ __u16 bustype;
+ __u16 vendor;
+ __u16 product;
+ __u16 version;
+
+ kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
+ kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
+
+ kernel_ulong_t driver_info;
+};
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 38701454e19..48cc32d83f7 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -337,6 +337,10 @@ struct compat_xt_entry_match
char name[XT_FUNCTION_MAXNAMELEN - 1];
u_int8_t revision;
} user;
+ struct {
+ u_int16_t match_size;
+ compat_uptr_t match;
+ } kernel;
u_int16_t match_size;
} u;
unsigned char data[0];
@@ -350,6 +354,10 @@ struct compat_xt_entry_target
char name[XT_FUNCTION_MAXNAMELEN - 1];
u_int8_t revision;
} user;
+ struct {
+ u_int16_t target_size;
+ compat_uptr_t target;
+ } kernel;
u_int16_t target_size;
} u;
unsigned char data[0];
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
index 0bd828081c0..c6e9a0b6d30 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h
@@ -2,7 +2,7 @@
* ip_conntrack_helper_h323_asn1.h - BER and PER decoding library for H.323
* conntrack/NAT module.
*
- * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
*
* This source code is licensed under General Public License version 2.
*
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index f8f3d1c927f..87b8a5703eb 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -143,6 +143,7 @@ struct netlink_skb_parms
__u32 dst_group;
kernel_cap_t eff_cap;
__u32 loginuid; /* Login (audit) uid */
+ __u32 sid; /* SELinux security id */
};
#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 0008d4bd405..ea4f7cd7bfd 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -5,8 +5,9 @@
#define PIPE_BUFFERS (16)
-#define PIPE_BUF_FLAG_STOLEN 0x01
-#define PIPE_BUF_FLAG_LRU 0x02
+#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */
+#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
+#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
struct pipe_buffer {
struct page *page;
@@ -15,10 +16,23 @@ struct pipe_buffer {
unsigned int flags;
};
+/*
+ * Note on the nesting of these functions:
+ *
+ * ->pin()
+ * ->steal()
+ * ...
+ * ->map()
+ * ...
+ * ->unmap()
+ *
+ * That is, ->map() must be called on a pinned buffer, same goes for ->steal().
+ */
struct pipe_buf_operations {
int can_merge;
- void * (*map)(struct file *, struct pipe_inode_info *, struct pipe_buffer *);
- void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *);
+ void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int);
+ void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *);
+ int (*pin)(struct pipe_inode_info *, struct pipe_buffer *);
void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
@@ -51,6 +65,13 @@ struct pipe_inode_info * alloc_pipe_info(struct inode * inode);
void free_pipe_info(struct inode * inode);
void __free_pipe_info(struct pipe_inode_info *);
+/* Generic pipe buffer ops functions */
+void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
+void generic_pipe_buf_unmap(struct pipe_inode_info *, struct pipe_buffer *, void *);
+void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_pin(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
+
/*
* splice is tied to pipes as a transport (at least for now), so we'll just
* add the splice flags here.
@@ -60,6 +81,7 @@ void __free_pipe_info(struct pipe_inode_info *);
/* we may still block on the fd we splice */
/* from/to, of course */
#define SPLICE_F_MORE (0x04) /* expect more data */
+#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */
/*
* Passed to the actors
diff --git a/include/linux/security.h b/include/linux/security.h
index aaa0a5cdbf7..1bab48f6aea 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -869,11 +869,6 @@ struct swap_info_struct;
* @ipcp contains the kernel IPC permission structure
* @flag contains the desired (requested) permission set
* Return 0 if permission is granted.
- * @ipc_getsecurity:
- * Copy the security label associated with the ipc object into
- * @buffer. @buffer may be NULL to request the size of the buffer
- * required. @size indicates the size of @buffer in bytes. Return
- * number of bytes used/required on success.
*
* Security hooks for individual messages held in System V IPC message queues
* @msg_msg_alloc_security:
@@ -1223,7 +1218,6 @@ struct security_operations {
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
- int (*ipc_getsecurity)(struct kern_ipc_perm *ipcp, void *buffer, size_t size);
int (*msg_msg_alloc_security) (struct msg_msg * msg);
void (*msg_msg_free_security) (struct msg_msg * msg);
@@ -1887,11 +1881,6 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
return security_ops->ipc_permission (ipcp, flag);
}
-static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- return security_ops->ipc_getsecurity(ipcp, buffer, size);
-}
-
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return security_ops->msg_msg_alloc_security (msg);
@@ -2532,11 +2521,6 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
return 0;
}
-static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- return -EOPNOTSUPP;
-}
-
static inline int security_msg_msg_alloc (struct msg_msg * msg)
{
return 0;
diff --git a/include/linux/selinux.h b/include/linux/selinux.h
new file mode 100644
index 00000000000..4047bcde448
--- /dev/null
+++ b/include/linux/selinux.h
@@ -0,0 +1,177 @@
+/*
+ * SELinux services exported to the rest of the kernel.
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.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 _LINUX_SELINUX_H
+#define _LINUX_SELINUX_H
+
+struct selinux_audit_rule;
+struct audit_context;
+struct inode;
+struct kern_ipc_perm;
+
+#ifdef CONFIG_SECURITY_SELINUX
+
+/**
+ * selinux_audit_rule_init - alloc/init an selinux audit rule structure.
+ * @field: the field this rule refers to
+ * @op: the operater the rule uses
+ * @rulestr: the text "target" of the rule
+ * @rule: pointer to the new rule structure returned via this
+ *
+ * Returns 0 if successful, -errno if not. On success, the rule structure
+ * will be allocated internally. The caller must free this structure with
+ * selinux_audit_rule_free() after use.
+ */
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+ struct selinux_audit_rule **rule);
+
+/**
+ * selinux_audit_rule_free - free an selinux audit rule structure.
+ * @rule: pointer to the audit rule to be freed
+ *
+ * This will free all memory associated with the given rule.
+ * If @rule is NULL, no operation is performed.
+ */
+void selinux_audit_rule_free(struct selinux_audit_rule *rule);
+
+/**
+ * selinux_audit_rule_match - determine if a context ID matches a rule.
+ * @ctxid: the context ID to check
+ * @field: the field this rule refers to
+ * @op: the operater the rule uses
+ * @rule: pointer to the audit rule to check against
+ * @actx: the audit context (can be NULL) associated with the check
+ *
+ * Returns 1 if the context id matches the rule, 0 if it does not, and
+ * -errno on failure.
+ */
+int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
+ struct selinux_audit_rule *rule,
+ struct audit_context *actx);
+
+/**
+ * selinux_audit_set_callback - set the callback for policy reloads.
+ * @callback: the function to call when the policy is reloaded
+ *
+ * This sets the function callback function that will update the rules
+ * upon policy reloads. This callback should rebuild all existing rules
+ * using selinux_audit_rule_init().
+ */
+void selinux_audit_set_callback(int (*callback)(void));
+
+/**
+ * selinux_task_ctxid - determine a context ID for a process.
+ * @tsk: the task object
+ * @ctxid: ID value returned via this
+ *
+ * On return, ctxid will contain an ID for the context. This value
+ * should only be used opaquely.
+ */
+void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid);
+
+/**
+ * selinux_ctxid_to_string - map a security context ID to a string
+ * @ctxid: security context ID to be converted.
+ * @ctx: address of context string to be returned
+ * @ctxlen: length of returned context string.
+ *
+ * Returns 0 if successful, -errno if not. On success, the context
+ * string will be allocated internally, and the caller must call
+ * kfree() on it after use.
+ */
+int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen);
+
+/**
+ * selinux_get_inode_sid - get the inode's security context ID
+ * @inode: inode structure to get the sid from.
+ * @sid: pointer to security context ID to be filled in.
+ *
+ * Returns nothing
+ */
+void selinux_get_inode_sid(const struct inode *inode, u32 *sid);
+
+/**
+ * selinux_get_ipc_sid - get the ipc security context ID
+ * @ipcp: ipc structure to get the sid from.
+ * @sid: pointer to security context ID to be filled in.
+ *
+ * Returns nothing
+ */
+void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
+
+/**
+ * selinux_get_task_sid - return the SID of task
+ * @tsk: the task whose SID will be returned
+ * @sid: pointer to security context ID to be filled in.
+ *
+ * Returns nothing
+ */
+void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
+
+
+#else
+
+static inline int selinux_audit_rule_init(u32 field, u32 op,
+ char *rulestr,
+ struct selinux_audit_rule **rule)
+{
+ return -ENOTSUPP;
+}
+
+static inline void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+{
+ return;
+}
+
+static inline int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
+ struct selinux_audit_rule *rule,
+ struct audit_context *actx)
+{
+ return 0;
+}
+
+static inline void selinux_audit_set_callback(int (*callback)(void))
+{
+ return;
+}
+
+static inline void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid)
+{
+ *ctxid = 0;
+}
+
+static inline int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen)
+{
+ *ctx = NULL;
+ *ctxlen = 0;
+ return 0;
+}
+
+static inline void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+{
+ *sid = 0;
+}
+
+static inline void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+{
+ *sid = 0;
+}
+
+static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+{
+ *sid = 0;
+}
+
+#endif /* CONFIG_SECURITY_SELINUX */
+
+#endif /* _LINUX_SELINUX_H */
diff --git a/include/linux/spi/ads7846.h b/include/linux/spi/ads7846.h
index 72261e0f2ac..adb3dafd33e 100644
--- a/include/linux/spi/ads7846.h
+++ b/include/linux/spi/ads7846.h
@@ -14,5 +14,12 @@ struct ads7846_platform_data {
u16 x_min, x_max;
u16 y_min, y_max;
u16 pressure_min, pressure_max;
+
+ u16 debounce_max; /* max number of additional readings
+ * per sample */
+ u16 debounce_tol; /* tolerance used for filtering */
+ u16 debounce_rep; /* additional consecutive good readings
+ * required after the first two */
+ int (*get_pendown_state)(void);
};
diff --git a/include/net/ax25.h b/include/net/ax25.h
index d052b221dbc..5bd99748705 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -145,14 +145,14 @@ enum {
#define AX25_DEF_CONMODE 2 /* Connected mode allowed */
#define AX25_DEF_WINDOW 2 /* Window=2 */
#define AX25_DEF_EWINDOW 32 /* Module-128 Window=32 */
-#define AX25_DEF_T1 (10 * HZ) /* T1=10s */
-#define AX25_DEF_T2 (3 * HZ) /* T2=3s */
-#define AX25_DEF_T3 (300 * HZ) /* T3=300s */
+#define AX25_DEF_T1 10000 /* T1=10s */
+#define AX25_DEF_T2 3000 /* T2=3s */
+#define AX25_DEF_T3 300000 /* T3=300s */
#define AX25_DEF_N2 10 /* N2=10 */
-#define AX25_DEF_IDLE (0 * 60 * HZ) /* Idle=None */
+#define AX25_DEF_IDLE 0 /* Idle=None */
#define AX25_DEF_PACLEN 256 /* Paclen=256 */
#define AX25_DEF_PROTOCOL AX25_PROTO_STD_SIMPLEX /* Standard AX.25 */
-#define AX25_DEF_DS_TIMEOUT (3 * 60 * HZ) /* DAMA timeout 3 minutes */
+#define AX25_DEF_DS_TIMEOUT 180000 /* DAMA timeout 3 minutes */
typedef struct ax25_uid_assoc {
struct hlist_node uid_node;
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 1da294c4752..e837f98fdb5 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -150,7 +150,7 @@ static inline void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
static inline int inet_twsk_dead_hashed(const struct inet_timewait_sock *tw)
{
- return tw->tw_death_node.pprev != NULL;
+ return !hlist_unhashed(&tw->tw_death_node);
}
static inline void inet_twsk_dead_node_init(struct inet_timewait_sock *tw)
diff --git a/include/net/netrom.h b/include/net/netrom.h
index a5ee53bce62..e0ca112024a 100644
--- a/include/net/netrom.h
+++ b/include/net/netrom.h
@@ -42,11 +42,11 @@ enum {
#define NR_COND_PEER_RX_BUSY 0x04
#define NR_COND_OWN_RX_BUSY 0x08
-#define NR_DEFAULT_T1 (120 * HZ) /* Outstanding frames - 120 seconds */
-#define NR_DEFAULT_T2 (5 * HZ) /* Response delay - 5 seconds */
+#define NR_DEFAULT_T1 120000 /* Outstanding frames - 120 seconds */
+#define NR_DEFAULT_T2 5000 /* Response delay - 5 seconds */
#define NR_DEFAULT_N2 3 /* Number of Retries - 3 */
-#define NR_DEFAULT_T4 (180 * HZ) /* Busy Delay - 180 seconds */
-#define NR_DEFAULT_IDLE (0 * 60 * HZ) /* No Activity Timeout - none */
+#define NR_DEFAULT_T4 180000 /* Busy Delay - 180 seconds */
+#define NR_DEFAULT_IDLE 0 /* No Activity Timeout - none */
#define NR_DEFAULT_WINDOW 4 /* Default Window Size - 4 */
#define NR_DEFAULT_OBS 6 /* Default Obsolescence Count - 6 */
#define NR_DEFAULT_QUAL 10 /* Default Neighbour Quality - 10 */
diff --git a/include/net/rose.h b/include/net/rose.h
index 3249b979605..012b09ed240 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -49,14 +49,14 @@ enum {
ROSE_STATE_5 /* Deferred Call Acceptance */
};
-#define ROSE_DEFAULT_T0 (180 * HZ) /* Default T10 T20 value */
-#define ROSE_DEFAULT_T1 (200 * HZ) /* Default T11 T21 value */
-#define ROSE_DEFAULT_T2 (180 * HZ) /* Default T12 T22 value */
-#define ROSE_DEFAULT_T3 (180 * HZ) /* Default T13 T23 value */
-#define ROSE_DEFAULT_HB (5 * HZ) /* Default Holdback value */
-#define ROSE_DEFAULT_IDLE (0 * 60 * HZ) /* No Activity Timeout - none */
+#define ROSE_DEFAULT_T0 180000 /* Default T10 T20 value */
+#define ROSE_DEFAULT_T1 200000 /* Default T11 T21 value */
+#define ROSE_DEFAULT_T2 180000 /* Default T12 T22 value */
+#define ROSE_DEFAULT_T3 180000 /* Default T13 T23 value */
+#define ROSE_DEFAULT_HB 5000 /* Default Holdback value */
+#define ROSE_DEFAULT_IDLE 0 /* No Activity Timeout - none */
#define ROSE_DEFAULT_ROUTING 1 /* Default routing flag */
-#define ROSE_DEFAULT_FAIL_TIMEOUT (120 * HZ) /* Time until link considered usable */
+#define ROSE_DEFAULT_FAIL_TIMEOUT 120000 /* Time until link considered usable */
#define ROSE_DEFAULT_MAXVC 50 /* Maximum number of VCs per neighbour */
#define ROSE_DEFAULT_WINDOW_SIZE 7 /* Default window size */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index eba99f37551..7f4fea173fb 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -712,6 +712,7 @@ struct sctp_chunk {
__u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */
__s8 fast_retransmit; /* Is this chunk fast retransmitted? */
__u8 tsn_missing_report; /* Data chunk missing counter. */
+ __u8 data_accepted; /* At least 1 chunk in this packet accepted */
};
void sctp_chunk_hold(struct sctp_chunk *);
diff --git a/include/net/sock.h b/include/net/sock.h
index ff8b0dad7b0..c9fad6fb629 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -279,7 +279,7 @@ static inline int sk_unhashed(const struct sock *sk)
static inline int sk_hashed(const struct sock *sk)
{
- return sk->sk_node.pprev != NULL;
+ return !sk_unhashed(sk);
}
static __inline__ void sk_node_init(struct hlist_node *node)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index df70e7592ab..373425895fa 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -374,12 +374,14 @@ struct snd_pcm_substream {
/* -- OSS things -- */
struct snd_pcm_oss_substream oss;
#endif
+#ifdef CONFIG_SND_VERBOSE_PROCFS
struct snd_info_entry *proc_root;
struct snd_info_entry *proc_info_entry;
struct snd_info_entry *proc_hw_params_entry;
struct snd_info_entry *proc_sw_params_entry;
struct snd_info_entry *proc_status_entry;
struct snd_info_entry *proc_prealloc_entry;
+#endif
/* misc flags */
unsigned int no_mmap_ctrl: 1;
unsigned int hw_opened: 1;
@@ -400,12 +402,14 @@ struct snd_pcm_str {
struct snd_pcm_oss_stream oss;
#endif
struct snd_pcm_file *files;
+#ifdef CONFIG_SND_VERBOSE_PROCFS
struct snd_info_entry *proc_root;
struct snd_info_entry *proc_info_entry;
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
unsigned int xrun_debug; /* 0 = disabled, 1 = verbose, 2 = stacktrace */
struct snd_info_entry *proc_xrun_debug_entry;
#endif
+#endif
};
struct snd_pcm {
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index 39df2baca18..c854647b6f3 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -75,7 +75,9 @@ struct snd_pcm_oss_substream {
struct snd_pcm_oss_stream {
struct snd_pcm_oss_setup *setup_list; /* setup list */
struct mutex setup_mutex;
+#ifdef CONFIG_SND_VERBOSE_PROCFS
struct snd_info_entry *proc_entry;
+#endif
};
struct snd_pcm_oss {
diff --git a/init/main.c b/init/main.c
index 4a2f0898dda..f715b9b8975 100644
--- a/init/main.c
+++ b/init/main.c
@@ -582,7 +582,7 @@ static void __init do_initcalls(void)
result = (*call)();
- if (result && (result != -ENODEV || initcall_debug)) {
+ if (result && result != -ENODEV && initcall_debug) {
sprintf(msgbuf, "error code %d", result);
msg = msgbuf;
}
diff --git a/ipc/msg.c b/ipc/msg.c
index 48a7f17a723..7d1340ccb16 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -13,6 +13,9 @@
* mostly rewritten, threaded and wake-one semantics added
* MSGMAX limit removed, sysctl's added
* (c) 1999 Manfred Spraul <manfred@colorfullife.com>
+ *
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/capability.h>
@@ -447,6 +450,11 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
if (msg_checkid(msq,msqid))
goto out_unlock_up;
ipcp = &msq->q_perm;
+
+ err = audit_ipc_obj(ipcp);
+ if (err)
+ goto out_unlock_up;
+
err = -EPERM;
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
@@ -460,7 +468,8 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
switch (cmd) {
case IPC_SET:
{
- if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
+ if (err)
goto out_unlock_up;
err = -EPERM;
diff --git a/ipc/sem.c b/ipc/sem.c
index 642659cd596..7919f8ece6b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -61,6 +61,9 @@
* (c) 2001 Red Hat Inc <alan@redhat.com>
* Lockless wakeup
* (c) 2003 Manfred Spraul <manfred@colorfullife.com>
+ *
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/config.h>
@@ -820,6 +823,11 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
goto out_unlock;
}
ipcp = &sma->sem_perm;
+
+ err = audit_ipc_obj(ipcp);
+ if (err)
+ goto out_unlock;
+
if (current->euid != ipcp->cuid &&
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
err=-EPERM;
@@ -836,7 +844,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
err = 0;
break;
case IPC_SET:
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
+ err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
+ if (err)
goto out_unlock;
ipcp->uid = setbuf.uid;
ipcp->gid = setbuf.gid;
diff --git a/ipc/shm.c b/ipc/shm.c
index 1c2faf62bc7..80989685190 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -13,6 +13,8 @@
* Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com>
* Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com>
*
+ * support for audit of ipc object properties and permission changes
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/config.h>
@@ -542,6 +544,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
if(err)
goto out_unlock;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock;
+
if (!capable(CAP_IPC_LOCK)) {
err = -EPERM;
if (current->euid != shp->shm_perm.uid &&
@@ -594,6 +600,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
if(err)
goto out_unlock_up;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
+
if (current->euid != shp->shm_perm.uid &&
current->euid != shp->shm_perm.cuid &&
!capable(CAP_SYS_ADMIN)) {
@@ -627,12 +637,15 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
err=-EINVAL;
if(shp==NULL)
goto out_up;
- if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid,
- setbuf.mode, &(shp->shm_perm))))
- goto out_unlock_up;
err = shm_checkid(shp,shmid);
if(err)
goto out_unlock_up;
+ err = audit_ipc_obj(&(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
+ err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, &(shp->shm_perm));
+ if (err)
+ goto out_unlock_up;
err=-EPERM;
if (current->euid != shp->shm_perm.uid &&
current->euid != shp->shm_perm.cuid &&
diff --git a/ipc/util.c b/ipc/util.c
index b3dcfad3b4f..8193299f45f 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -10,6 +10,8 @@
* Manfred Spraul <manfred@colorfullife.com>
* Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
* Mingming Cao <cmm@us.ibm.com>
+ * Mar 2006 - support for audit of ipc object properties
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/config.h>
@@ -27,6 +29,7 @@
#include <linux/workqueue.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
+#include <linux/audit.h>
#include <asm/unistd.h>
@@ -464,8 +467,10 @@ void ipc_rcu_putref(void *ptr)
int ipcperms (struct kern_ipc_perm *ipcp, short flag)
{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
- int requested_mode, granted_mode;
+ int requested_mode, granted_mode, err;
+ if (unlikely((err = audit_ipc_obj(ipcp))))
+ return err;
requested_mode = (flag >> 6) | (flag >> 3) | flag;
granted_mode = ipcp->mode;
if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
diff --git a/kernel/audit.c b/kernel/audit.c
index c8ccbd09048..df57b493e1c 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -55,6 +55,9 @@
#include <net/netlink.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
+#include <linux/selinux.h>
+
+#include "audit.h"
/* No auditing will take place until audit_initialized != 0.
* (Initialization happens after skb_init is called.) */
@@ -227,49 +230,103 @@ void audit_log_lost(const char *message)
}
}
-static int audit_set_rate_limit(int limit, uid_t loginuid)
+static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_rate_limit;
- audit_rate_limit = limit;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ int old = audit_rate_limit;
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_rate_limit=%d old=%d by auid=%u subj=%s",
+ limit, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_rate_limit=%d old=%d by auid=%u",
- audit_rate_limit, old, loginuid);
+ limit, old, loginuid);
+ audit_rate_limit = limit;
return old;
}
-static int audit_set_backlog_limit(int limit, uid_t loginuid)
+static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_backlog_limit;
- audit_backlog_limit = limit;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ int old = audit_backlog_limit;
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_backlog_limit=%d old=%d by auid=%u subj=%s",
+ limit, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_backlog_limit=%d old=%d by auid=%u",
- audit_backlog_limit, old, loginuid);
+ limit, old, loginuid);
+ audit_backlog_limit = limit;
return old;
}
-static int audit_set_enabled(int state, uid_t loginuid)
+static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
{
- int old = audit_enabled;
+ int old = audit_enabled;
+
if (state != 0 && state != 1)
return -EINVAL;
- audit_enabled = state;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_enabled=%d old=%d by auid=%u subj=%s",
+ state, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_enabled=%d old=%d by auid=%u",
- audit_enabled, old, loginuid);
+ state, old, loginuid);
+ audit_enabled = state;
return old;
}
-static int audit_set_failure(int state, uid_t loginuid)
+static int audit_set_failure(int state, uid_t loginuid, u32 sid)
{
- int old = audit_failure;
+ int old = audit_failure;
+
if (state != AUDIT_FAIL_SILENT
&& state != AUDIT_FAIL_PRINTK
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
- audit_failure = state;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_failure=%d old=%d by auid=%u subj=%s",
+ state, old, loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_failure=%d old=%d by auid=%u",
- audit_failure, old, loginuid);
+ state, old, loginuid);
+ audit_failure = state;
return old;
}
@@ -387,7 +444,7 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
- u32 uid, pid, seq;
+ u32 uid, pid, seq, sid;
void *data;
struct audit_status *status_get, status_set;
int err;
@@ -413,6 +470,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
pid = NETLINK_CREDS(skb)->pid;
uid = NETLINK_CREDS(skb)->uid;
loginuid = NETLINK_CB(skb).loginuid;
+ sid = NETLINK_CB(skb).sid;
seq = nlh->nlmsg_seq;
data = NLMSG_DATA(nlh);
@@ -433,25 +491,43 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
status_get = (struct audit_status *)data;
if (status_get->mask & AUDIT_STATUS_ENABLED) {
- err = audit_set_enabled(status_get->enabled, loginuid);
+ err = audit_set_enabled(status_get->enabled,
+ loginuid, sid);
if (err < 0) return err;
}
if (status_get->mask & AUDIT_STATUS_FAILURE) {
- err = audit_set_failure(status_get->failure, loginuid);
+ err = audit_set_failure(status_get->failure,
+ loginuid, sid);
if (err < 0) return err;
}
if (status_get->mask & AUDIT_STATUS_PID) {
int old = audit_pid;
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ int rc;
+ if ((rc = selinux_ctxid_to_string(
+ sid, &ctx, &len)))
+ return rc;
+ else
+ audit_log(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE,
+ "audit_pid=%d old=%d by auid=%u subj=%s",
+ status_get->pid, old,
+ loginuid, ctx);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_pid=%d old=%d by auid=%u",
+ status_get->pid, old, loginuid);
audit_pid = status_get->pid;
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_pid=%d old=%d by auid=%u",
- audit_pid, old, loginuid);
}
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
- audit_set_rate_limit(status_get->rate_limit, loginuid);
+ audit_set_rate_limit(status_get->rate_limit,
+ loginuid, sid);
if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
audit_set_backlog_limit(status_get->backlog_limit,
- loginuid);
+ loginuid, sid);
break;
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
@@ -465,8 +541,23 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
if (ab) {
audit_log_format(ab,
- "user pid=%d uid=%u auid=%u msg='%.1024s'",
- pid, uid, loginuid, (char *)data);
+ "user pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " msg='%.1024s'",
+ (char *)data);
audit_set_pid(ab, pid);
audit_log_end(ab);
}
@@ -480,7 +571,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
uid, seq, data, nlmsg_len(nlh),
- loginuid);
+ loginuid, sid);
break;
case AUDIT_ADD_RULE:
case AUDIT_DEL_RULE:
@@ -490,7 +581,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_LIST_RULES:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
uid, seq, data, nlmsg_len(nlh),
- loginuid);
+ loginuid, sid);
break;
case AUDIT_SIGNAL_INFO:
sig_data.uid = audit_sig_uid;
@@ -564,6 +655,11 @@ static int __init audit_init(void)
skb_queue_head_init(&audit_skb_queue);
audit_initialized = 1;
audit_enabled = audit_default;
+
+ /* Register the callback with selinux. This callback will be invoked
+ * when a new policy is loaded. */
+ selinux_audit_set_callback(&selinux_audit_rule_update);
+
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
return 0;
}
diff --git a/kernel/audit.h b/kernel/audit.h
index bc5392076e2..6f733920fd3 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -54,9 +54,11 @@ enum audit_state {
/* Rule lists */
struct audit_field {
- u32 type;
- u32 val;
- u32 op;
+ u32 type;
+ u32 val;
+ u32 op;
+ char *se_str;
+ struct selinux_audit_rule *se_rule;
};
struct audit_krule {
@@ -86,3 +88,5 @@ extern void audit_send_reply(int pid, int seq, int type,
extern void audit_log_lost(const char *message);
extern void audit_panic(const char *message);
extern struct mutex audit_netlink_mutex;
+
+extern int selinux_audit_rule_update(void);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index d3a8539f3a8..7c134906d68 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -23,6 +23,7 @@
#include <linux/audit.h>
#include <linux/kthread.h>
#include <linux/netlink.h>
+#include <linux/selinux.h>
#include "audit.h"
/* There are three lists of rules -- one to search at task creation
@@ -42,6 +43,13 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
static inline void audit_free_rule(struct audit_entry *e)
{
+ int i;
+ if (e->rule.fields)
+ for (i = 0; i < e->rule.field_count; i++) {
+ struct audit_field *f = &e->rule.fields[i];
+ kfree(f->se_str);
+ selinux_audit_rule_free(f->se_rule);
+ }
kfree(e->rule.fields);
kfree(e);
}
@@ -52,9 +60,29 @@ static inline void audit_free_rule_rcu(struct rcu_head *head)
audit_free_rule(e);
}
+/* Initialize an audit filterlist entry. */
+static inline struct audit_entry *audit_init_entry(u32 field_count)
+{
+ struct audit_entry *entry;
+ struct audit_field *fields;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (unlikely(!entry))
+ return NULL;
+
+ fields = kzalloc(sizeof(*fields) * field_count, GFP_KERNEL);
+ if (unlikely(!fields)) {
+ kfree(entry);
+ return NULL;
+ }
+ entry->rule.fields = fields;
+
+ return entry;
+}
+
/* Unpack a filter field's string representation from user-space
* buffer. */
-static __attribute__((unused)) char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
+static char *audit_unpack_string(void **bufp, size_t *remain, size_t len)
{
char *str;
@@ -84,7 +112,6 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
{
unsigned listnr;
struct audit_entry *entry;
- struct audit_field *fields;
int i, err;
err = -EINVAL;
@@ -108,23 +135,14 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
goto exit_err;
err = -ENOMEM;
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if (unlikely(!entry))
- goto exit_err;
- fields = kmalloc(sizeof(*fields) * rule->field_count, GFP_KERNEL);
- if (unlikely(!fields)) {
- kfree(entry);
+ entry = audit_init_entry(rule->field_count);
+ if (!entry)
goto exit_err;
- }
-
- memset(&entry->rule, 0, sizeof(struct audit_krule));
- memset(fields, 0, sizeof(struct audit_field));
entry->rule.flags = rule->flags & AUDIT_FILTER_PREPEND;
entry->rule.listnr = listnr;
entry->rule.action = rule->action;
entry->rule.field_count = rule->field_count;
- entry->rule.fields = fields;
for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
entry->rule.mask[i] = rule->mask[i];
@@ -150,15 +168,20 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
for (i = 0; i < rule->field_count; i++) {
struct audit_field *f = &entry->rule.fields[i];
- if (rule->fields[i] & AUDIT_UNUSED_BITS) {
- err = -EINVAL;
- goto exit_free;
- }
-
f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS);
f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
f->val = rule->values[i];
+ if (f->type & AUDIT_UNUSED_BITS ||
+ f->type == AUDIT_SE_USER ||
+ f->type == AUDIT_SE_ROLE ||
+ f->type == AUDIT_SE_TYPE ||
+ f->type == AUDIT_SE_SEN ||
+ f->type == AUDIT_SE_CLR) {
+ err = -EINVAL;
+ goto exit_free;
+ }
+
entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
/* Support for legacy operators where
@@ -188,8 +211,9 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
int err = 0;
struct audit_entry *entry;
void *bufp;
- /* size_t remain = datasz - sizeof(struct audit_rule_data); */
+ size_t remain = datasz - sizeof(struct audit_rule_data);
int i;
+ char *str;
entry = audit_to_entry_common((struct audit_rule *)data);
if (IS_ERR(entry))
@@ -207,10 +231,35 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
f->op = data->fieldflags[i] & AUDIT_OPERATORS;
f->type = data->fields[i];
+ f->val = data->values[i];
+ f->se_str = NULL;
+ f->se_rule = NULL;
switch(f->type) {
- /* call type-specific conversion routines here */
- default:
- f->val = data->values[i];
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ str = audit_unpack_string(&bufp, &remain, f->val);
+ if (IS_ERR(str))
+ goto exit_free;
+ entry->rule.buflen += f->val;
+
+ err = selinux_audit_rule_init(f->type, f->op, str,
+ &f->se_rule);
+ /* Keep currently invalid fields around in case they
+ * become valid after a policy reload. */
+ if (err == -EINVAL) {
+ printk(KERN_WARNING "audit rule for selinux "
+ "\'%s\' is invalid\n", str);
+ err = 0;
+ }
+ if (err) {
+ kfree(str);
+ goto exit_free;
+ } else
+ f->se_str = str;
+ break;
}
}
@@ -286,7 +335,14 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
data->fields[i] = f->type;
data->fieldflags[i] = f->op;
switch(f->type) {
- /* call type-specific conversion routines here */
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ data->buflen += data->values[i] =
+ audit_pack_string(&bufp, f->se_str);
+ break;
default:
data->values[i] = f->val;
}
@@ -314,7 +370,14 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
return 1;
switch(a->fields[i].type) {
- /* call type-specific comparison routines here */
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
+ return 1;
+ break;
default:
if (a->fields[i].val != b->fields[i].val)
return 1;
@@ -328,6 +391,81 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
return 0;
}
+/* Duplicate selinux field information. The se_rule is opaque, so must be
+ * re-initialized. */
+static inline int audit_dupe_selinux_field(struct audit_field *df,
+ struct audit_field *sf)
+{
+ int ret = 0;
+ char *se_str;
+
+ /* our own copy of se_str */
+ se_str = kstrdup(sf->se_str, GFP_KERNEL);
+ if (unlikely(IS_ERR(se_str)))
+ return -ENOMEM;
+ df->se_str = se_str;
+
+ /* our own (refreshed) copy of se_rule */
+ ret = selinux_audit_rule_init(df->type, df->op, df->se_str,
+ &df->se_rule);
+ /* Keep currently invalid fields around in case they
+ * become valid after a policy reload. */
+ if (ret == -EINVAL) {
+ printk(KERN_WARNING "audit rule for selinux \'%s\' is "
+ "invalid\n", df->se_str);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/* Duplicate an audit rule. This will be a deep copy with the exception
+ * of the watch - that pointer is carried over. The selinux specific fields
+ * will be updated in the copy. The point is to be able to replace the old
+ * rule with the new rule in the filterlist, then free the old rule. */
+static struct audit_entry *audit_dupe_rule(struct audit_krule *old)
+{
+ u32 fcount = old->field_count;
+ struct audit_entry *entry;
+ struct audit_krule *new;
+ int i, err = 0;
+
+ entry = audit_init_entry(fcount);
+ if (unlikely(!entry))
+ return ERR_PTR(-ENOMEM);
+
+ new = &entry->rule;
+ new->vers_ops = old->vers_ops;
+ new->flags = old->flags;
+ new->listnr = old->listnr;
+ new->action = old->action;
+ for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+ new->mask[i] = old->mask[i];
+ new->buflen = old->buflen;
+ new->field_count = old->field_count;
+ memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
+
+ /* deep copy this information, updating the se_rule fields, because
+ * the originals will all be freed when the old rule is freed. */
+ for (i = 0; i < fcount; i++) {
+ switch (new->fields[i].type) {
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ err = audit_dupe_selinux_field(&new->fields[i],
+ &old->fields[i]);
+ }
+ if (err) {
+ audit_free_rule(entry);
+ return ERR_PTR(err);
+ }
+ }
+
+ return entry;
+}
+
/* Add rule to given filterlist if not a duplicate. Protected by
* audit_netlink_mutex. */
static inline int audit_add_rule(struct audit_entry *entry,
@@ -448,9 +586,10 @@ static int audit_list_rules(void *_dest)
* @data: payload data
* @datasz: size of payload data
* @loginuid: loginuid of sender
+ * @sid: SE Linux Security ID of sender
*/
int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
- size_t datasz, uid_t loginuid)
+ size_t datasz, uid_t loginuid, u32 sid)
{
struct task_struct *tsk;
int *dest;
@@ -493,9 +632,23 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_add_rule(entry,
&audit_filter_list[entry->rule.listnr]);
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u add rule to list=%d res=%d\n",
- loginuid, entry->rule.listnr, !err);
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(sid, &ctx, &len)) {
+ /* Maybe call audit_panic? */
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u ssid=%u add rule to list=%d res=%d",
+ loginuid, sid, entry->rule.listnr, !err);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u subj=%s add rule to list=%d res=%d",
+ loginuid, ctx, entry->rule.listnr, !err);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u add rule to list=%d res=%d",
+ loginuid, entry->rule.listnr, !err);
if (err)
audit_free_rule(entry);
@@ -511,9 +664,24 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_del_rule(entry,
&audit_filter_list[entry->rule.listnr]);
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "auid=%u remove rule from list=%d res=%d\n",
- loginuid, entry->rule.listnr, !err);
+
+ if (sid) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(sid, &ctx, &len)) {
+ /* Maybe call audit_panic? */
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u ssid=%u remove rule from list=%d res=%d",
+ loginuid, sid, entry->rule.listnr, !err);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u subj=%s remove rule from list=%d res=%d",
+ loginuid, ctx, entry->rule.listnr, !err);
+ kfree(ctx);
+ } else
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "auid=%u remove rule from list=%d res=%d",
+ loginuid, entry->rule.listnr, !err);
audit_free_rule(entry);
break;
@@ -628,3 +796,62 @@ unlock_and_return:
rcu_read_unlock();
return result;
}
+
+/* Check to see if the rule contains any selinux fields. Returns 1 if there
+ are selinux fields specified in the rule, 0 otherwise. */
+static inline int audit_rule_has_selinux(struct audit_krule *rule)
+{
+ int i;
+
+ for (i = 0; i < rule->field_count; i++) {
+ struct audit_field *f = &rule->fields[i];
+ switch (f->type) {
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* This function will re-initialize the se_rule field of all applicable rules.
+ * It will traverse the filter lists serarching for rules that contain selinux
+ * specific filter fields. When such a rule is found, it is copied, the
+ * selinux field is re-initialized, and the old rule is replaced with the
+ * updated rule. */
+int selinux_audit_rule_update(void)
+{
+ struct audit_entry *entry, *n, *nentry;
+ int i, err = 0;
+
+ /* audit_netlink_mutex synchronizes the writers */
+ mutex_lock(&audit_netlink_mutex);
+
+ for (i = 0; i < AUDIT_NR_FILTERS; i++) {
+ list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
+ if (!audit_rule_has_selinux(&entry->rule))
+ continue;
+
+ nentry = audit_dupe_rule(&entry->rule);
+ if (unlikely(IS_ERR(nentry))) {
+ /* save the first error encountered for the
+ * return value */
+ if (!err)
+ err = PTR_ERR(nentry);
+ audit_panic("error updating selinux filters");
+ list_del_rcu(&entry->list);
+ } else {
+ list_replace_rcu(&entry->list, &nentry->list);
+ }
+ call_rcu(&entry->rcu, audit_free_rule_rcu);
+ }
+ }
+
+ mutex_unlock(&audit_netlink_mutex);
+
+ return err;
+}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 7f160df21a2..1c03a4ed1b2 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -58,6 +58,7 @@
#include <linux/security.h>
#include <linux/list.h>
#include <linux/tty.h>
+#include <linux/selinux.h>
#include "audit.h"
@@ -89,7 +90,7 @@ struct audit_names {
uid_t uid;
gid_t gid;
dev_t rdev;
- char *ctx;
+ u32 osid;
};
struct audit_aux_data {
@@ -106,7 +107,7 @@ struct audit_aux_data_ipcctl {
uid_t uid;
gid_t gid;
mode_t mode;
- char *ctx;
+ u32 osid;
};
struct audit_aux_data_socketcall {
@@ -167,7 +168,8 @@ static int audit_filter_rules(struct task_struct *tsk,
struct audit_context *ctx,
enum audit_state *state)
{
- int i, j;
+ int i, j, need_sid = 1;
+ u32 sid;
for (i = 0; i < rule->field_count; i++) {
struct audit_field *f = &rule->fields[i];
@@ -257,6 +259,27 @@ static int audit_filter_rules(struct task_struct *tsk,
if (ctx)
result = audit_comparator(ctx->loginuid, f->op, f->val);
break;
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ /* NOTE: this may return negative values indicating
+ a temporary error. We simply treat this as a
+ match for now to avoid losing information that
+ may be wanted. An error message will also be
+ logged upon error */
+ if (f->se_rule) {
+ if (need_sid) {
+ selinux_task_ctxid(tsk, &sid);
+ need_sid = 0;
+ }
+ result = selinux_audit_rule_match(sid, f->type,
+ f->op,
+ f->se_rule,
+ ctx);
+ }
+ break;
case AUDIT_ARG0:
case AUDIT_ARG1:
case AUDIT_ARG2:
@@ -329,7 +352,6 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk,
return AUDIT_BUILD_CONTEXT;
}
-/* This should be called with task_lock() held. */
static inline struct audit_context *audit_get_context(struct task_struct *tsk,
int return_valid,
int return_code)
@@ -391,9 +413,6 @@ static inline void audit_free_names(struct audit_context *context)
#endif
for (i = 0; i < context->name_count; i++) {
- char *p = context->names[i].ctx;
- context->names[i].ctx = NULL;
- kfree(p);
if (context->names[i].name)
__putname(context->names[i].name);
}
@@ -416,11 +435,6 @@ static inline void audit_free_aux(struct audit_context *context)
dput(axi->dentry);
mntput(axi->mnt);
}
- if ( aux->type == AUDIT_IPC ) {
- struct audit_aux_data_ipcctl *axi = (void *)aux;
- if (axi->ctx)
- kfree(axi->ctx);
- }
context->aux = aux->next;
kfree(aux);
@@ -506,7 +520,7 @@ static inline void audit_free_context(struct audit_context *context)
printk(KERN_ERR "audit: freed %d contexts\n", count);
}
-static void audit_log_task_context(struct audit_buffer *ab, gfp_t gfp_mask)
+static void audit_log_task_context(struct audit_buffer *ab)
{
char *ctx = NULL;
ssize_t len = 0;
@@ -518,7 +532,7 @@ static void audit_log_task_context(struct audit_buffer *ab, gfp_t gfp_mask)
return;
}
- ctx = kmalloc(len, gfp_mask);
+ ctx = kmalloc(len, GFP_KERNEL);
if (!ctx)
goto error_path;
@@ -536,47 +550,46 @@ error_path:
return;
}
-static void audit_log_task_info(struct audit_buffer *ab, gfp_t gfp_mask)
+static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
{
- char name[sizeof(current->comm)];
- struct mm_struct *mm = current->mm;
+ char name[sizeof(tsk->comm)];
+ struct mm_struct *mm = tsk->mm;
struct vm_area_struct *vma;
- get_task_comm(name, current);
+ /* tsk == current */
+
+ get_task_comm(name, tsk);
audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, name);
- if (!mm)
- return;
-
- /*
- * this is brittle; all callers that pass GFP_ATOMIC will have
- * NULL current->mm and we won't get here.
- */
- down_read(&mm->mmap_sem);
- vma = mm->mmap;
- while (vma) {
- if ((vma->vm_flags & VM_EXECUTABLE) &&
- vma->vm_file) {
- audit_log_d_path(ab, "exe=",
- vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
- break;
+ if (mm) {
+ down_read(&mm->mmap_sem);
+ vma = mm->mmap;
+ while (vma) {
+ if ((vma->vm_flags & VM_EXECUTABLE) &&
+ vma->vm_file) {
+ audit_log_d_path(ab, "exe=",
+ vma->vm_file->f_dentry,
+ vma->vm_file->f_vfsmnt);
+ break;
+ }
+ vma = vma->vm_next;
}
- vma = vma->vm_next;
+ up_read(&mm->mmap_sem);
}
- up_read(&mm->mmap_sem);
- audit_log_task_context(ab, gfp_mask);
+ audit_log_task_context(ab);
}
-static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
+static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{
- int i;
+ int i, call_panic = 0;
struct audit_buffer *ab;
struct audit_aux_data *aux;
const char *tty;
- ab = audit_log_start(context, gfp_mask, AUDIT_SYSCALL);
+ /* tsk == current */
+
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "arch=%x syscall=%d",
@@ -587,8 +600,8 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
audit_log_format(ab, " success=%s exit=%ld",
(context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
context->return_code);
- if (current->signal->tty && current->signal->tty->name)
- tty = current->signal->tty->name;
+ if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
+ tty = tsk->signal->tty->name;
else
tty = "(none)";
audit_log_format(ab,
@@ -607,12 +620,12 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
context->gid,
context->euid, context->suid, context->fsuid,
context->egid, context->sgid, context->fsgid, tty);
- audit_log_task_info(ab, gfp_mask);
+ audit_log_task_info(ab, tsk);
audit_log_end(ab);
for (aux = context->aux; aux; aux = aux->next) {
- ab = audit_log_start(context, gfp_mask, aux->type);
+ ab = audit_log_start(context, GFP_KERNEL, aux->type);
if (!ab)
continue; /* audit_panic has been called */
@@ -620,8 +633,39 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
case AUDIT_IPC: {
struct audit_aux_data_ipcctl *axi = (void *)aux;
audit_log_format(ab,
- " qbytes=%lx iuid=%u igid=%u mode=%x obj=%s",
- axi->qbytes, axi->uid, axi->gid, axi->mode, axi->ctx);
+ " qbytes=%lx iuid=%u igid=%u mode=%x",
+ axi->qbytes, axi->uid, axi->gid, axi->mode);
+ if (axi->osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ axi->osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ axi->osid);
+ call_panic = 1;
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
+ }
+ break; }
+
+ case AUDIT_IPC_SET_PERM: {
+ struct audit_aux_data_ipcctl *axi = (void *)aux;
+ audit_log_format(ab,
+ " new qbytes=%lx new iuid=%u new igid=%u new mode=%x",
+ axi->qbytes, axi->uid, axi->gid, axi->mode);
+ if (axi->osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ axi->osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ axi->osid);
+ call_panic = 1;
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
+ }
break; }
case AUDIT_SOCKETCALL: {
@@ -649,7 +693,7 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
}
if (context->pwd && context->pwdmnt) {
- ab = audit_log_start(context, gfp_mask, AUDIT_CWD);
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
if (ab) {
audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
audit_log_end(ab);
@@ -659,7 +703,7 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
unsigned long ino = context->names[i].ino;
unsigned long pino = context->names[i].pino;
- ab = audit_log_start(context, gfp_mask, AUDIT_PATH);
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
if (!ab)
continue; /* audit_panic has been called */
@@ -685,32 +729,35 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
context->names[i].gid,
MAJOR(context->names[i].rdev),
MINOR(context->names[i].rdev));
- if (context->names[i].ctx) {
- audit_log_format(ab, " obj=%s",
- context->names[i].ctx);
+ if (context->names[i].osid != 0) {
+ char *ctx = NULL;
+ u32 len;
+ if (selinux_ctxid_to_string(
+ context->names[i].osid, &ctx, &len)) {
+ audit_log_format(ab, " osid=%u",
+ context->names[i].osid);
+ call_panic = 2;
+ } else
+ audit_log_format(ab, " obj=%s", ctx);
+ kfree(ctx);
}
audit_log_end(ab);
}
+ if (call_panic)
+ audit_panic("error converting sid to string");
}
/**
* audit_free - free a per-task audit context
* @tsk: task whose audit context block to free
*
- * Called from copy_process and __put_task_struct.
+ * Called from copy_process and do_exit
*/
void audit_free(struct task_struct *tsk)
{
struct audit_context *context;
- /*
- * No need to lock the task - when we execute audit_free()
- * then the task has no external references anymore, and
- * we are tearing it down. (The locking also confuses
- * DEBUG_LOCKDEP - this freeing may occur in softirq
- * contexts as well, via RCU.)
- */
context = audit_get_context(tsk, 0, 0);
if (likely(!context))
return;
@@ -719,8 +766,9 @@ void audit_free(struct task_struct *tsk)
* function (e.g., exit_group), then free context block.
* We use GFP_ATOMIC here because we might be doing this
* in the context of the idle thread */
+ /* that can happen only if we are called from do_exit() */
if (context->in_syscall && context->auditable)
- audit_log_exit(context, GFP_ATOMIC);
+ audit_log_exit(context, tsk);
audit_free_context(context);
}
@@ -743,10 +791,11 @@ void audit_free(struct task_struct *tsk)
* will only be written if another part of the kernel requests that it
* be written).
*/
-void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
+void audit_syscall_entry(int arch, int major,
unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4)
{
+ struct task_struct *tsk = current;
struct audit_context *context = tsk->audit_context;
enum audit_state state;
@@ -824,22 +873,18 @@ void audit_syscall_entry(struct task_struct *tsk, int arch, int major,
* message), then write out the syscall information. In call cases,
* free the names stored from getname().
*/
-void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
+void audit_syscall_exit(int valid, long return_code)
{
+ struct task_struct *tsk = current;
struct audit_context *context;
- get_task_struct(tsk);
- task_lock(tsk);
context = audit_get_context(tsk, valid, return_code);
- task_unlock(tsk);
- /* Not having a context here is ok, since the parent may have
- * called __put_task_struct. */
if (likely(!context))
- goto out;
+ return;
if (context->in_syscall && context->auditable)
- audit_log_exit(context, GFP_KERNEL);
+ audit_log_exit(context, tsk);
context->in_syscall = 0;
context->auditable = 0;
@@ -854,8 +899,6 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
audit_free_aux(context);
tsk->audit_context = context;
}
- out:
- put_task_struct(tsk);
}
/**
@@ -936,40 +979,11 @@ void audit_putname(const char *name)
#endif
}
-void audit_inode_context(int idx, const struct inode *inode)
+static void audit_inode_context(int idx, const struct inode *inode)
{
struct audit_context *context = current->audit_context;
- const char *suffix = security_inode_xattr_getsuffix();
- char *ctx = NULL;
- int len = 0;
-
- if (!suffix)
- goto ret;
-
- len = security_inode_getsecurity(inode, suffix, NULL, 0, 0);
- if (len == -EOPNOTSUPP)
- goto ret;
- if (len < 0)
- goto error_path;
-
- ctx = kmalloc(len, GFP_KERNEL);
- if (!ctx)
- goto error_path;
- len = security_inode_getsecurity(inode, suffix, ctx, len, 0);
- if (len < 0)
- goto error_path;
-
- kfree(context->names[idx].ctx);
- context->names[idx].ctx = ctx;
- goto ret;
-
-error_path:
- if (ctx)
- kfree(ctx);
- audit_panic("error in audit_inode_context");
-ret:
- return;
+ selinux_get_inode_sid(inode, &context->names[idx].osid);
}
@@ -1155,40 +1169,37 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
return ctx ? ctx->loginuid : -1;
}
-static char *audit_ipc_context(struct kern_ipc_perm *ipcp)
+/**
+ * audit_ipc_obj - record audit data for ipc object
+ * @ipcp: ipc permissions
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
+ struct audit_aux_data_ipcctl *ax;
struct audit_context *context = current->audit_context;
- char *ctx = NULL;
- int len = 0;
if (likely(!context))
- return NULL;
-
- len = security_ipc_getsecurity(ipcp, NULL, 0);
- if (len == -EOPNOTSUPP)
- goto ret;
- if (len < 0)
- goto error_path;
-
- ctx = kmalloc(len, GFP_ATOMIC);
- if (!ctx)
- goto error_path;
+ return 0;
- len = security_ipc_getsecurity(ipcp, ctx, len);
- if (len < 0)
- goto error_path;
+ ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+ if (!ax)
+ return -ENOMEM;
- return ctx;
+ ax->uid = ipcp->uid;
+ ax->gid = ipcp->gid;
+ ax->mode = ipcp->mode;
+ selinux_get_ipc_sid(ipcp, &ax->osid);
-error_path:
- kfree(ctx);
- audit_panic("error in audit_ipc_context");
-ret:
- return NULL;
+ ax->d.type = AUDIT_IPC;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
}
/**
- * audit_ipc_perms - record audit data for ipc
+ * audit_ipc_set_perm - record audit data for new ipc permissions
* @qbytes: msgq bytes
* @uid: msgq user id
* @gid: msgq group id
@@ -1196,7 +1207,7 @@ ret:
*
* Returns 0 for success or NULL context or < 0 on error.
*/
-int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
+int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
{
struct audit_aux_data_ipcctl *ax;
struct audit_context *context = current->audit_context;
@@ -1212,9 +1223,9 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, str
ax->uid = uid;
ax->gid = gid;
ax->mode = mode;
- ax->ctx = audit_ipc_context(ipcp);
+ selinux_get_ipc_sid(ipcp, &ax->osid);
- ax->d.type = AUDIT_IPC;
+ ax->d.type = AUDIT_IPC_SET_PERM;
ax->d.next = context->aux;
context->aux = (void *)ax;
return 0;
diff --git a/kernel/exit.c b/kernel/exit.c
index f86434d7b3d..e95b9328221 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -35,6 +35,7 @@
#include <linux/futex.h>
#include <linux/compat.h>
#include <linux/pipe_fs_i.h>
+#include <linux/audit.h> /* for audit_free() */
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -910,6 +911,8 @@ fastcall NORET_TYPE void do_exit(long code)
if (unlikely(tsk->compat_robust_list))
compat_exit_robust_list(tsk);
#endif
+ if (unlikely(tsk->audit_context))
+ audit_free(tsk);
exit_mm(tsk);
exit_sem(tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index d2fa57d480d..ac8100e3088 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -114,8 +114,6 @@ void __put_task_struct(struct task_struct *tsk)
WARN_ON(atomic_read(&tsk->usage));
WARN_ON(tsk == current);
- if (unlikely(tsk->audit_context))
- audit_free(tsk);
security_task_free(tsk);
free_uid(tsk->user);
put_group_info(tsk->group_info);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4e0f0ec003f..b0f8da80d7d 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -148,12 +148,16 @@ int ptrace_may_attach(struct task_struct *task)
int ptrace_attach(struct task_struct *task)
{
int retval;
- task_lock(task);
+
retval = -EPERM;
if (task->pid <= 1)
- goto bad;
+ goto out;
if (task->tgid == current->tgid)
- goto bad;
+ goto out;
+
+ write_lock_irq(&tasklist_lock);
+ task_lock(task);
+
/* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED)
goto bad;
@@ -166,17 +170,15 @@ int ptrace_attach(struct task_struct *task)
? PT_ATTACHED : 0);
if (capable(CAP_SYS_PTRACE))
task->ptrace |= PT_PTRACE_CAP;
- task_unlock(task);
- write_lock_irq(&tasklist_lock);
__ptrace_link(task, current);
- write_unlock_irq(&tasklist_lock);
force_sig_specific(SIGSTOP, task);
- return 0;
bad:
+ write_unlock_irq(&tasklist_lock);
task_unlock(task);
+out:
return retval;
}
@@ -417,21 +419,22 @@ int ptrace_request(struct task_struct *child, long request,
*/
int ptrace_traceme(void)
{
- int ret;
+ int ret = -EPERM;
/*
* Are we already being traced?
*/
- if (current->ptrace & PT_PTRACED)
- return -EPERM;
- ret = security_ptrace(current->parent, current);
- if (ret)
- return -EPERM;
- /*
- * Set the ptrace bit in the process ptrace flags.
- */
- current->ptrace |= PT_PTRACED;
- return 0;
+ task_lock(current);
+ if (!(current->ptrace & PT_PTRACED)) {
+ ret = security_ptrace(current->parent, current);
+ /*
+ * Set the ptrace bit in the process ptrace flags.
+ */
+ if (!ret)
+ current->ptrace |= PT_PTRACED;
+ }
+ task_unlock(current);
+ return ret;
}
/**
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 1fe76d963ac..1ae2b2cc3a5 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -69,12 +69,16 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn,
for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) {
err = __add_section(zone, phys_start_pfn + i);
- if (err)
+ /* We want to keep adding the rest of the
+ * sections if the first ones already exist
+ */
+ if (err && (err != -EEXIST))
break;
}
return err;
}
+EXPORT_SYMBOL_GPL(__add_pages);
static void grow_zone_span(struct zone *zone,
unsigned long start_pfn, unsigned long end_pfn)
diff --git a/mm/migrate.c b/mm/migrate.c
index d444229f259..1c25040693d 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -439,6 +439,17 @@ redo:
goto unlock_both;
}
+ /* Make sure the dirty bit is up to date */
+ if (try_to_unmap(page, 1) == SWAP_FAIL) {
+ rc = -EPERM;
+ goto unlock_both;
+ }
+
+ if (page_mapcount(page)) {
+ rc = -EAGAIN;
+ goto unlock_both;
+ }
+
/*
* Default handling if a filesystem does not provide
* a migration function. We can only migrate clean
diff --git a/mm/sparse.c b/mm/sparse.c
index 0a51f36ba3a..d7c32de99ee 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -32,7 +32,10 @@ static struct mem_section *sparse_index_alloc(int nid)
unsigned long array_size = SECTIONS_PER_ROOT *
sizeof(struct mem_section);
- section = alloc_bootmem_node(NODE_DATA(nid), array_size);
+ if (system_state == SYSTEM_RUNNING)
+ section = kmalloc_node(array_size, GFP_KERNEL, nid);
+ else
+ section = alloc_bootmem_node(NODE_DATA(nid), array_size);
if (section)
memset(section, 0, array_size);
@@ -281,9 +284,9 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
ret = sparse_init_one_section(ms, section_nr, memmap);
- if (ret <= 0)
- __kfree_section_memmap(memmap, nr_pages);
out:
pgdat_resize_unlock(pgdat, &flags);
+ if (ret <= 0)
+ __kfree_section_memmap(memmap, nr_pages);
return ret;
}
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index dbf9b47681f..a2e0dd047e9 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -228,6 +228,8 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr,
return NULL;
}
+EXPORT_SYMBOL(ax25_find_cb);
+
void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
{
ax25_cb *s;
@@ -424,6 +426,26 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
return 0;
}
+static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev)
+{
+ ax25->rtt = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2;
+ ax25->t1 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]);
+ ax25->t2 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T2]);
+ ax25->t3 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T3]);
+ ax25->n2 = ax25_dev->values[AX25_VALUES_N2];
+ ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];
+ ax25->idle = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_IDLE]);
+ ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
+
+ if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
+ ax25->modulus = AX25_EMODULUS;
+ ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
+ } else {
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
+ }
+}
+
/*
* Fill in a created AX.25 created control block with the default
* values for a particular device.
@@ -433,39 +455,28 @@ void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)
ax25->ax25_dev = ax25_dev;
if (ax25->ax25_dev != NULL) {
- ax25->rtt = ax25_dev->values[AX25_VALUES_T1] / 2;
- ax25->t1 = ax25_dev->values[AX25_VALUES_T1];
- ax25->t2 = ax25_dev->values[AX25_VALUES_T2];
- ax25->t3 = ax25_dev->values[AX25_VALUES_T3];
- ax25->n2 = ax25_dev->values[AX25_VALUES_N2];
- ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN];
- ax25->idle = ax25_dev->values[AX25_VALUES_IDLE];
- ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
-
- if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW];
- } else {
- ax25->modulus = AX25_MODULUS;
- ax25->window = ax25_dev->values[AX25_VALUES_WINDOW];
- }
+ ax25_fillin_cb_from_dev(ax25, ax25_dev);
+ return;
+ }
+
+ /*
+ * No device, use kernel / AX.25 spec default values
+ */
+ ax25->rtt = msecs_to_jiffies(AX25_DEF_T1) / 2;
+ ax25->t1 = msecs_to_jiffies(AX25_DEF_T1);
+ ax25->t2 = msecs_to_jiffies(AX25_DEF_T2);
+ ax25->t3 = msecs_to_jiffies(AX25_DEF_T3);
+ ax25->n2 = AX25_DEF_N2;
+ ax25->paclen = AX25_DEF_PACLEN;
+ ax25->idle = msecs_to_jiffies(AX25_DEF_IDLE);
+ ax25->backoff = AX25_DEF_BACKOFF;
+
+ if (AX25_DEF_AXDEFMODE) {
+ ax25->modulus = AX25_EMODULUS;
+ ax25->window = AX25_DEF_EWINDOW;
} else {
- ax25->rtt = AX25_DEF_T1 / 2;
- ax25->t1 = AX25_DEF_T1;
- ax25->t2 = AX25_DEF_T2;
- ax25->t3 = AX25_DEF_T3;
- ax25->n2 = AX25_DEF_N2;
- ax25->paclen = AX25_DEF_PACLEN;
- ax25->idle = AX25_DEF_IDLE;
- ax25->backoff = AX25_DEF_BACKOFF;
-
- if (AX25_DEF_AXDEFMODE) {
- ax25->modulus = AX25_EMODULUS;
- ax25->window = AX25_DEF_EWINDOW;
- } else {
- ax25->modulus = AX25_MODULUS;
- ax25->window = AX25_DEF_WINDOW;
- }
+ ax25->modulus = AX25_MODULUS;
+ ax25->window = AX25_DEF_WINDOW;
}
}
@@ -1979,24 +1990,6 @@ static struct notifier_block ax25_dev_notifier = {
.notifier_call =ax25_device_event,
};
-EXPORT_SYMBOL(ax25_hard_header);
-EXPORT_SYMBOL(ax25_rebuild_header);
-EXPORT_SYMBOL(ax25_findbyuid);
-EXPORT_SYMBOL(ax25_find_cb);
-EXPORT_SYMBOL(ax25_linkfail_register);
-EXPORT_SYMBOL(ax25_linkfail_release);
-EXPORT_SYMBOL(ax25_listen_register);
-EXPORT_SYMBOL(ax25_listen_release);
-EXPORT_SYMBOL(ax25_protocol_register);
-EXPORT_SYMBOL(ax25_protocol_release);
-EXPORT_SYMBOL(ax25_send_frame);
-EXPORT_SYMBOL(ax25_uid_policy);
-EXPORT_SYMBOL(ax25cmp);
-EXPORT_SYMBOL(ax2asc);
-EXPORT_SYMBOL(asc2ax);
-EXPORT_SYMBOL(null_ax25_address);
-EXPORT_SYMBOL(ax25_display_timer);
-
static int __init ax25_init(void)
{
int rc = proto_register(&ax25_proto, 0);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 0164a155b8c..5f0896ad004 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -11,6 +11,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -33,6 +34,8 @@
*/
ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
+EXPORT_SYMBOL(null_ax25_address);
+
/*
* ax25 -> ascii conversion
*/
@@ -64,6 +67,8 @@ char *ax2asc(char *buf, ax25_address *a)
}
+EXPORT_SYMBOL(ax2asc);
+
/*
* ascii -> ax25 conversion
*/
@@ -97,6 +102,8 @@ void asc2ax(ax25_address *addr, char *callsign)
addr->ax25_call[6] &= 0x1E;
}
+EXPORT_SYMBOL(asc2ax);
+
/*
* Compare two ax.25 addresses
*/
@@ -116,6 +123,8 @@ int ax25cmp(ax25_address *a, ax25_address *b)
return 2; /* Partial match */
}
+EXPORT_SYMBOL(ax25cmp);
+
/*
* Compare two AX.25 digipeater paths.
*/
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 061083efc1d..5961459935e 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -61,7 +61,8 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
return;
del_timer(&ax25_dev->dama.slave_timer);
- ax25_dev->dama.slave_timeout = ax25_dev->values[AX25_VALUES_DS_TIMEOUT] / 10;
+ ax25_dev->dama.slave_timeout =
+ msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10;
ax25_ds_add_timer(ax25_dev);
}
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index d68aff10072..3bb152710b7 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -12,6 +12,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
@@ -74,6 +75,8 @@ int ax25_protocol_register(unsigned int pid,
return 1;
}
+EXPORT_SYMBOL(ax25_protocol_register);
+
void ax25_protocol_release(unsigned int pid)
{
struct protocol_struct *s, *protocol;
@@ -106,6 +109,8 @@ void ax25_protocol_release(unsigned int pid)
write_unlock(&protocol_list_lock);
}
+EXPORT_SYMBOL(ax25_protocol_release);
+
int ax25_linkfail_register(void (*func)(ax25_cb *, int))
{
struct linkfail_struct *linkfail;
@@ -123,6 +128,8 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int))
return 1;
}
+EXPORT_SYMBOL(ax25_linkfail_register);
+
void ax25_linkfail_release(void (*func)(ax25_cb *, int))
{
struct linkfail_struct *s, *linkfail;
@@ -155,6 +162,8 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
spin_unlock_bh(&linkfail_lock);
}
+EXPORT_SYMBOL(ax25_linkfail_release);
+
int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
{
struct listen_struct *listen;
@@ -176,6 +185,8 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
return 1;
}
+EXPORT_SYMBOL(ax25_listen_register);
+
void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
{
struct listen_struct *s, *listen;
@@ -208,6 +219,8 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
spin_unlock_bh(&listen_lock);
}
+EXPORT_SYMBOL(ax25_listen_release);
+
int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
{
int (*res)(struct sk_buff *, ax25_cb *) = NULL;
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index d643dac3ecc..a0b534f80f1 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -12,6 +12,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -221,3 +222,5 @@ int ax25_rebuild_header(struct sk_buff *skb)
#endif
+EXPORT_SYMBOL(ax25_hard_header);
+EXPORT_SYMBOL(ax25_rebuild_header);
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 5fc048dcd39..5d99852b239 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -14,6 +14,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -104,6 +105,8 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2
return ax25; /* We had to create it */
}
+EXPORT_SYMBOL(ax25_send_frame);
+
/*
* All outgoing AX.25 I frames pass via this routine. Therefore this is
* where the fragmentation of frames takes place. If fragment is set to
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index f04f8630fd2..5ac98250797 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -360,7 +360,7 @@ struct file_operations ax25_route_fops = {
/*
* Find AX.25 route
*
- * Only routes with a refernce rout of zero can be destroyed.
+ * Only routes with a reference count of zero can be destroyed.
*/
static ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
{
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c
index 7a6b50a1455..ec254057f21 100644
--- a/net/ax25/ax25_timer.c
+++ b/net/ax25/ax25_timer.c
@@ -18,6 +18,7 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -137,6 +138,8 @@ unsigned long ax25_display_timer(struct timer_list *timer)
return timer->expires - jiffies;
}
+EXPORT_SYMBOL(ax25_display_timer);
+
static void ax25_heartbeat_expiry(unsigned long param)
{
int proto = AX25_PROTO_STD_SIMPLEX;
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index b8b5854bce9..5e9a81e8b21 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -49,6 +49,8 @@ static DEFINE_RWLOCK(ax25_uid_lock);
int ax25_uid_policy = 0;
+EXPORT_SYMBOL(ax25_uid_policy);
+
ax25_uid_assoc *ax25_findbyuid(uid_t uid)
{
ax25_uid_assoc *ax25_uid, *res = NULL;
@@ -67,6 +69,8 @@ ax25_uid_assoc *ax25_findbyuid(uid_t uid)
return res;
}
+EXPORT_SYMBOL(ax25_findbyuid);
+
int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
{
ax25_uid_assoc *ax25_uid;
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index 894a22558d9..bdb64c36df1 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -18,14 +18,14 @@ static int min_backoff[1], max_backoff[] = {2};
static int min_conmode[1], max_conmode[] = {2};
static int min_window[] = {1}, max_window[] = {7};
static int min_ewindow[] = {1}, max_ewindow[] = {63};
-static int min_t1[] = {1}, max_t1[] = {30 * HZ};
-static int min_t2[] = {1}, max_t2[] = {20 * HZ};
-static int min_t3[1], max_t3[] = {3600 * HZ};
-static int min_idle[1], max_idle[] = {65535 * HZ};
+static int min_t1[] = {1}, max_t1[] = {30000};
+static int min_t2[] = {1}, max_t2[] = {20000};
+static int min_t3[1], max_t3[] = {3600000};
+static int min_idle[1], max_idle[] = {65535000};
static int min_n2[] = {1}, max_n2[] = {31};
static int min_paclen[] = {1}, max_paclen[] = {512};
static int min_proto[1], max_proto[] = { AX25_PROTO_MAX };
-static int min_ds_timeout[1], max_ds_timeout[] = {65535 * HZ};
+static int min_ds_timeout[1], max_ds_timeout[] = {65535000};
static struct ctl_table_header *ax25_table_header;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b0b7f55c1ed..bfa4d8c333f 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -66,6 +66,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
}
if (is_multicast_ether_addr(dest)) {
+ br->statistics.multicast++;
br_flood_forward(br, skb, !passedup);
if (!passedup)
br_pass_frame_up(br, skb);
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 1ff7328b0e1..2e0ee8355c4 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -848,6 +848,7 @@ static int dccp_close_state(struct sock *sk)
void dccp_close(struct sock *sk, long timeout)
{
struct sk_buff *skb;
+ int state;
lock_sock(sk);
@@ -882,6 +883,11 @@ void dccp_close(struct sock *sk, long timeout)
sk_stream_wait_close(sk, timeout);
adjudge_to_death:
+ state = sk->sk_state;
+ sock_hold(sk);
+ sock_orphan(sk);
+ atomic_inc(sk->sk_prot->orphan_count);
+
/*
* It is the last release_sock in its life. It will remove backlog.
*/
@@ -894,8 +900,9 @@ adjudge_to_death:
bh_lock_sock(sk);
BUG_TRAP(!sock_owned_by_user(sk));
- sock_hold(sk);
- sock_orphan(sk);
+ /* Have we already been destroyed by a softirq or backlog? */
+ if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED)
+ goto out;
/*
* The last release_sock may have processed the CLOSE or RESET
@@ -915,12 +922,12 @@ adjudge_to_death:
#endif
}
- atomic_inc(sk->sk_prot->orphan_count);
if (sk->sk_state == DCCP_CLOSED)
inet_csk_destroy_sock(sk);
/* Otherwise, socket is reprieved until protocol close. */
+out:
bh_unlock_sock(sk);
local_bh_enable();
sock_put(sk);
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 7c8692c26bf..66e230c3b32 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -493,7 +493,6 @@ struct elist_cb_state {
static void neigh_elist_cb(struct neighbour *neigh, void *_info)
{
struct elist_cb_state *s = _info;
- struct dn_dev *dn_db;
struct dn_neigh *dn;
if (neigh->dev != s->dev)
@@ -503,10 +502,6 @@ static void neigh_elist_cb(struct neighbour *neigh, void *_info)
if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
return;
- dn_db = (struct dn_dev *) s->dev->dn_ptr;
- if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
- return;
-
if (s->t == s->n)
s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
else
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index dc206f1f914..0a277453526 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1257,7 +1257,7 @@ out_unregister_udp_proto:
goto out;
}
-module_init(inet_init);
+fs_initcall(inet_init);
/* ------------------------------------------------------------------------ */
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index 2c2fb700d83..518f581d39e 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -162,6 +162,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct,
/* Validate TPKT length */
tpktlen = tpkt[2] * 256 + tpkt[3];
+ if (tpktlen < 4)
+ goto clear_out;
if (tpktlen > tcpdatalen) {
if (tcpdatalen == 4) { /* Separate TPKT header */
/* Netmeeting sends TPKT header and data separately */
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
index 48078002e45..355a53a5b6c 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
@@ -2,7 +2,7 @@
* ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
* conntrack/NAT module.
*
- * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com>
+ * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
*
* This source code is licensed under General Public License version 2.
*
@@ -703,6 +703,10 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
type = get_bits(bs, f->sz);
}
+ /* Write Type */
+ if (base)
+ *(unsigned *) base = type;
+
/* Check Range */
if (type >= f->ub) { /* Newer version? */
BYTE_ALIGN(bs);
@@ -712,10 +716,6 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
return H323_ERROR_NONE;
}
- /* Write Type */
- if (base)
- *(unsigned *) base = type;
-
/* Transfer to son level */
son = &f->fields[type];
if (son->attr & STOP) {
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index 5259abd0fb4..0416073c560 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -235,12 +235,15 @@ static int do_basic_checks(struct ip_conntrack *conntrack,
flag = 1;
}
- /* Cookie Ack/Echo chunks not the first OR
- Init / Init Ack / Shutdown compl chunks not the only chunks */
- if ((sch->type == SCTP_CID_COOKIE_ACK
+ /*
+ * Cookie Ack/Echo chunks not the first OR
+ * Init / Init Ack / Shutdown compl chunks not the only chunks
+ * OR zero-length.
+ */
+ if (((sch->type == SCTP_CID_COOKIE_ACK
|| sch->type == SCTP_CID_COOKIE_ECHO
|| flag)
- && count !=0 ) {
+ && count !=0) || !sch->length) {
DEBUGP("Basic checks failed\n");
return 1;
}
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 8f760b28617..67e676783da 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -219,8 +219,10 @@ ip_nat_out(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+#ifdef CONFIG_XFRM
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
+#endif
unsigned int ret;
/* root is playing with raw sockets. */
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index d25ac8ba6eb..cee3397ec27 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -956,15 +956,16 @@ struct compat_ipt_standard_target
compat_int_t verdict;
};
-#define IPT_ST_OFFSET (sizeof(struct ipt_standard_target) - \
- sizeof(struct compat_ipt_standard_target))
-
struct compat_ipt_standard
{
struct compat_ipt_entry entry;
struct compat_ipt_standard_target target;
};
+#define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target))
+#define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target))
+#define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN)
+
static int compat_ipt_standard_fn(void *target,
void **dstptr, int *size, int convert)
{
@@ -975,35 +976,29 @@ static int compat_ipt_standard_fn(void *target,
ret = 0;
switch (convert) {
case COMPAT_TO_USER:
- pst = (struct ipt_standard_target *)target;
+ pst = target;
memcpy(&compat_st.target, &pst->target,
- sizeof(struct ipt_entry_target));
+ sizeof(compat_st.target));
compat_st.verdict = pst->verdict;
if (compat_st.verdict > 0)
compat_st.verdict -=
compat_calc_jump(compat_st.verdict);
- compat_st.target.u.user.target_size =
- sizeof(struct compat_ipt_standard_target);
- if (__copy_to_user(*dstptr, &compat_st,
- sizeof(struct compat_ipt_standard_target)))
+ compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN;
+ if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN))
ret = -EFAULT;
*size -= IPT_ST_OFFSET;
- *dstptr += sizeof(struct compat_ipt_standard_target);
+ *dstptr += IPT_ST_COMPAT_LEN;
break;
case COMPAT_FROM_USER:
- pcompat_st =
- (struct compat_ipt_standard_target *)target;
- memcpy(&st.target, &pcompat_st->target,
- sizeof(struct ipt_entry_target));
+ pcompat_st = target;
+ memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN);
st.verdict = pcompat_st->verdict;
if (st.verdict > 0)
st.verdict += compat_calc_jump(st.verdict);
- st.target.u.user.target_size =
- sizeof(struct ipt_standard_target);
- memcpy(*dstptr, &st,
- sizeof(struct ipt_standard_target));
+ st.target.u.user.target_size = IPT_ST_LEN;
+ memcpy(*dstptr, &st, IPT_ST_LEN);
*size += IPT_ST_OFFSET;
- *dstptr += sizeof(struct ipt_standard_target);
+ *dstptr += IPT_ST_LEN;
break;
case COMPAT_CALC_SIZE:
*size += IPT_ST_OFFSET;
@@ -1446,7 +1441,7 @@ static int compat_copy_entry_to_user(struct ipt_entry *e,
ret = -EFAULT;
origsize = *size;
ce = (struct compat_ipt_entry __user *)*dstptr;
- if (__copy_to_user(ce, e, sizeof(struct ipt_entry)))
+ if (copy_to_user(ce, e, sizeof(struct ipt_entry)))
goto out;
*dstptr += sizeof(struct compat_ipt_entry);
@@ -1464,9 +1459,9 @@ static int compat_copy_entry_to_user(struct ipt_entry *e,
goto out;
ret = -EFAULT;
next_offset = e->next_offset - (origsize - *size);
- if (__put_user(target_offset, &ce->target_offset))
+ if (put_user(target_offset, &ce->target_offset))
goto out;
- if (__put_user(next_offset, &ce->next_offset))
+ if (put_user(next_offset, &ce->next_offset))
goto out;
return 0;
out:
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 87f68e787d0..e2b7b805503 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1468,6 +1468,7 @@ void tcp_close(struct sock *sk, long timeout)
{
struct sk_buff *skb;
int data_was_unread = 0;
+ int state;
lock_sock(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
@@ -1544,6 +1545,11 @@ void tcp_close(struct sock *sk, long timeout)
sk_stream_wait_close(sk, timeout);
adjudge_to_death:
+ state = sk->sk_state;
+ sock_hold(sk);
+ sock_orphan(sk);
+ atomic_inc(sk->sk_prot->orphan_count);
+
/* It is the last release_sock in its life. It will remove backlog. */
release_sock(sk);
@@ -1555,8 +1561,9 @@ adjudge_to_death:
bh_lock_sock(sk);
BUG_TRAP(!sock_owned_by_user(sk));
- sock_hold(sk);
- sock_orphan(sk);
+ /* Have we already been destroyed by a softirq or backlog? */
+ if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE)
+ goto out;
/* This is a (useful) BSD violating of the RFC. There is a
* problem with TCP as specified in that the other end could
@@ -1584,7 +1591,6 @@ adjudge_to_death:
if (tmo > TCP_TIMEWAIT_LEN) {
inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk));
} else {
- atomic_inc(sk->sk_prot->orphan_count);
tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
goto out;
}
@@ -1603,7 +1609,6 @@ adjudge_to_death:
NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY);
}
}
- atomic_inc(sk->sk_prot->orphan_count);
if (sk->sk_state == TCP_CLOSE)
inet_csk_destroy_sock(sk);
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index e0e9d1383c7..b72fa55dfb8 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -137,8 +137,8 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
tp->snd_cwnd_cnt += ca->ai;
if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
- tp->snd_cwnd++;
tp->snd_cwnd_cnt -= tp->snd_cwnd;
+ tp->snd_cwnd++;
}
}
}
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index a28ae593b97..743016baa04 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -465,7 +465,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
TCP_INC_STATS(TCP_MIB_OUTSEGS);
err = icsk->icsk_af_ops->queue_xmit(skb, 0);
- if (unlikely(err <= 0))
+ if (likely(err <= 0))
return err;
tcp_enter_cwr(sk);
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 32ad229b4fe..4ef8efaf6a6 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -62,7 +62,7 @@ static void xfrm4_encap(struct sk_buff *skb)
top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
0 : (iph->frag_off & htons(IP_DF));
if (!top_iph->frag_off)
- __ip_select_ident(top_iph, dst, 0);
+ __ip_select_ident(top_iph, dst->child, 0);
top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 79078747a64..0190e39096b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -317,7 +317,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
__FUNCTION__, head, head ? *head : NULL, oif);
for (rt = rt0, metric = rt0->rt6i_metric;
- rt && rt->rt6i_metric == metric;
+ rt && rt->rt6i_metric == metric && (!last || rt != rt0);
rt = rt->u.next) {
int m;
@@ -343,9 +343,12 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
(strict & RT6_SELECT_F_REACHABLE) &&
last && last != rt0) {
/* no entries matched; do round-robin */
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ spin_lock(&lock);
*head = rt0->u.next;
rt0->u.next = last->u.next;
last->u.next = rt0;
+ spin_unlock(&lock);
}
RT6_TRACE("%s() => %p, score=%d\n",
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 9cccc325b68..0c6da496cfa 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -240,12 +240,15 @@ static int do_basic_checks(struct nf_conn *conntrack,
flag = 1;
}
- /* Cookie Ack/Echo chunks not the first OR
- Init / Init Ack / Shutdown compl chunks not the only chunks */
- if ((sch->type == SCTP_CID_COOKIE_ACK
+ /*
+ * Cookie Ack/Echo chunks not the first OR
+ * Init / Init Ack / Shutdown compl chunks not the only chunks
+ * OR zero-length.
+ */
+ if (((sch->type == SCTP_CID_COOKIE_ACK
|| sch->type == SCTP_CID_COOKIE_ECHO
|| flag)
- && count !=0 ) {
+ && count !=0) || !sch->length) {
DEBUGP("Basic checks failed\n");
return 1;
}
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 17abf60f957..99293c63ff7 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -289,7 +289,7 @@ int xt_compat_match(void *match, void **dstptr, int *size, int convert)
case COMPAT_TO_USER:
pm = (struct xt_entry_match *)match;
msize = pm->u.user.match_size;
- if (__copy_to_user(*dstptr, pm, msize)) {
+ if (copy_to_user(*dstptr, pm, msize)) {
ret = -EFAULT;
break;
}
@@ -366,7 +366,7 @@ int xt_compat_target(void *target, void **dstptr, int *size, int convert)
case COMPAT_TO_USER:
pt = (struct xt_entry_target *)target;
tsize = pt->u.user.target_size;
- if (__copy_to_user(*dstptr, pt, tsize)) {
+ if (copy_to_user(*dstptr, pt, tsize)) {
ret = -EFAULT;
break;
}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 2a233ffcf61..3862e73d14d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -56,12 +56,12 @@
#include <linux/mm.h>
#include <linux/types.h>
#include <linux/audit.h>
+#include <linux/selinux.h>
#include <net/sock.h>
#include <net/scm.h>
#include <net/netlink.h>
-#define Nprintk(a...)
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
struct netlink_sock {
@@ -1157,6 +1157,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
NETLINK_CB(skb).dst_pid = dst_pid;
NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
+ selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
/* What can I do? Netlink is asynchronous, so that
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index d44981f5a61..3669cb953e6 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -425,11 +425,16 @@ static int nr_create(struct socket *sock, int protocol)
nr_init_timers(sk);
- nr->t1 = sysctl_netrom_transport_timeout;
- nr->t2 = sysctl_netrom_transport_acknowledge_delay;
- nr->n2 = sysctl_netrom_transport_maximum_tries;
- nr->t4 = sysctl_netrom_transport_busy_delay;
- nr->idle = sysctl_netrom_transport_no_activity_timeout;
+ nr->t1 =
+ msecs_to_jiffies(sysctl_netrom_transport_timeout);
+ nr->t2 =
+ msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay);
+ nr->n2 =
+ msecs_to_jiffies(sysctl_netrom_transport_maximum_tries);
+ nr->t4 =
+ msecs_to_jiffies(sysctl_netrom_transport_busy_delay);
+ nr->idle =
+ msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout);
nr->window = sysctl_netrom_transport_requested_window_size;
nr->bpqext = 1;
@@ -1365,8 +1370,6 @@ static struct notifier_block nr_dev_notifier = {
static struct net_device **dev_nr;
-static char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n";
-
static int __init nr_proto_init(void)
{
int i;
@@ -1414,7 +1417,6 @@ static int __init nr_proto_init(void)
}
register_netdevice_notifier(&nr_dev_notifier);
- printk(banner);
ax25_protocol_register(AX25_P_NETROM, nr_route_frame);
ax25_linkfail_register(nr_link_failed);
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
index 509afddae56..621e5586ab0 100644
--- a/net/netrom/nr_dev.c
+++ b/net/netrom/nr_dev.c
@@ -185,7 +185,6 @@ static struct net_device_stats *nr_get_stats(struct net_device *dev)
void nr_setup(struct net_device *dev)
{
- SET_MODULE_OWNER(dev);
dev->mtu = NR_MAX_PACKET_SIZE;
dev->hard_start_xmit = nr_xmit;
dev->open = nr_open;
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index ea65396d161..55564efccf1 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -518,11 +518,11 @@ static int rose_create(struct socket *sock, int protocol)
init_timer(&rose->timer);
init_timer(&rose->idletimer);
- rose->t1 = sysctl_rose_call_request_timeout;
- rose->t2 = sysctl_rose_reset_request_timeout;
- rose->t3 = sysctl_rose_clear_request_timeout;
- rose->hb = sysctl_rose_ack_hold_back_timeout;
- rose->idle = sysctl_rose_no_activity_timeout;
+ rose->t1 = msecs_to_jiffies(sysctl_rose_call_request_timeout);
+ rose->t2 = msecs_to_jiffies(sysctl_rose_reset_request_timeout);
+ rose->t3 = msecs_to_jiffies(sysctl_rose_clear_request_timeout);
+ rose->hb = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout);
+ rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout);
rose->state = ROSE_STATE_0;
@@ -1469,8 +1469,6 @@ static struct notifier_block rose_dev_notifier = {
static struct net_device **dev_rose;
-static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n";
-
static int __init rose_proto_init(void)
{
int i;
@@ -1519,7 +1517,6 @@ static int __init rose_proto_init(void)
sock_register(&rose_family_ops);
register_netdevice_notifier(&rose_dev_notifier);
- printk(banner);
ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
ax25_linkfail_register(rose_link_failed);
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index d297af737d1..2a1bf8e119e 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -135,7 +135,6 @@ static struct net_device_stats *rose_get_stats(struct net_device *dev)
void rose_setup(struct net_device *dev)
{
- SET_MODULE_OWNER(dev);
dev->mtu = ROSE_MAX_PACKET_SIZE - 2;
dev->hard_start_xmit = rose_xmit;
dev->open = rose_open;
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
index 09e9e9d04d9..bd86a63960c 100644
--- a/net/rose/rose_link.c
+++ b/net/rose/rose_link.c
@@ -40,7 +40,8 @@ void rose_start_ftimer(struct rose_neigh *neigh)
neigh->ftimer.data = (unsigned long)neigh;
neigh->ftimer.function = &rose_ftimer_expiry;
- neigh->ftimer.expires = jiffies + sysctl_rose_link_fail_timeout;
+ neigh->ftimer.expires =
+ jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout);
add_timer(&neigh->ftimer);
}
@@ -51,7 +52,8 @@ static void rose_start_t0timer(struct rose_neigh *neigh)
neigh->t0timer.data = (unsigned long)neigh;
neigh->t0timer.function = &rose_t0timer_expiry;
- neigh->t0timer.expires = jiffies + sysctl_rose_restart_request_timeout;
+ neigh->t0timer.expires =
+ jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout);
add_timer(&neigh->t0timer);
}
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 8631b65a731..a22542fa1bc 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -48,8 +48,6 @@ static DEFINE_SPINLOCK(rose_route_list_lock);
struct rose_neigh *rose_loopback_neigh;
-static void rose_remove_neigh(struct rose_neigh *);
-
/*
* Add a new route to a node, and in the process add the node and the
* neighbour if it is new.
@@ -235,11 +233,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
skb_queue_purge(&rose_neigh->queue);
- spin_lock_bh(&rose_neigh_list_lock);
-
if ((s = rose_neigh_list) == rose_neigh) {
rose_neigh_list = rose_neigh->next;
- spin_unlock_bh(&rose_neigh_list_lock);
kfree(rose_neigh->digipeat);
kfree(rose_neigh);
return;
@@ -248,7 +243,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
while (s != NULL && s->next != NULL) {
if (s->next == rose_neigh) {
s->next = rose_neigh->next;
- spin_unlock_bh(&rose_neigh_list_lock);
kfree(rose_neigh->digipeat);
kfree(rose_neigh);
return;
@@ -256,7 +250,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh)
s = s->next;
}
- spin_unlock_bh(&rose_neigh_list_lock);
}
/*
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 7228d30512c..5a4a4d0ae50 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -167,7 +167,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
if (count == 0) {
sch->qstats.drops++;
kfree_skb(skb);
- return NET_XMIT_DROP;
+ return NET_XMIT_BYPASS;
}
/*
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 297b8951463..cf0c767d43a 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -149,6 +149,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
/* This is the first chunk in the packet. */
chunk->singleton = 1;
ch = (sctp_chunkhdr_t *) chunk->skb->data;
+ chunk->data_accepted = 0;
}
chunk->chunk_hdr = ch;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 2b9a832b29a..8cdba51ec07 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -636,8 +636,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
*/
chunk->subh.cookie_hdr =
(struct sctp_signed_cookie *)chunk->skb->data;
- skb_pull(chunk->skb,
- ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));
+ if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
+ sizeof(sctp_chunkhdr_t)))
+ goto nomem;
/* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint
* "Z" will reply with a COOKIE ACK chunk after building a TCB
@@ -965,7 +966,8 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep,
*/
chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data;
paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
- skb_pull(chunk->skb, paylen);
+ if (!pskb_pull(chunk->skb, paylen))
+ goto nomem;
reply = sctp_make_heartbeat_ack(asoc, chunk,
chunk->subh.hb_hdr, paylen);
@@ -1860,8 +1862,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep,
* are in good shape.
*/
chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data;
- skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
- sizeof(sctp_chunkhdr_t));
+ if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -
+ sizeof(sctp_chunkhdr_t)))
+ goto nomem;
/* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie
* of a duplicate COOKIE ECHO match the Verification Tags of the
@@ -5151,7 +5154,9 @@ static int sctp_eat_data(const struct sctp_association *asoc,
int tmp;
__u32 tsn;
int account_value;
+ struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
struct sock *sk = asoc->base.sk;
+ int rcvbuf_over = 0;
data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
@@ -5162,10 +5167,16 @@ static int sctp_eat_data(const struct sctp_association *asoc,
/* ASSERT: Now skb->data is really the user data. */
/*
- * if we are established, and we have used up our receive
- * buffer memory, drop the frame
- */
- if (asoc->state == SCTP_STATE_ESTABLISHED) {
+ * If we are established, and we have used up our receive buffer
+ * memory, think about droping the frame.
+ * Note that we have an opportunity to improve performance here.
+ * If we accept one chunk from an skbuff, we have to keep all the
+ * memory of that skbuff around until the chunk is read into user
+ * space. Therefore, once we accept 1 chunk we may as well accept all
+ * remaining chunks in the skbuff. The data_accepted flag helps us do
+ * that.
+ */
+ if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) {
/*
* If the receive buffer policy is 1, then each
* association can allocate up to sk_rcvbuf bytes
@@ -5176,9 +5187,25 @@ static int sctp_eat_data(const struct sctp_association *asoc,
account_value = atomic_read(&asoc->rmem_alloc);
else
account_value = atomic_read(&sk->sk_rmem_alloc);
-
- if (account_value > sk->sk_rcvbuf)
- return SCTP_IERROR_IGNORE_TSN;
+ if (account_value > sk->sk_rcvbuf) {
+ /*
+ * We need to make forward progress, even when we are
+ * under memory pressure, so we always allow the
+ * next tsn after the ctsn ack point to be accepted.
+ * This lets us avoid deadlocks in which we have to
+ * drop frames that would otherwise let us drain the
+ * receive queue.
+ */
+ if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn)
+ return SCTP_IERROR_IGNORE_TSN;
+
+ /*
+ * We're going to accept the frame but we should renege
+ * to make space for it. This will send us down that
+ * path later in this function.
+ */
+ rcvbuf_over = 1;
+ }
}
/* Process ECN based congestion.
@@ -5226,6 +5253,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
datalen -= sizeof(sctp_data_chunk_t);
deliver = SCTP_CMD_CHUNK_ULP;
+ chunk->data_accepted = 1;
/* Think about partial delivery. */
if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) {
@@ -5242,7 +5270,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* large spill over.
*/
if (!asoc->rwnd || asoc->rwnd_over ||
- (datalen > asoc->rwnd + asoc->frag_point)) {
+ (datalen > asoc->rwnd + asoc->frag_point) ||
+ rcvbuf_over) {
/* If this is the next TSN, consider reneging to make
* room. Note: Playing nice with a confused sender. A
@@ -5250,8 +5279,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
* space and in the future we may want to detect and
* do more drastic reneging.
*/
- if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) &&
- (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) {
+ if (sctp_tsnmap_has_gap(map) &&
+ (sctp_tsnmap_get_ctsn(map) + 1) == tsn) {
SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn);
deliver = SCTP_CMD_RENEGE;
} else {
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 75ef1040876..8bcca567615 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -366,9 +366,9 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_EMPTY */ \
{.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_ESTABLISHED */ \
@@ -380,7 +380,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_ECN_ECNE */
#define TYPE_SCTP_ECN_CWR { \
@@ -401,7 +401,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
/* SCTP_STATE_SHUTDOWN_RECEIVED */ \
{.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
/* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \
} /* TYPE_SCTP_ECN_CWR */
#define TYPE_SCTP_SHUTDOWN_COMPLETE { \
@@ -647,7 +647,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
/* SCTP_STATE_EMPTY */ \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_CLOSED */ \
- {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
{.fn = sctp_sf_do_prm_requestheartbeat, \
.name = "sctp_sf_do_prm_requestheartbeat"}, \
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index 2080b2d28c9..575e556aeb3 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -279,6 +279,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq,
static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag)
{
struct sk_buff *pos;
+ struct sk_buff *new = NULL;
struct sctp_ulpevent *event;
struct sk_buff *pnext, *last;
struct sk_buff *list = skb_shinfo(f_frag)->frag_list;
@@ -297,11 +298,33 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu
*/
if (last)
last->next = pos;
- else
- skb_shinfo(f_frag)->frag_list = pos;
+ else {
+ if (skb_cloned(f_frag)) {
+ /* This is a cloned skb, we can't just modify
+ * the frag_list. We need a new skb to do that.
+ * Instead of calling skb_unshare(), we'll do it
+ * ourselves since we need to delay the free.
+ */
+ new = skb_copy(f_frag, GFP_ATOMIC);
+ if (!new)
+ return NULL; /* try again later */
+
+ new->sk = f_frag->sk;
+
+ skb_shinfo(new)->frag_list = pos;
+ } else
+ skb_shinfo(f_frag)->frag_list = pos;
+ }
/* Remove the first fragment from the reassembly queue. */
__skb_unlink(f_frag, queue);
+
+ /* if we did unshare, then free the old skb and re-assign */
+ if (new) {
+ kfree_skb(f_frag);
+ f_frag = new;
+ }
+
while (pos) {
pnext = pos->next;
diff --git a/net/socket.c b/net/socket.c
index 0ce12dfc7a7..02948b622bd 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -267,6 +267,8 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ule
return -EINVAL;
if(len)
{
+ if (audit_sockaddr(klen, kaddr))
+ return -ENOMEM;
if(copy_to_user(uaddr,kaddr,len))
return -EFAULT;
}
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c
index 0a92e1da392..71ff3088f6f 100644
--- a/net/x25/x25_timer.c
+++ b/net/x25/x25_timer.c
@@ -114,8 +114,9 @@ static void x25_heartbeat_expiry(unsigned long param)
if (sock_flag(sk, SOCK_DESTROY) ||
(sk->sk_state == TCP_LISTEN &&
sock_flag(sk, SOCK_DEAD))) {
+ bh_unlock_sock(sk);
x25_destroy_socket(sk);
- goto unlock;
+ return;
}
break;
@@ -128,7 +129,6 @@ static void x25_heartbeat_expiry(unsigned long param)
}
restart_heartbeat:
x25_start_heartbeat(sk);
-unlock:
bh_unlock_sock(sk);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index c3725fe2a8f..b469c8b5461 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -57,12 +57,12 @@ int xfrm_register_type(struct xfrm_type *type, unsigned short family)
return -EAFNOSUPPORT;
typemap = afinfo->type_map;
- write_lock(&typemap->lock);
+ write_lock_bh(&typemap->lock);
if (likely(typemap->map[type->proto] == NULL))
typemap->map[type->proto] = type;
else
err = -EEXIST;
- write_unlock(&typemap->lock);
+ write_unlock_bh(&typemap->lock);
xfrm_policy_put_afinfo(afinfo);
return err;
}
@@ -78,12 +78,12 @@ int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
return -EAFNOSUPPORT;
typemap = afinfo->type_map;
- write_lock(&typemap->lock);
+ write_lock_bh(&typemap->lock);
if (unlikely(typemap->map[type->proto] != type))
err = -ENOENT;
else
typemap->map[type->proto] = NULL;
- write_unlock(&typemap->lock);
+ write_unlock_bh(&typemap->lock);
xfrm_policy_put_afinfo(afinfo);
return err;
}
@@ -1251,7 +1251,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_policy_afinfo_lock);
+ write_lock_bh(&xfrm_policy_afinfo_lock);
if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL))
err = -ENOBUFS;
else {
@@ -1268,7 +1268,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
afinfo->garbage_collect = __xfrm_garbage_collect;
xfrm_policy_afinfo[afinfo->family] = afinfo;
}
- write_unlock(&xfrm_policy_afinfo_lock);
+ write_unlock_bh(&xfrm_policy_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -1280,7 +1280,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_policy_afinfo_lock);
+ write_lock_bh(&xfrm_policy_afinfo_lock);
if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) {
if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo))
err = -EINVAL;
@@ -1294,7 +1294,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
afinfo->garbage_collect = NULL;
}
}
- write_unlock(&xfrm_policy_afinfo_lock);
+ write_unlock_bh(&xfrm_policy_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 3dc3e1f3b7a..93a2f36ad3d 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1061,7 +1061,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_state_afinfo_lock);
+ write_lock_bh(&xfrm_state_afinfo_lock);
if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL))
err = -ENOBUFS;
else {
@@ -1069,7 +1069,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
afinfo->state_byspi = xfrm_state_byspi;
xfrm_state_afinfo[afinfo->family] = afinfo;
}
- write_unlock(&xfrm_state_afinfo_lock);
+ write_unlock_bh(&xfrm_state_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_state_register_afinfo);
@@ -1081,7 +1081,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
return -EINVAL;
if (unlikely(afinfo->family >= NPROTO))
return -EAFNOSUPPORT;
- write_lock(&xfrm_state_afinfo_lock);
+ write_lock_bh(&xfrm_state_afinfo_lock);
if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) {
if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo))
err = -EINVAL;
@@ -1091,7 +1091,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
afinfo->state_bydst = NULL;
}
}
- write_unlock(&xfrm_state_afinfo_lock);
+ write_unlock_bh(&xfrm_state_afinfo_lock);
return err;
}
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 84e21201f3c..37f67c23e11 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -374,10 +374,10 @@ static void do_input(char *alias,
kernel_ulong_t *arr, unsigned int min, unsigned int max)
{
unsigned int i;
- for (i = min; i < max; i++) {
- if (arr[i/BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
- sprintf(alias+strlen(alias), "%X,*", i);
- }
+
+ for (i = min; i < max; i++)
+ if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
+ sprintf(alias + strlen(alias), "%X,*", i);
}
/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
@@ -386,39 +386,37 @@ static int do_input_entry(const char *filename, struct input_device_id *id,
{
sprintf(alias, "input:");
- ADD(alias, "b", id->flags&INPUT_DEVICE_ID_MATCH_BUS, id->id.bustype);
- ADD(alias, "v", id->flags&INPUT_DEVICE_ID_MATCH_VENDOR, id->id.vendor);
- ADD(alias, "p", id->flags&INPUT_DEVICE_ID_MATCH_PRODUCT,
- id->id.product);
- ADD(alias, "e", id->flags&INPUT_DEVICE_ID_MATCH_VERSION,
- id->id.version);
+ ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
+ ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
+ ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
+ ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
sprintf(alias + strlen(alias), "-e*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_EVBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
do_input(alias, id->evbit, 0, EV_MAX);
sprintf(alias + strlen(alias), "k*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_KEYBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
sprintf(alias + strlen(alias), "r*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_RELBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
do_input(alias, id->relbit, 0, REL_MAX);
sprintf(alias + strlen(alias), "a*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_ABSBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
do_input(alias, id->absbit, 0, ABS_MAX);
sprintf(alias + strlen(alias), "m*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_MSCIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
do_input(alias, id->mscbit, 0, MSC_MAX);
sprintf(alias + strlen(alias), "l*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_LEDBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
do_input(alias, id->ledbit, 0, LED_MAX);
sprintf(alias + strlen(alias), "s*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_SNDBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
do_input(alias, id->sndbit, 0, SND_MAX);
sprintf(alias + strlen(alias), "f*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
do_input(alias, id->ffbit, 0, FF_MAX);
sprintf(alias + strlen(alias), "w*");
- if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT)
+ if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
do_input(alias, id->swbit, 0, SW_MAX);
return 1;
}
diff --git a/security/dummy.c b/security/dummy.c
index fd99429278e..8ccccccc12a 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -563,11 +563,6 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
return 0;
}
-static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- return -EOPNOTSUPP;
-}
-
static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
{
return 0;
@@ -976,7 +971,6 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, task_reparent_to_init);
set_to_dummy_if_null(ops, task_to_inode);
set_to_dummy_if_null(ops, ipc_permission);
- set_to_dummy_if_null(ops, ipc_getsecurity);
set_to_dummy_if_null(ops, msg_msg_alloc_security);
set_to_dummy_if_null(ops, msg_msg_free_security);
set_to_dummy_if_null(ops, msg_queue_alloc_security);
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 688c0a267b6..faf2e02e441 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
-selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o
selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index ac5d69bb337..a300702da52 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -800,7 +800,7 @@ out:
int avc_ss_reset(u32 seqno)
{
struct avc_callback_node *c;
- int i, rc = 0;
+ int i, rc = 0, tmprc;
unsigned long flag;
struct avc_node *node;
@@ -813,15 +813,16 @@ int avc_ss_reset(u32 seqno)
for (c = avc_callbacks; c; c = c->next) {
if (c->events & AVC_CALLBACK_RESET) {
- rc = c->callback(AVC_CALLBACK_RESET,
- 0, 0, 0, 0, NULL);
- if (rc)
- goto out;
+ tmprc = c->callback(AVC_CALLBACK_RESET,
+ 0, 0, 0, 0, NULL);
+ /* save the first error encountered for the return
+ value and continue processing the callbacks */
+ if (!rc)
+ rc = tmprc;
}
}
avc_latest_notif_update(seqno, 0);
-out:
return rc;
}
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
new file mode 100644
index 00000000000..ae4c73eb308
--- /dev/null
+++ b/security/selinux/exports.c
@@ -0,0 +1,74 @@
+/*
+ * SELinux services exported to the rest of the kernel.
+ *
+ * Author: James Morris <jmorris@redhat.com>
+ *
+ * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.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.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/selinux.h>
+#include <linux/fs.h>
+#include <linux/ipc.h>
+
+#include "security.h"
+#include "objsec.h"
+
+void selinux_task_ctxid(struct task_struct *tsk, u32 *ctxid)
+{
+ struct task_security_struct *tsec = tsk->security;
+ if (selinux_enabled)
+ *ctxid = tsec->sid;
+ else
+ *ctxid = 0;
+}
+
+int selinux_ctxid_to_string(u32 ctxid, char **ctx, u32 *ctxlen)
+{
+ if (selinux_enabled)
+ return security_sid_to_context(ctxid, ctx, ctxlen);
+ else {
+ *ctx = NULL;
+ *ctxlen = 0;
+ }
+
+ return 0;
+}
+
+void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
+{
+ if (selinux_enabled) {
+ struct inode_security_struct *isec = inode->i_security;
+ *sid = isec->sid;
+ return;
+ }
+ *sid = 0;
+}
+
+void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
+{
+ if (selinux_enabled) {
+ struct ipc_security_struct *isec = ipcp->security;
+ *sid = isec->sid;
+ return;
+ }
+ *sid = 0;
+}
+
+void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
+{
+ if (selinux_enabled) {
+ struct task_security_struct *tsec = tsk->security;
+ *sid = tsec->sid;
+ return;
+ }
+ *sid = 0;
+}
+
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b61b9554bc2..d987048d3f3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -101,6 +101,8 @@ static int __init selinux_enabled_setup(char *str)
return 1;
}
__setup("selinux=", selinux_enabled_setup);
+#else
+int selinux_enabled = 1;
#endif
/* Original (dummy) security module. */
@@ -4052,13 +4054,6 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
return ipc_has_perm(ipcp, av);
}
-static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
-{
- struct ipc_security_struct *isec = ipcp->security;
-
- return selinux_getsecurity(isec->sid, buffer, size);
-}
-
/* module stacking operations */
static int selinux_register_security (const char *name, struct security_operations *ops)
{
@@ -4321,7 +4316,6 @@ static struct security_operations selinux_ops = {
.task_to_inode = selinux_task_to_inode,
.ipc_permission = selinux_ipc_permission,
- .ipc_getsecurity = selinux_ipc_getsecurity,
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
.msg_msg_free_security = selinux_msg_msg_free_security,
@@ -4543,6 +4537,7 @@ int selinux_disable(void)
printk(KERN_INFO "SELinux: Disabled at runtime.\n");
selinux_disabled = 1;
+ selinux_enabled = 0;
/* Reset security_ops to the secondary module, dummy or capability. */
security_ops = secondary_ops;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 5f016c98056..063af47bb23 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -29,12 +29,7 @@
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB
-#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
extern int selinux_enabled;
-#else
-#define selinux_enabled 1
-#endif
-
extern int selinux_mls_enabled;
int security_load_policy(void * data, size_t len);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 84047f69f9c..7bc5b6440f7 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -8,7 +8,7 @@
*
* Support for enhanced MLS infrastructure.
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
*/
#include <linux/kernel.h>
@@ -385,6 +385,34 @@ out:
}
/*
+ * Set the MLS fields in the security context structure
+ * `context' based on the string representation in
+ * the string `str'. This function will allocate temporary memory with the
+ * given constraints of gfp_mask.
+ */
+int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+{
+ char *tmpstr, *freestr;
+ int rc;
+
+ if (!selinux_mls_enabled)
+ return -EINVAL;
+
+ /* we need freestr because mls_context_to_sid will change
+ the value of tmpstr */
+ tmpstr = freestr = kstrdup(str, gfp_mask);
+ if (!tmpstr) {
+ rc = -ENOMEM;
+ } else {
+ rc = mls_context_to_sid(':', &tmpstr, context,
+ NULL, SECSID_NULL);
+ kfree(freestr);
+ }
+
+ return rc;
+}
+
+/*
* Copies the effective MLS range from `src' into `dst'.
*/
static inline int mls_scopy_context(struct context *dst,
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 03de697c805..fbb42f07dd7 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -8,7 +8,7 @@
*
* Support for enhanced MLS infrastructure.
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
*/
#ifndef _SS_MLS_H_
@@ -27,6 +27,8 @@ int mls_context_to_sid(char oldc,
struct sidtab *s,
u32 def_sid);
+int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
+
int mls_convert_context(struct policydb *oldp,
struct policydb *newp,
struct context *context);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 61492485de8..7177e98df7f 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -7,12 +7,13 @@
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
*
* Support for enhanced MLS infrastructure.
+ * Support for context based audit filters.
*
* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
*
* Added conditional policy language extensions
*
- * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* This program is free software; you can redistribute it and/or modify
@@ -1811,3 +1812,235 @@ out:
POLICY_RDUNLOCK;
return rc;
}
+
+struct selinux_audit_rule {
+ u32 au_seqno;
+ struct context au_ctxt;
+};
+
+void selinux_audit_rule_free(struct selinux_audit_rule *rule)
+{
+ if (rule) {
+ context_destroy(&rule->au_ctxt);
+ kfree(rule);
+ }
+}
+
+int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
+ struct selinux_audit_rule **rule)
+{
+ struct selinux_audit_rule *tmprule;
+ struct role_datum *roledatum;
+ struct type_datum *typedatum;
+ struct user_datum *userdatum;
+ int rc = 0;
+
+ *rule = NULL;
+
+ if (!ss_initialized)
+ return -ENOTSUPP;
+
+ switch (field) {
+ case AUDIT_SE_USER:
+ case AUDIT_SE_ROLE:
+ case AUDIT_SE_TYPE:
+ /* only 'equals' and 'not equals' fit user, role, and type */
+ if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL)
+ return -EINVAL;
+ break;
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ /* we do not allow a range, indicated by the presense of '-' */
+ if (strchr(rulestr, '-'))
+ return -EINVAL;
+ break;
+ default:
+ /* only the above fields are valid */
+ return -EINVAL;
+ }
+
+ tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL);
+ if (!tmprule)
+ return -ENOMEM;
+
+ context_init(&tmprule->au_ctxt);
+
+ POLICY_RDLOCK;
+
+ tmprule->au_seqno = latest_granting;
+
+ switch (field) {
+ case AUDIT_SE_USER:
+ userdatum = hashtab_search(policydb.p_users.table, rulestr);
+ if (!userdatum)
+ rc = -EINVAL;
+ else
+ tmprule->au_ctxt.user = userdatum->value;
+ break;
+ case AUDIT_SE_ROLE:
+ roledatum = hashtab_search(policydb.p_roles.table, rulestr);
+ if (!roledatum)
+ rc = -EINVAL;
+ else
+ tmprule->au_ctxt.role = roledatum->value;
+ break;
+ case AUDIT_SE_TYPE:
+ typedatum = hashtab_search(policydb.p_types.table, rulestr);
+ if (!typedatum)
+ rc = -EINVAL;
+ else
+ tmprule->au_ctxt.type = typedatum->value;
+ break;
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
+ break;
+ }
+
+ POLICY_RDUNLOCK;
+
+ if (rc) {
+ selinux_audit_rule_free(tmprule);
+ tmprule = NULL;
+ }
+
+ *rule = tmprule;
+
+ return rc;
+}
+
+int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op,
+ struct selinux_audit_rule *rule,
+ struct audit_context *actx)
+{
+ struct context *ctxt;
+ struct mls_level *level;
+ int match = 0;
+
+ if (!rule) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ "selinux_audit_rule_match: missing rule\n");
+ return -ENOENT;
+ }
+
+ POLICY_RDLOCK;
+
+ if (rule->au_seqno < latest_granting) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ "selinux_audit_rule_match: stale rule\n");
+ match = -ESTALE;
+ goto out;
+ }
+
+ ctxt = sidtab_search(&sidtab, ctxid);
+ if (!ctxt) {
+ audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
+ "selinux_audit_rule_match: unrecognized SID %d\n",
+ ctxid);
+ match = -ENOENT;
+ goto out;
+ }
+
+ /* a field/op pair that is not caught here will simply fall through
+ without a match */
+ switch (field) {
+ case AUDIT_SE_USER:
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = (ctxt->user == rule->au_ctxt.user);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = (ctxt->user != rule->au_ctxt.user);
+ break;
+ }
+ break;
+ case AUDIT_SE_ROLE:
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = (ctxt->role == rule->au_ctxt.role);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = (ctxt->role != rule->au_ctxt.role);
+ break;
+ }
+ break;
+ case AUDIT_SE_TYPE:
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = (ctxt->type == rule->au_ctxt.type);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = (ctxt->type != rule->au_ctxt.type);
+ break;
+ }
+ break;
+ case AUDIT_SE_SEN:
+ case AUDIT_SE_CLR:
+ level = (op == AUDIT_SE_SEN ?
+ &ctxt->range.level[0] : &ctxt->range.level[1]);
+ switch (op) {
+ case AUDIT_EQUAL:
+ match = mls_level_eq(&rule->au_ctxt.range.level[0],
+ level);
+ break;
+ case AUDIT_NOT_EQUAL:
+ match = !mls_level_eq(&rule->au_ctxt.range.level[0],
+ level);
+ break;
+ case AUDIT_LESS_THAN:
+ match = (mls_level_dom(&rule->au_ctxt.range.level[0],
+ level) &&
+ !mls_level_eq(&rule->au_ctxt.range.level[0],
+ level));
+ break;
+ case AUDIT_LESS_THAN_OR_EQUAL:
+ match = mls_level_dom(&rule->au_ctxt.range.level[0],
+ level);
+ break;
+ case AUDIT_GREATER_THAN:
+ match = (mls_level_dom(level,
+ &rule->au_ctxt.range.level[0]) &&
+ !mls_level_eq(level,
+ &rule->au_ctxt.range.level[0]));
+ break;
+ case AUDIT_GREATER_THAN_OR_EQUAL:
+ match = mls_level_dom(level,
+ &rule->au_ctxt.range.level[0]);
+ break;
+ }
+ }
+
+out:
+ POLICY_RDUNLOCK;
+ return match;
+}
+
+static int (*aurule_callback)(void) = NULL;
+
+static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
+ u16 class, u32 perms, u32 *retained)
+{
+ int err = 0;
+
+ if (event == AVC_CALLBACK_RESET && aurule_callback)
+ err = aurule_callback();
+ return err;
+}
+
+static int __init aurule_init(void)
+{
+ int err;
+
+ err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET,
+ SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
+ if (err)
+ panic("avc_add_callback() failed, error %d\n", err);
+
+ return err;
+}
+__initcall(aurule_init);
+
+void selinux_audit_set_callback(int (*callback)(void))
+{
+ aurule_callback = callback;
+}
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 8efc1b12f3a..4262a1c8773 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -142,7 +142,7 @@ config SND_SUPPORT_OLD_API
config SND_VERBOSE_PROCFS
bool "Verbose procfs contents"
- depends on SND
+ depends on SND && PROC_FS
default y
help
Say Y here to include code for verbose procfs contents (provides
@@ -171,3 +171,13 @@ config SND_DEBUG_DETECT
help
Say Y here to enable extra-verbose log messages printed when
detecting devices.
+
+config SND_PCM_XRUN_DEBUG
+ bool "Enable PCM ring buffer overrun/underrun debugging"
+ default n
+ depends on SND_DEBUG && SND_VERBOSE_PROCFS
+ help
+ Say Y to enable the PCM ring buffer overrun/underrun debugging.
+ It is usually not required, but if you have trouble with
+ sound clicking when system is loaded, it may help to determine
+ the process or driver which causes the scheduling gaps.
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index c5978d6c608..ac990bf0b48 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1242,6 +1242,8 @@ static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int for
if (format != AFMT_QUERY) {
formats = snd_pcm_oss_get_formats(pcm_oss_file);
+ if (formats < 0)
+ return formats;
if (!(formats & format))
format = AFMT_U8;
for (idx = 1; idx >= 0; --idx) {
@@ -2212,7 +2214,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
return 0;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SND_VERBOSE_PROCFS
/*
* /proc interface
*/
@@ -2366,10 +2368,10 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm)
}
}
}
-#else /* !CONFIG_PROC_FS */
+#else /* !CONFIG_SND_VERBOSE_PROCFS */
#define snd_pcm_oss_proc_init(pcm)
#define snd_pcm_oss_proc_done(pcm)
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_SND_VERBOSE_PROCFS */
/*
* ENTRY functions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 122e10a61ab..84b00038236 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -142,7 +142,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
return -ENOIOCTLCMD;
}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SND_VERBOSE_PROCFS)
+#ifdef CONFIG_SND_VERBOSE_PROCFS
#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
@@ -436,7 +436,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "appl_ptr : %ld\n", runtime->control->appl_ptr);
}
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
static void snd_pcm_xrun_debug_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
@@ -480,7 +480,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
}
pstr->proc_info_entry = entry;
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
pstr->proc_root)) != NULL) {
entry->c.text.read_size = 64;
@@ -501,7 +501,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr)
{
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (pstr->proc_xrun_debug_entry) {
snd_info_unregister(pstr->proc_xrun_debug_entry);
pstr->proc_xrun_debug_entry = NULL;
@@ -599,12 +599,12 @@ static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream)
}
return 0;
}
-#else /* !CONFIG_PROC_FS */
+#else /* !CONFIG_SND_VERBOSE_PROCFS */
static inline int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) { return 0; }
static inline int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { return 0; }
static inline int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) { return 0; }
static inline int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { return 0; }
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_SND_VERBOSE_PROCFS */
/**
* snd_pcm_new_stream - create a new PCM stream
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 230a940d00b..eedc6cb038b 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -130,7 +130,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
static void xrun(struct snd_pcm_substream *substream)
{
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (substream->pstr->xrun_debug) {
snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
substream->pcm->card->number,
@@ -204,7 +204,7 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs
delta = hw_ptr_interrupt - new_hw_ptr;
if (delta > 0) {
if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (runtime->periods > 1 && substream->pstr->xrun_debug) {
snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
if (substream->pstr->xrun_debug > 1)
@@ -249,7 +249,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
delta = old_hw_ptr - new_hw_ptr;
if (delta > 0) {
if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
if (runtime->periods > 2 && substream->pstr->xrun_debug) {
snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
if (substream->pstr->xrun_debug > 1)
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index a0119ae67dc..428f8c169ee 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -100,8 +100,10 @@ static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream
int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
{
snd_pcm_lib_preallocate_dma_free(substream);
+#ifdef CONFIG_SND_VERBOSE_PROCFS
snd_info_unregister(substream->proc_prealloc_entry);
substream->proc_prealloc_entry = NULL;
+#endif
return 0;
}
@@ -124,7 +126,7 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
return 0;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_SND_VERBOSE_PROCFS
/*
* read callback for prealloc proc file
*
@@ -203,9 +205,9 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
substream->proc_prealloc_entry = entry;
}
-#else /* !CONFIG_PROC_FS */
+#else /* !CONFIG_SND_VERBOSE_PROCFS */
#define preallocate_info_init(s)
-#endif
+#endif /* CONFIG_SND_VERBOSE_PROCFS */
/*
* pre-allocate the buffer and create a proc file for the substream
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index e35fd5779a9..ae0df549fac 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -675,10 +675,8 @@ static int __init alsa_card_dummy_init(void)
continue;
device = platform_device_register_simple(SND_DUMMY_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
devices[i] = device;
cards++;
}
@@ -686,14 +684,10 @@ static int __init alsa_card_dummy_init(void)
#ifdef MODULE
printk(KERN_ERR "Dummy soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_dummy_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_dummy_unregister_all();
- return err;
}
static void __exit alsa_card_dummy_exit(void)
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 9ea3059a706..da7ef26995c 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -251,10 +251,8 @@ static int __init alsa_card_mpu401_init(void)
#endif
device = platform_device_register_simple(SND_MPU401_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
platform_devices[i] = device;
snd_mpu401_devices++;
}
@@ -266,14 +264,10 @@ static int __init alsa_card_mpu401_init(void)
#ifdef MODULE
printk(KERN_ERR "MPU-401 device not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_mpu401_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_mpu401_unregister_all();
- return err;
}
static void __exit alsa_card_mpu401_exit(void)
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 1a7fbefe474..c01b4c5118b 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -996,10 +996,8 @@ static int __init alsa_card_serial_init(void)
continue;
device = platform_device_register_simple(SND_SERIAL_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
devices[i] = device;
cards++;
}
@@ -1007,14 +1005,10 @@ static int __init alsa_card_serial_init(void)
#ifdef MODULE
printk(KERN_ERR "serial midi soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_serial_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_serial_unregister_all();
- return err;
}
static void __exit alsa_card_serial_exit(void)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index a3ee306239c..26eb2499d44 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -169,10 +169,8 @@ static int __init alsa_card_virmidi_init(void)
continue;
device = platform_device_register_simple(SND_VIRMIDI_DRIVER,
i, NULL, 0);
- if (IS_ERR(device)) {
- err = PTR_ERR(device);
- goto errout;
- }
+ if (IS_ERR(device))
+ continue;
devices[i] = device;
cards++;
}
@@ -180,14 +178,10 @@ static int __init alsa_card_virmidi_init(void)
#ifdef MODULE
printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n");
#endif
- err = -ENODEV;
- goto errout;
+ snd_virmidi_unregister_all();
+ return -ENODEV;
}
return 0;
-
- errout:
- snd_virmidi_unregister_all();
- return err;
}
static void __exit alsa_card_virmidi_exit(void)
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 83d64bc07ff..e6bfcf74c1c 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1179,20 +1179,17 @@ static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_mir
/* force ACI into a known state */
for (i = 0; i < 3; i++)
if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "can't force aci into known state.\n");
return -ENXIO;
}
if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 ||
(miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port);
return -ENXIO;
}
if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) {
- snd_card_free(card);
snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n",
miro->aci_port);
return -ENXIO;
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index c6c8333acc6..eece1c7e55a 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -39,7 +39,6 @@
#include <linux/interrupt.h>
#include <linux/compiler.h>
#include <linux/delay.h>
-#include <linux/dma-mapping.h>
#include <sound/driver.h>
#include <sound/core.h>
@@ -1052,7 +1051,7 @@ snd_ad1889_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-static struct pci_device_id snd_ad1889_ids[] = {
+static struct pci_device_id snd_ad1889_ids[] __devinitdata = {
{ PCI_DEVICE(PCI_VENDOR_ID_ANALOG_DEVICES, PCI_DEVICE_ID_AD1889JS) },
{ 0, },
};
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index fc92b6896c2..e2dbc211890 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -279,7 +279,7 @@ struct snd_ali {
#endif
};
-static struct pci_device_id snd_ali_ids[] = {
+static struct pci_device_id snd_ali_ids[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0},
{0, }
};
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 91899f87f03..901b08ae917 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -146,7 +146,7 @@ struct snd_als300_substream_data {
int block_counter_register;
};
-static struct pci_device_id snd_als300_ids[] = {
+static struct pci_device_id snd_als300_ids[] __devinitdata = {
{ 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 },
{ 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS },
{ 0, }
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 100d8127a41..60423b1c678 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -116,7 +116,7 @@ struct snd_card_als4000 {
#endif
};
-static struct pci_device_id snd_als4000_ids[] = {
+static struct pci_device_id snd_als4000_ids[] __devinitdata = {
{ 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */
{ 0, }
};
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 12e61885126..d0f759d86d3 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -284,7 +284,7 @@ struct atiixp {
/*
*/
-static struct pci_device_id snd_atiixp_ids[] = {
+static struct pci_device_id snd_atiixp_ids[] __devinitdata = {
{ 0x1002, 0x4341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
{ 0x1002, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB300 */
{ 0x1002, 0x4370, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 1d376604464..12a34c39caa 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -262,7 +262,7 @@ struct atiixp_modem {
/*
*/
-static struct pci_device_id snd_atiixp_ids[] = {
+static struct pci_device_id snd_atiixp_ids[] __devinitdata = {
{ 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
{ 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
{ 0, }
diff --git a/sound/pci/au88x0/au8810.c b/sound/pci/au88x0/au8810.c
index fce22c7af0e..bd3352998ad 100644
--- a/sound/pci/au88x0/au8810.c
+++ b/sound/pci/au88x0/au8810.c
@@ -1,6 +1,6 @@
#include "au8810.h"
#include "au88x0.h"
-static struct pci_device_id snd_vortex_ids[] = {
+static struct pci_device_id snd_vortex_ids[] __devinitdata = {
{PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1,},
{0,}
diff --git a/sound/pci/au88x0/au8820.c b/sound/pci/au88x0/au8820.c
index d1fbcce0725..7e3fd8372d8 100644
--- a/sound/pci/au88x0/au8820.c
+++ b/sound/pci/au88x0/au8820.c
@@ -1,6 +1,6 @@
#include "au8820.h"
#include "au88x0.h"
-static struct pci_device_id snd_vortex_ids[] = {
+static struct pci_device_id snd_vortex_ids[] __devinitdata = {
{PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
{0,}
diff --git a/sound/pci/au88x0/au8830.c b/sound/pci/au88x0/au8830.c
index d4f2717c14f..b840f6608a6 100644
--- a/sound/pci/au88x0/au8830.c
+++ b/sound/pci/au88x0/au8830.c
@@ -1,6 +1,6 @@
#include "au8830.h"
#include "au88x0.h"
-static struct pci_device_id snd_vortex_ids[] = {
+static struct pci_device_id snd_vortex_ids[] __devinitdata = {
{PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
{0,}
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 680077e1e05..52a36452426 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -216,7 +216,7 @@ struct snd_azf3328 {
int irq;
};
-static const struct pci_device_id snd_azf3328_ids[] = {
+static const struct pci_device_id snd_azf3328_ids[] __devinitdata = {
{ 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */
{ 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */
{ 0, }
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 7b44a8db033..9ee07d4aac1 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -774,7 +774,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card,
.driver_data = rate }
/* driver_data is the default digital_rate value for that device */
-static struct pci_device_id snd_bt87x_ids[] = {
+static struct pci_device_id snd_bt87x_ids[] __devinitdata = {
/* Hauppauge WinTV series */
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0x13eb, 32000),
/* Hauppauge WinTV series */
@@ -911,7 +911,7 @@ static void __devexit snd_bt87x_remove(struct pci_dev *pci)
/* default entries for all Bt87x cards - it's not exported */
/* driver_data is set to 0 to call detection */
-static struct pci_device_id snd_bt87x_default_ids[] = {
+static struct pci_device_id snd_bt87x_default_ids[] __devinitdata = {
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, PCI_ANY_ID, PCI_ANY_ID, 0),
BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, PCI_ANY_ID, PCI_ANY_ID, 0),
{ }
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 9477838a9c8..fd8bfebfbd5 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1561,7 +1561,7 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci)
}
// PCI IDs
-static struct pci_device_id snd_ca0106_ids[] = {
+static struct pci_device_id snd_ca0106_ids[] __devinitdata = {
{ 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
{ 0, }
};
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 2ecbddbbdcf..e5ce2dabd08 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2609,7 +2609,7 @@ static inline void snd_cmipci_proc_init(struct cmipci *cm) {}
#endif
-static struct pci_device_id snd_cmipci_ids[] = {
+static struct pci_device_id snd_cmipci_ids[] __devinitdata = {
{PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index ac4e73f69c1..b3c94d83450 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -494,7 +494,7 @@ struct cs4281 {
static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_cs4281_ids[] = {
+static struct pci_device_id snd_cs4281_ids[] __devinitdata = {
{ 0x1013, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4281 */
{ 0, }
};
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index c590602e20c..848d772ae3c 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control.");
module_param_array(mmap_valid, bool, NULL, 0444);
MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
-static struct pci_device_id snd_cs46xx_ids[] = {
+static struct pci_device_id snd_cs46xx_ids[] __devinitdata = {
{ 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4280 */
{ 0x1013, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4612 */
{ 0x1013, 0x6004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CS4615 */
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 9fc7f382746..2c1213a35dc 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -45,7 +45,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-static struct pci_device_id snd_cs5535audio_ids[] = {
+static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = {
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 2dfa932f782..42b11ba1d21 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -77,7 +77,7 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
/*
* Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400
*/
-static struct pci_device_id snd_emu10k1_ids[] = {
+static struct pci_device_id snd_emu10k1_ids[] __devinitdata = {
{ 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* EMU10K1 */
{ 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy */
{ 0x1102, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, /* Audigy 2 Value SB0400 */
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 3e332f39816..d51290c1816 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -36,7 +36,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
-#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -1596,7 +1595,7 @@ static void __devexit snd_emu10k1x_remove(struct pci_dev *pci)
}
// PCI IDs
-static struct pci_device_id snd_emu10k1x_ids[] = {
+static struct pci_device_id snd_emu10k1x_ids[] __devinitdata = {
{ 0x1102, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Dell OEM version (EMU10K1) */
{ 0, }
};
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index a5533c86b0b..ca9e34e88f6 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -446,7 +446,7 @@ struct ensoniq {
static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_audiopci_ids[] = {
+static struct pci_device_id snd_audiopci_ids[] __devinitdata = {
#ifdef CHIP1370
{ 0x1274, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1370 */
#endif
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 4d62fe43917..6f9094ca4fb 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -242,7 +242,7 @@ struct es1938 {
static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_es1938_ids[] = {
+static struct pci_device_id snd_es1938_ids[] __devinitdata = {
{ 0x125d, 0x1969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Solo-1 */
{ 0, }
};
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index e3ad17f53c2..5ff4175c7b6 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -104,7 +104,6 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/moduleparam.h>
-#include <linux/dma-mapping.h>
#include <linux/mutex.h>
#include <sound/core.h>
@@ -593,7 +592,7 @@ struct es1968 {
static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static struct pci_device_id snd_es1968_ids[] = {
+static struct pci_device_id snd_es1968_ids[] __devinitdata = {
/* Maestro 1 */
{ 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO },
/* Maestro 2 */
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 6ab4aefbccf..d72fc28c580 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -199,7 +199,7 @@ struct fm801 {
#endif
};
-static struct pci_device_id snd_fm801_ids[] = {
+static struct pci_device_id snd_fm801_ids[] __devinitdata = {
{ 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */
{ 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */
{ 0, }
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 0ad60ae2901..e821d65afa1 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1614,7 +1614,7 @@ static void __devexit azx_remove(struct pci_dev *pci)
}
/* PCI IDs */
-static struct pci_device_id azx_ids[] = {
+static struct pci_device_id azx_ids[] __devinitdata = {
{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index bcfca159c6a..40f000ba136 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -799,10 +799,14 @@ static struct hda_board_config ad1986a_cfg_tbl[] = {
{ .modelname = "laptop-eapd", .config = AD1986A_LAPTOP_EAPD },
{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc024,
.config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153,
+ .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1213,
.config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7,
.config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1297,
+ .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */
{ .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
.config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
{}
@@ -1330,12 +1334,8 @@ enum { AD1981_BASIC, AD1981_HP };
static struct hda_board_config ad1981_cfg_tbl[] = {
{ .modelname = "hp", .config = AD1981_HP },
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x30aa,
- .config = AD1981_HP }, /* HP nx6320 */
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x309f,
- .config = AD1981_HP }, /* HP nx9420 AngelFire */
- { .pci_subvendor = 0x103c, .pci_subdevice = 0x30a2,
- .config = AD1981_HP }, /* HP nx9420 AngelFire */
+ /* All HP models */
+ { .pci_subvendor = 0x103c, .config = AD1981_HP },
{ .modelname = "basic", .config = AD1981_BASIC },
{}
};
@@ -2623,5 +2623,6 @@ struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
+ { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 66bbdb60f50..f0e9a9c9078 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2148,6 +2148,7 @@ static struct hda_board_config alc880_cfg_tbl[] = {
{ .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
{ .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
{ .pci_subvendor = 0x1509, .pci_subdevice = 0x925d, .config = ALC880_6ST_DIG }, /* FIC P4M-915GD1 */
+ { .pci_subvendor = 0x1695, .pci_subdevice = 0x4012, .config = ALC880_5ST_DIG }, /* Epox EP-5LDA+ GLi */
{ .modelname = "asus", .config = ALC880_ASUS },
{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 71526078795..8c440fb9860 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1212,8 +1212,8 @@ static hda_nid_t vaio_mux_nids[] = { 0x15 };
static struct hda_input_mux vaio_mux = {
.num_items = 2,
.items = {
- /* { "HP", 0x0 },
- { "Unknown", 0x1 }, */
+ /* { "HP", 0x0 }, */
+ { "Line", 0x1 },
{ "Mic", 0x2 },
{ "PCM", 0x3 },
}
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 32f8415558a..c56793b381e 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -56,7 +56,6 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
-#include <linux/dma-mapping.h>
#include <linux/mutex.h>
#include <sound/core.h>
@@ -108,7 +107,7 @@ module_param_array(dxr_enable, int, NULL, 0444);
MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE.");
-static struct pci_device_id snd_ice1712_ids[] = {
+static struct pci_device_id snd_ice1712_ids[] __devinitdata = {
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */
{ 0, }
};
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index fce616c2761..b1c007e022d 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -86,7 +86,7 @@ MODULE_PARM_DESC(model, "Use the given board model.");
/* Both VT1720 and VT1724 have the same PCI IDs */
-static struct pci_device_id snd_vt1724_ids[] = {
+static struct pci_device_id snd_vt1724_ids[] __devinitdata = {
{ PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, }
};
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index ebbf2cf4ca0..0df7602568e 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -413,7 +413,7 @@ struct intel8x0 {
u32 int_sta_mask; /* interrupt status mask */
};
-static struct pci_device_id snd_intel8x0_ids[] = {
+static struct pci_device_id snd_intel8x0_ids[] __devinitdata = {
{ 0x8086, 0x2415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */
{ 0x8086, 0x2425, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */
{ 0x8086, 0x2445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */
@@ -1293,6 +1293,7 @@ static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substre
return 0;
}
+#if 0 // NYI
static int snd_intel8x0_ali_spdifin_open(struct snd_pcm_substream *substream)
{
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
@@ -1308,7 +1309,6 @@ static int snd_intel8x0_ali_spdifin_close(struct snd_pcm_substream *substream)
return 0;
}
-#if 0 // NYI
static int snd_intel8x0_ali_spdifout_open(struct snd_pcm_substream *substream)
{
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
@@ -1435,6 +1435,7 @@ static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
+#if 0 // NYI
static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
.open = snd_intel8x0_ali_spdifin_open,
.close = snd_intel8x0_ali_spdifin_close,
@@ -1446,7 +1447,6 @@ static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-#if 0 // NYI
static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = {
.open = snd_intel8x0_ali_spdifout_open,
.close = snd_intel8x0_ali_spdifout_close,
@@ -1582,7 +1582,7 @@ static struct ich_pcm_table ali_pcms[] __devinitdata = {
{
.suffix = "IEC958",
.playback_ops = &snd_intel8x0_ali_ac97spdifout_ops,
- .capture_ops = &snd_intel8x0_ali_spdifin_ops,
+ /* .capture_ops = &snd_intel8x0_ali_spdifin_ops, */
.prealloc_size = 64 * 1024,
.prealloc_max_size = 128 * 1024,
.ac97_idx = ALID_AC97SPDIFOUT,
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 47e26aaa9ad..720635f0cb8 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -224,7 +224,7 @@ struct intel8x0m {
unsigned int pcm_pos_shift;
};
-static struct pci_device_id snd_intel8x0m_ids[] = {
+static struct pci_device_id snd_intel8x0m_ids[] __devinitdata = {
{ 0x8086, 0x2416, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */
{ 0x8086, 0x2426, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */
{ 0x8086, 0x2446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 4721c096335..e39fad1a420 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -424,7 +424,7 @@ module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard.");
MODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>");
-static struct pci_device_id snd_korg1212_ids[] = {
+static struct pci_device_id snd_korg1212_ids[] __devinitdata = {
{
.vendor = 0x10b5,
.device = 0x906d,
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 9c90d901e6b..1928e06b6d8 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -41,7 +41,6 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
-#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/control.h>
@@ -870,7 +869,7 @@ struct snd_m3 {
/*
* pci ids
*/
-static struct pci_device_id snd_m3_ids[] = {
+static struct pci_device_id snd_m3_ids[] __devinitdata = {
{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
{PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID,
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index b5a095052d4..09cc0786495 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -28,7 +28,6 @@
#include <linux/dma-mapping.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
-#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -62,7 +61,7 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
/*
*/
-static struct pci_device_id snd_mixart_ids[] = {
+static struct pci_device_id snd_mixart_ids[] __devinitdata = {
{ 0x1057, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* MC8240 */
{ 0, }
};
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index cc297abc9d1..b92d6600deb 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -263,7 +263,7 @@ struct nm256 {
/*
* PCI ids
*/
-static struct pci_device_id snd_nm256_ids[] = {
+static struct pci_device_id snd_nm256_ids[] __devinitdata = {
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 35875c8aa29..dafa2235aba 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
-#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -74,7 +73,7 @@ enum {
PCI_ID_LAST
};
-static struct pci_device_id pcxhr_ids[] = {
+static struct pci_device_id pcxhr_ids[] __devinitdata = {
{ 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, /* VX882HR */
{ 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, /* PCX882HR */
{ 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, /* VX881HR */
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 03517c10e99..369c19fea98 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -385,8 +385,8 @@ static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
fw.size = dsp->length;
fw.data = vmalloc(fw.size);
if (! fw.data) {
- snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%d bytes)\n",
- fw.size);
+ snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%lu bytes)\n",
+ (unsigned long)fw.size);
return -ENOMEM;
}
if (copy_from_user(fw.data, dsp->image, dsp->length)) {
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index f148ee434a6..d8cc985d724 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -506,7 +506,7 @@ static int riptide_reset(struct cmdif *cif, struct snd_riptide *chip);
/*
*/
-static struct pci_device_id snd_riptide_ids[] = {
+static struct pci_device_id snd_riptide_ids[] __devinitdata = {
{
.vendor = 0x127a,.device = 0x4310,
.subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
@@ -527,7 +527,7 @@ static struct pci_device_id snd_riptide_ids[] = {
};
#ifdef SUPPORT_JOYSTICK
-static struct pci_device_id snd_riptide_joystick_ids[] = {
+static struct pci_device_id snd_riptide_joystick_ids[] __devinitdata = {
{
.vendor = 0x127a,.device = 0x4312,
.subvendor = PCI_ANY_ID,.subdevice = PCI_ANY_ID,
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index ab78544bf04..55b1d4838d9 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -227,7 +227,7 @@ struct rme32 {
struct snd_kcontrol *spdif_ctl;
};
-static struct pci_device_id snd_rme32_ids[] = {
+static struct pci_device_id snd_rme32_ids[] __devinitdata = {
{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
{PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8,
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 6c2a9f4a765..3c1bc533d51 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -232,7 +232,7 @@ struct rme96 {
struct snd_kcontrol *spdif_ctl;
};
-static struct pci_device_id snd_rme96_ids[] = {
+static struct pci_device_id snd_rme96_ids[] __devinitdata = {
{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8,
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index ebf7a2b86c2..61f82f0d5cc 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -568,7 +568,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d
}
-static struct pci_device_id snd_hdsp_ids[] = {
+static struct pci_device_id snd_hdsp_ids[] __devinitdata = {
{
.vendor = PCI_VENDOR_ID_XILINX,
.device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP,
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index b5538efd146..722b9e6ce54 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -426,7 +426,7 @@ static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
};
-static struct pci_device_id snd_hdspm_ids[] = {
+static struct pci_device_id snd_hdspm_ids[] __devinitdata = {
{
.vendor = PCI_VENDOR_ID_XILINX,
.device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index a687eb63236..75d6406303d 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -315,7 +315,7 @@ static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_d
}
-static struct pci_device_id snd_rme9652_ids[] = {
+static struct pci_device_id snd_rme9652_ids[] __devinitdata = {
{
.vendor = 0x10ee,
.device = 0x3fc4,
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 2d66a09fe5e..91f8bf3ae9f 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -243,7 +243,7 @@ struct sonicvibes {
#endif
};
-static struct pci_device_id snd_sonic_ids[] = {
+static struct pci_device_id snd_sonic_ids[] __devinitdata = {
{ 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
{ 0, }
};
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index b4538045049..9624a5f2b87 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM.");
module_param_array(wavetable_size, int, NULL, 0444);
MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
-static struct pci_device_id snd_trident_ids[] = {
+static struct pci_device_id snd_trident_ids[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
{PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 0f171dd1377..39daf62d2ba 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -123,6 +123,7 @@ module_param(enable, bool, 0444);
#define VIA_REV_8233A 0x40 /* 1 rec, 1 multi-pb, spdf */
#define VIA_REV_8235 0x50 /* 2 rec, 4 pb, 1 multi-pb, spdif */
#define VIA_REV_8237 0x60
+#define VIA_REV_8251 0x70
/*
* Direct registers
@@ -395,7 +396,7 @@ struct via82xx {
#endif
};
-static struct pci_device_id snd_via82xx_ids[] = {
+static struct pci_device_id snd_via82xx_ids[] __devinitdata = {
/* 0x1106, 0x3058 */
{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, }, /* 686A */
/* 0x1106, 0x3059 */
@@ -862,6 +863,11 @@ static snd_pcm_uframes_t snd_via8233_pcm_pointer(struct snd_pcm_substream *subst
if (!status)
status = inb(VIADEV_REG(viadev, OFFSET_STATUS));
+ /* An apparent bug in the 8251 is worked around by sending a
+ * REG_CTRL_START. */
+ if (chip->revision == VIA_REV_8251 && (status & VIA_REG_STAT_EOL))
+ snd_via82xx_pcm_trigger(substream, SNDRV_PCM_TRIGGER_START);
+
if (!(status & VIA_REG_STAT_ACTIVE)) {
res = 0;
goto unlock;
@@ -2313,6 +2319,7 @@ static struct via823x_info via823x_cards[] __devinitdata = {
{ VIA_REV_8233A, "VIA 8233A", TYPE_VIA8233A },
{ VIA_REV_8235, "VIA 8235", TYPE_VIA8233 },
{ VIA_REV_8237, "VIA 8237", TYPE_VIA8233 },
+ { VIA_REV_8251, "VIA 8251", TYPE_VIA8233 },
};
/*
@@ -2325,7 +2332,7 @@ struct dxs_whitelist {
short action; /* new dxs_support value */
};
-static int __devinit check_dxs_list(struct pci_dev *pci)
+static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
{
static struct dxs_whitelist whitelist[] = {
{ .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
@@ -2342,6 +2349,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
{ .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */
{ .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */
{ .subvendor = 0x1043, .subdevice = 0x8174, .action = VIA_DXS_SRC }, /* ASUS */
+ { .subvendor = 0x1043, .subdevice = 0x81b9, .action = VIA_DXS_SRC }, /* ASUS A8V-MX */
{ .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
{ .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
{ .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
@@ -2405,6 +2413,10 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
}
}
+ /* for newer revision, default to DXS_SRC */
+ if (revision >= VIA_REV_8235)
+ return VIA_DXS_SRC;
+
/*
* not detected, try 48k rate only to be sure.
*/
@@ -2449,7 +2461,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
}
if (chip_type != TYPE_VIA8233A) {
if (dxs_support == VIA_DXS_AUTO)
- dxs_support = check_dxs_list(pci);
+ dxs_support = check_dxs_list(pci, revision);
/* force to use VIA8233 or 8233A model according to
* dxs_support module option
*/
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 22ce4d30992..ef97e50cd6c 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -261,7 +261,7 @@ struct via82xx_modem {
struct snd_info_entry *proc_entry;
};
-static struct pci_device_id snd_via82xx_modem_ids[] = {
+static struct pci_device_id snd_via82xx_modem_ids[] __devinitdata = {
{ 0x1106, 0x3068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA82XX_MODEM, },
{ 0, }
};
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index c816ddf1b21..0f1ebb010a5 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -60,7 +60,7 @@ enum {
VX_PCI_VX222_NEW
};
-static struct pci_device_id snd_vx222_ids[] = {
+static struct pci_device_id snd_vx222_ids[] __devinitdata = {
{ 0x10b5, 0x9050, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_OLD, }, /* PLX */
{ 0x10b5, 0x9030, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_NEW, }, /* PLX */
{ 0, }
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index db57ce939fa..65ebf5f1933 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -70,7 +70,7 @@ MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
module_param_array(rear_swap, bool, NULL, 0444);
MODULE_PARM_DESC(rear_swap, "Swap rear channels (must be enabled for correct IEC958 (S/PDIF)) output");
-static struct pci_device_id snd_ymfpci_ids[] = {
+static struct pci_device_id snd_ymfpci_ids[] __devinitdata = {
{ 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724 */
{ 0x1073, 0x000d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF724F */
{ 0x1073, 0x000a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* YMF740 */
diff --git a/sound/pcmcia/Kconfig b/sound/pcmcia/Kconfig
index 5d1b0b762ef..c9fa1a2bc58 100644
--- a/sound/pcmcia/Kconfig
+++ b/sound/pcmcia/Kconfig
@@ -5,7 +5,7 @@ menu "PCMCIA devices"
config SND_VXPOCKET
tristate "Digigram VXpocket"
- depends on SND && PCMCIA && ISA
+ depends on SND && PCMCIA
select SND_VX_LIB
help
Say Y here to include support for Digigram VXpocket and
@@ -16,7 +16,7 @@ config SND_VXPOCKET
config SND_PDAUDIOCF
tristate "Sound Core PDAudioCF"
- depends on SND && PCMCIA && ISA
+ depends on SND && PCMCIA
select SND_PCM
help
Say Y here to include support for Sound Core PDAudioCF
diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c
index 4e595172e42..1ac7c8552f5 100644
--- a/sound/ppc/toonie.c
+++ b/sound/ppc/toonie.c
@@ -335,7 +335,7 @@ static void toonie_cleanup(struct snd_pmac *chip)
chip->mixer_data = NULL;
}
-int snd_pmac_toonie_init(struct snd_pmac *chip)
+int __init snd_pmac_toonie_init(struct snd_pmac *chip)
{
struct pmac_toonie *mix;
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 0992a0923f1..9351846d7a9 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1531,6 +1531,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0014),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "TerraTec",
+ .product_name = "PHASE 26",
+ .ifnum = 3,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
+ }
+},
+{
USB_DEVICE(0x0ccd, 0x0035),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
.vendor_name = "Miditech",