aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-03-31 20:58:51 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2005-03-31 20:58:51 -0800
commit24ca97c3746c322cf857475c47b813eaf06dc786 (patch)
tree7d306aeea06f195d13145661322ec4c4d24f6628
parent4b84c6431470729efeb5cc2a9f2e45da053cc25e (diff)
parentf6ea76c0dc98f2a9219ee5327a2d3a00dfb7e89b (diff)
downloadhistory-24ca97c3746c322cf857475c47b813eaf06dc786.tar.gz
Merge sunset.davemloft.net:/home/davem/src/BK/sparcwork-2.6
into sunset.davemloft.net:/home/davem/src/BK/sparc-2.6
-rw-r--r--Documentation/SubmittingDrivers7
-rw-r--r--Documentation/cpusets.txt8
-rw-r--r--Documentation/i2c/busses/i2c-ali153542
-rw-r--r--Documentation/i2c/busses/i2c-ali156327
-rw-r--r--Documentation/i2c/busses/i2c-ali15x3112
-rw-r--r--Documentation/i2c/busses/i2c-amd75625
-rw-r--r--Documentation/i2c/busses/i2c-amd811141
-rw-r--r--Documentation/i2c/busses/i2c-i80180
-rw-r--r--Documentation/i2c/busses/i2c-i81046
-rw-r--r--Documentation/i2c/busses/i2c-nforce241
-rw-r--r--Documentation/i2c/busses/i2c-parport (renamed from Documentation/i2c/i2c-parport)18
-rw-r--r--Documentation/i2c/busses/i2c-parport-light11
-rw-r--r--Documentation/i2c/busses/i2c-pca-isa23
-rw-r--r--Documentation/i2c/busses/i2c-piix472
-rw-r--r--Documentation/i2c/busses/i2c-prosavage23
-rw-r--r--Documentation/i2c/busses/i2c-savage426
-rw-r--r--Documentation/i2c/busses/i2c-sis559559
-rw-r--r--Documentation/i2c/busses/i2c-sis63049
-rw-r--r--Documentation/i2c/busses/i2c-sis69x73
-rw-r--r--Documentation/i2c/busses/i2c-via34
-rw-r--r--Documentation/i2c/busses/i2c-viapro47
-rw-r--r--Documentation/i2c/busses/i2c-voodoo362
-rw-r--r--Documentation/i2c/busses/scx200_acb14
-rw-r--r--Documentation/kernel-docs.txt7
-rw-r--r--Documentation/oops-tracing.txt32
-rw-r--r--Documentation/sysrq.txt2
-rw-r--r--arch/frv/kernel/setup.c3
-rw-r--r--arch/i386/kernel/acpi/sleep.c3
-rw-r--r--arch/i386/kernel/cpu/common.c11
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c456
-rw-r--r--arch/i386/kernel/entry.S130
-rw-r--r--arch/i386/kernel/head.S2
-rw-r--r--arch/i386/kernel/kprobes.c19
-rw-r--r--arch/i386/kernel/process.c29
-rw-r--r--arch/i386/kernel/smp.c2
-rw-r--r--arch/i386/kernel/traps.c45
-rw-r--r--arch/ia64/Kconfig1
-rw-r--r--arch/ia64/kernel/acpi.c2
-rw-r--r--arch/ia64/kernel/iosapic.c9
-rw-r--r--arch/ia64/kernel/ivt.S3
-rw-r--r--arch/ia64/kernel/minstate.h2
-rw-r--r--arch/ia64/kernel/setup.c9
-rw-r--r--arch/ia64/kernel/unaligned.c16
-rw-r--r--arch/ia64/pci/pci.c134
-rw-r--r--arch/ia64/sn/kernel/setup.c28
-rw-r--r--arch/m32r/kernel/setup.c31
-rw-r--r--arch/m32r/mm/discontig.c1
-rw-r--r--arch/ppc/Kconfig2
-rw-r--r--arch/ppc/boot/simple/mpc52xx_tty.c30
-rw-r--r--arch/ppc/kernel/entry.S91
-rw-r--r--arch/ppc/kernel/head_44x.S77
-rw-r--r--arch/ppc/kernel/head_4xx.S44
-rw-r--r--arch/ppc/kernel/head_booke.h139
-rw-r--r--arch/ppc/kernel/head_e500.S81
-rw-r--r--arch/ppc/platforms/85xx/mpc8560_ads.c18
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c19
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c21
-rw-r--r--arch/ppc/platforms/Makefile2
-rw-r--r--arch/ppc/platforms/lite5200.c87
-rw-r--r--arch/ppc/platforms/lite5200.h2
-rw-r--r--arch/ppc/platforms/pmac_backlight.c80
-rw-r--r--arch/ppc/syslib/Makefile3
-rw-r--r--arch/ppc/syslib/cpm2_pic.c94
-rw-r--r--arch/ppc/syslib/cpm2_pic.h3
-rw-r--r--arch/ppc/syslib/m8260_setup.c8
-rw-r--r--arch/ppc/syslib/mpc52xx_devices.c318
-rw-r--r--arch/ppc/syslib/mpc52xx_pci.c2
-rw-r--r--arch/ppc/syslib/mpc52xx_pic.c4
-rw-r--r--arch/ppc/syslib/mpc52xx_setup.c42
-rw-r--r--arch/ppc/syslib/mpc52xx_sys.c38
-rw-r--r--arch/ppc/syslib/mpc85xx_sys.c8
-rw-r--r--arch/ppc64/Kconfig17
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c40
-rw-r--r--arch/ppc64/kernel/kprobes.c15
-rw-r--r--arch/ppc64/kernel/lmb.c26
-rw-r--r--arch/ppc64/kernel/prom.c15
-rw-r--r--arch/ppc64/kernel/prom_init.c137
-rw-r--r--arch/ppc64/kernel/ptrace.c3
-rw-r--r--arch/ppc64/kernel/setup.c20
-rw-r--r--arch/ppc64/mm/hash_utils.c23
-rw-r--r--arch/ppc64/mm/numa.c46
-rw-r--r--arch/s390/mm/fault.c2
-rw-r--r--arch/sparc64/kernel/kprobes.c18
-rw-r--r--arch/um/Kconfig.debug2
-rw-r--r--arch/um/drivers/chan_kern.c5
-rw-r--r--arch/um/drivers/line.c2
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h16
-rw-r--r--arch/um/include/sysdep-i386/syscalls.h16
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h6
-rw-r--r--arch/um/include/sysdep-x86_64/syscalls.h5
-rw-r--r--arch/um/kernel/sigio_user.c29
-rw-r--r--arch/um/kernel/skas/uaccess.c3
-rw-r--r--arch/um/kernel/sys_call_table.c15
-rw-r--r--arch/um/kernel/um_arch.c2
-rw-r--r--arch/x86_64/ia32/sys_ia32.c1
-rw-r--r--arch/x86_64/kernel/kprobes.c160
-rw-r--r--arch/x86_64/kernel/process.c41
-rw-r--r--arch/x86_64/kernel/smp.c5
-rw-r--r--arch/x86_64/kernel/sys_x86_64.c1
-rw-r--r--drivers/acpi/Kconfig20
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ac.c18
-rw-r--r--drivers/acpi/acpi_memhotplug.c542
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/button.c4
-rw-r--r--drivers/acpi/container.c15
-rw-r--r--drivers/acpi/debug.c4
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c11
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c8
-rw-r--r--drivers/acpi/dispatcher/dsutils.c166
-rw-r--r--drivers/acpi/dispatcher/dswexec.c61
-rw-r--r--drivers/acpi/ec.c2
-rw-r--r--drivers/acpi/events/evxface.c4
-rw-r--r--drivers/acpi/executer/exmisc.c5
-rw-r--r--drivers/acpi/executer/exoparg2.c6
-rw-r--r--drivers/acpi/executer/exresolv.c6
-rw-r--r--drivers/acpi/executer/exstoren.c7
-rw-r--r--drivers/acpi/executer/exstorob.c27
-rw-r--r--drivers/acpi/fan.c33
-rw-r--r--drivers/acpi/ibm_acpi.c4
-rw-r--r--drivers/acpi/numa.c2
-rw-r--r--drivers/acpi/osl.c10
-rw-r--r--drivers/acpi/parser/psopcode.c2
-rw-r--r--drivers/acpi/parser/psparse.c42
-rw-r--r--drivers/acpi/parser/pswalk.c254
-rw-r--r--drivers/acpi/pci_irq.c38
-rw-r--r--drivers/acpi/pci_link.c14
-rw-r--r--drivers/acpi/pci_root.c4
-rw-r--r--drivers/acpi/power.c10
-rw-r--r--drivers/acpi/processor_core.c6
-rw-r--r--drivers/acpi/processor_thermal.c2
-rw-r--r--drivers/acpi/processor_throttling.c2
-rw-r--r--drivers/acpi/resources/rsaddr.c146
-rw-r--r--drivers/acpi/resources/rscalc.c14
-rw-r--r--drivers/acpi/resources/rsdump.c23
-rw-r--r--drivers/acpi/resources/rslist.c1
-rw-r--r--drivers/acpi/scan.c47
-rw-r--r--drivers/acpi/thermal.c2
-rw-r--r--drivers/acpi/toshiba_acpi.c2
-rw-r--r--drivers/acpi/utilities/utcopy.c19
-rw-r--r--drivers/acpi/utilities/utdelete.c18
-rw-r--r--drivers/acpi/utilities/utglobal.c10
-rw-r--r--drivers/acpi/utilities/utmisc.c44
-rw-r--r--drivers/acpi/video.c2
-rw-r--r--drivers/block/ll_rw_blk.c2
-rw-r--r--drivers/block/nbd.c2
-rw-r--r--drivers/block/rd.c4
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/mem.c31
-rw-r--r--drivers/char/rio/riocmd.c67
-rw-r--r--drivers/char/sx.c60
-rw-r--r--drivers/char/sysrq.c23
-rw-r--r--drivers/char/vt.c18
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c13
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c44
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c13
-rw-r--r--drivers/i2c/busses/Kconfig38
-rw-r--r--drivers/i2c/busses/i2c-elektor.c9
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c4
-rw-r--r--drivers/i2c/busses/i2c-ite.c7
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c15
-rw-r--r--drivers/i2c/busses/i2c-viapro.c17
-rw-r--r--drivers/i2c/chips/Kconfig25
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/i2c/chips/adm1021.c14
-rw-r--r--drivers/i2c/chips/ds1337.c402
-rw-r--r--drivers/i2c/chips/eeprom.c3
-rw-r--r--drivers/i2c/chips/it87.c10
-rw-r--r--drivers/i2c/chips/lm85.c104
-rw-r--r--drivers/i2c/chips/lm87.c20
-rw-r--r--drivers/i2c/chips/lm90.c44
-rw-r--r--drivers/i2c/chips/lm92.c423
-rw-r--r--drivers/i2c/chips/m41t00.c1
-rw-r--r--drivers/i2c/chips/w83627hf.c5
-rw-r--r--drivers/i2c/chips/w83781d.c100
-rw-r--r--drivers/i2c/i2c-core.c10
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c10
-rw-r--r--drivers/media/dvb/frontends/cx24110.c28
-rw-r--r--drivers/media/video/zr36050.c2
-rw-r--r--drivers/net/bonding/bond_main.c15
-rw-r--r--drivers/net/pppoe.c28
-rw-r--r--drivers/parport/parport_pc.c8
-rw-r--r--drivers/pci/msi.c4
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c9
-rw-r--r--drivers/serial/Kconfig2
-rw-r--r--drivers/serial/mpc52xx_uart.c189
-rw-r--r--drivers/video/Kconfig31
-rw-r--r--drivers/video/Makefile14
-rw-r--r--drivers/video/asiliantfb.c2
-rw-r--r--drivers/video/aty/aty128fb.c2
-rw-r--r--drivers/video/aty/atyfb_base.c27
-rw-r--r--drivers/video/aty/radeon_accel.c28
-rw-r--r--drivers/video/aty/radeon_base.c67
-rw-r--r--drivers/video/aty/radeon_i2c.c6
-rw-r--r--drivers/video/aty/radeon_monitor.c33
-rw-r--r--drivers/video/aty/radeon_pm.c41
-rw-r--r--drivers/video/aty/radeonfb.h146
-rw-r--r--drivers/video/chipsfb.c2
-rw-r--r--drivers/video/cirrusfb.c2
-rw-r--r--drivers/video/console/bitblit.c11
-rw-r--r--drivers/video/console/fbcon.c86
-rw-r--r--drivers/video/console/fbcon.h8
-rw-r--r--drivers/video/console/mdacon.c4
-rw-r--r--drivers/video/console/sticore.c9
-rw-r--r--drivers/video/cyber2000fb.c2
-rw-r--r--drivers/video/fbmem.c9
-rw-r--r--drivers/video/fbmon.c23
-rw-r--r--drivers/video/igafb.c3
-rw-r--r--drivers/video/imsttfb.c2
-rw-r--r--drivers/video/intelfb/intelfbdrv.c2
-rw-r--r--drivers/video/kyro/fbdev.c2
-rw-r--r--drivers/video/macmodes.c9
-rw-r--r--drivers/video/matrox/matroxfb_accel.c14
-rw-r--r--drivers/video/matrox/matroxfb_base.h4
-rw-r--r--drivers/video/modedb.c4
-rw-r--r--drivers/video/neofb.c38
-rw-r--r--drivers/video/nvidia/nv_accel.c72
-rw-r--r--drivers/video/nvidia/nv_dma.h10
-rw-r--r--drivers/video/nvidia/nv_hw.c11
-rw-r--r--drivers/video/nvidia/nv_i2c.c2
-rw-r--r--drivers/video/nvidia/nv_local.h13
-rw-r--r--drivers/video/nvidia/nv_of.c1
-rw-r--r--drivers/video/nvidia/nv_proto.h2
-rw-r--r--drivers/video/nvidia/nv_setup.c10
-rw-r--r--drivers/video/nvidia/nvidia.c35
-rw-r--r--drivers/video/pm2fb.c4
-rw-r--r--drivers/video/pvr2fb.c2
-rw-r--r--drivers/video/pxafb.c3
-rw-r--r--drivers/video/radeonfb.c2
-rw-r--r--drivers/video/riva/fbdev.c6
-rw-r--r--drivers/video/s1d13xxxfb.c772
-rw-r--r--drivers/video/sa1100fb.c3
-rw-r--r--drivers/video/savage/savagefb_driver.c3
-rw-r--r--drivers/video/sis/sis_main.c4
-rw-r--r--drivers/video/sstfb.c2
-rw-r--r--drivers/video/tdfxfb.c2
-rw-r--r--drivers/video/tgafb.c2
-rw-r--r--drivers/video/tridentfb.c4
-rw-r--r--drivers/video/vga16fb.c24
-rw-r--r--drivers/video/w100fb.c6
-rw-r--r--fs/buffer.c2
-rw-r--r--fs/fs-writeback.c4
-rw-r--r--fs/hostfs/hostfs_kern.c20
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/inode.c8
-rw-r--r--fs/nfs/dir.c2
-rw-r--r--fs/nfsd/nfs4acl.c40
-rw-r--r--fs/nfsd/nfs4callback.c2
-rw-r--r--fs/nfsd/nfs4proc.c60
-rw-r--r--fs/nfsd/nfs4state.c103
-rw-r--r--fs/nfsd/nfs4xdr.c5
-rw-r--r--fs/nfsd/vfs.c7
-rw-r--r--fs/ramfs/inode.c4
-rw-r--r--fs/sysfs/inode.c2
-rw-r--r--include/acpi/acconfig.h4
-rw-r--r--include/acpi/acdisasm.h5
-rw-r--r--include/acpi/acdispat.h10
-rw-r--r--include/acpi/acinterp.h1
-rw-r--r--include/acpi/aclocal.h4
-rw-r--r--include/acpi/acpi_bus.h1
-rw-r--r--include/acpi/acpi_drivers.h3
-rw-r--r--include/acpi/acstruct.h1
-rw-r--r--include/acpi/actbl.h4
-rw-r--r--include/acpi/actbl2.h79
-rw-r--r--include/acpi/actypes.h39
-rw-r--r--include/acpi/platform/acenv.h2
-rw-r--r--include/acpi/processor.h2
-rw-r--r--include/asm-arm/atomic.h1
-rw-r--r--include/asm-arm/ipc.h30
-rw-r--r--include/asm-arm26/ipc.h29
-rw-r--r--include/asm-cris/ipc.h36
-rw-r--r--include/asm-frv/ipc.h34
-rw-r--r--include/asm-generic/ipc.h31
-rw-r--r--include/asm-h8300/ipc.h32
-rw-r--r--include/asm-i386/desc.h4
-rw-r--r--include/asm-i386/ipc.h33
-rw-r--r--include/asm-i386/processor.h12
-rw-r--r--include/asm-i386/seccomp.h16
-rw-r--r--include/asm-i386/segment.h5
-rw-r--r--include/asm-ia64/smp.h45
-rw-r--r--include/asm-ia64/sn/addrs.h7
-rw-r--r--include/asm-ia64/sn/arch.h24
-rw-r--r--include/asm-ia64/sn/pda.h15
-rw-r--r--include/asm-ia64/sn/sn_cpuid.h5
-rw-r--r--include/asm-ia64/sn/sn_sal.h50
-rw-r--r--include/asm-m32r/ipc.h36
-rw-r--r--include/asm-m32r/spinlock.h6
-rw-r--r--include/asm-m68k/ipc.h32
-rw-r--r--include/asm-m68knommu/ipc.h2
-rw-r--r--include/asm-mips/ipc.h34
-rw-r--r--include/asm-ppc/cpm2.h2
-rw-r--r--include/asm-ppc/ipc.h30
-rw-r--r--include/asm-ppc/irq.h169
-rw-r--r--include/asm-ppc/mpc52xx.h113
-rw-r--r--include/asm-ppc/mpc85xx.h49
-rw-r--r--include/asm-ppc/ppc_sys.h2
-rw-r--r--include/asm-ppc64/ipc.h35
-rw-r--r--include/asm-ppc64/lmb.h1
-rw-r--r--include/asm-ppc64/seccomp.h21
-rw-r--r--include/asm-ppc64/thread_info.h4
-rw-r--r--include/asm-s390/ipc.h41
-rw-r--r--include/asm-sh/ipc.h33
-rw-r--r--include/asm-sh64/ipc.h7
-rw-r--r--include/asm-sparc/ipc.h33
-rw-r--r--include/asm-sparc64/ipc.h34
-rw-r--r--include/asm-v850/ipc.h32
-rw-r--r--include/asm-x86_64/ipc.h6
-rw-r--r--include/asm-x86_64/msr.h12
-rw-r--r--include/asm-x86_64/seccomp.h24
-rw-r--r--include/asm-x86_64/unistd.h2
-rw-r--r--include/linux/acpi.h2
-rw-r--r--include/linux/backing-dev.h41
-rw-r--r--include/linux/console.h1
-rw-r--r--include/linux/fb.h4
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/i2c.h13
-rw-r--r--include/linux/inetdevice.h20
-rw-r--r--include/linux/ip.h2
-rw-r--r--include/linux/rtnetlink.h13
-rw-r--r--include/linux/seccomp.h1
-rw-r--r--include/linux/sunrpc/svcauth.h14
-rw-r--r--include/net/llc_conn.h2
-rw-r--r--include/net/sock.h33
-rw-r--r--include/video/s1d13xxxfb.h166
-rw-r--r--include/video/trident.h2
-rw-r--r--kernel/cpuset.c4
-rw-r--r--kernel/printk.c18
-rw-r--r--kernel/rcupdate.c6
-rw-r--r--kernel/sched.c2
-rw-r--r--kernel/seccomp.c32
-rw-r--r--mm/filemap.c6
-rw-r--r--mm/nommu.c7
-rw-r--r--mm/page-writeback.c6
-rw-r--r--mm/page_alloc.c5
-rw-r--r--mm/readahead.c1
-rw-r--r--mm/shmem.c4
-rw-r--r--mm/swap_state.c2
-rw-r--r--net/appletalk/ddp.c19
-rw-r--r--net/atm/common.c32
-rw-r--r--net/ax25/af_ax25.c26
-rw-r--r--net/bluetooth/bnep/sock.c32
-rw-r--r--net/bluetooth/cmtp/sock.c30
-rw-r--r--net/bluetooth/hci_sock.c33
-rw-r--r--net/bluetooth/hidp/sock.c24
-rw-r--r--net/bluetooth/l2cap.c36
-rw-r--r--net/bluetooth/rfcomm/sock.c34
-rw-r--r--net/bluetooth/sco.c44
-rw-r--r--net/core/sock.c219
-rw-r--r--net/decnet/af_decnet.c28
-rw-r--r--net/econet/af_econet.c20
-rw-r--r--net/ipv4/af_inet.c24
-rw-r--r--net/ipv4/devinet.c6
-rw-r--r--net/ipv4/ipcomp.c26
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c16
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/syncookies.c5
-rw-r--r--net/ipv4/tcp_ipv4.c2
-rw-r--r--net/ipv4/tcp_minisocks.c6
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/af_inet6.c38
-rw-r--r--net/ipv6/ipcomp6.c14
-rw-r--r--net/ipv6/raw.c4
-rw-r--r--net/ipv6/tcp_ipv6.c2
-rw-r--r--net/ipv6/udp.c4
-rw-r--r--net/ipx/af_ipx.c28
-rw-r--r--net/irda/af_irda.c20
-rw-r--r--net/key/af_key.c39
-rw-r--r--net/llc/af_llc.c28
-rw-r--r--net/llc/llc_conn.c8
-rw-r--r--net/netlink/af_netlink.c39
-rw-r--r--net/netrom/af_netrom.c32
-rw-r--r--net/packet/af_packet.c22
-rw-r--r--net/rose/af_rose.c27
-rw-r--r--net/sched/sch_api.c41
-rw-r--r--net/sched/sch_netem.c49
-rw-r--r--net/sctp/ipv6.c14
-rw-r--r--net/sctp/protocol.c12
-rw-r--r--net/sctp/socket.c4
-rw-r--r--net/socket.c5
-rw-r--r--net/unix/af_unix.c34
-rw-r--r--net/unix/garbage.c2
-rw-r--r--net/wanrouter/af_wanpipe.c25
-rw-r--r--net/x25/af_x25.c20
-rw-r--r--net/xfrm/xfrm_policy.c17
-rw-r--r--net/xfrm/xfrm_state.c48
386 files changed, 8590 insertions, 3561 deletions
diff --git a/Documentation/SubmittingDrivers b/Documentation/SubmittingDrivers
index 2630629d7ab56d..de3b252e717d0f 100644
--- a/Documentation/SubmittingDrivers
+++ b/Documentation/SubmittingDrivers
@@ -118,13 +118,18 @@ Linux kernel mailing list:
linux-kernel@vger.kernel.org
[mail majordomo@vger.kernel.org to subscribe]
+Linux Device Drivers, Third Edition (covers 2.6.10):
+ http://lwn.net/Kernel/LDD3/ (free version)
+
Kernel traffic:
Weekly summary of kernel list activity (much easier to read)
http://www.kerneltraffic.org/kernel-traffic/
LWN.net:
Weekly summary of kernel development activity - http://lwn.net/
- 2.6 driver porting information:
+ 2.6 API changes:
+ http://lwn.net/Articles/2.6-kernel-api/
+ Porting drivers from prior kernels to 2.6:
http://lwn.net/Articles/driver-porting/
KernelTrap:
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index 488792243d15b9..1ad26d2c20ae61 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -261,6 +261,14 @@ that has had all its allowed CPUs or Memory Nodes taken offline. User
code should reconfigure cpusets to only refer to online CPUs and Memory
Nodes when using hotplug to add or remove such resources.
+There is a second exception to the above. GFP_ATOMIC requests are
+kernel internal allocations that must be satisfied, immediately.
+The kernel may drop some request, in rare cases even panic, if a
+GFP_ATOMIC alloc fails. If the request cannot be satisfied within
+the current tasks cpuset, then we relax the cpuset, and look for
+memory anywhere we can find it. It's better to violate the cpuset
+than stress the kernel.
+
To start a new job that is to be contained within a cpuset, the steps are:
1) mkdir /dev/cpuset
diff --git a/Documentation/i2c/busses/i2c-ali1535 b/Documentation/i2c/busses/i2c-ali1535
new file mode 100644
index 00000000000000..0db3b4c74ad111
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-ali1535
@@ -0,0 +1,42 @@
+Kernel driver i2c-ali1535
+
+Supported adapters:
+ * Acer Labs, Inc. ALI 1535 (south bridge)
+ Datasheet: Now under NDA
+ http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ Dan Eaton <dan.eaton@rocketlogix.com>,
+ Stephen Rousset<stephen.rousset@rocketlogix.com>
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1535 South Bridge.
+
+The M1535 is a South bridge for portable systems. It is very similar to the
+M15x3 South bridges also produced by Acer Labs Inc. Some of the registers
+within the part have moved and some have been redefined slightly.
+Additionally, the sequencing of the SMBus transactions has been modified to
+be more consistent with the sequencing recommended by the manufacturer and
+observed through testing. These changes are reflected in this driver and
+can be identified by comparing this driver to the i2c-ali15x3 driver. For
+an overview of these chips see http://www.acerlabs.com
+
+The SMB controller is part of the M7101 device, which is an ACPI-compliant
+Power Management Unit (PMU).
+
+The whole M7101 device has to be enabled for the SMB to work. You can't
+just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
+We make sure that the SMB is enabled. We leave the ACPI alone.
+
+
+Features
+--------
+
+This driver controls the SMB Host only. This driver does not use
+interrupts.
diff --git a/Documentation/i2c/busses/i2c-ali1563 b/Documentation/i2c/busses/i2c-ali1563
new file mode 100644
index 00000000000000..99ad4b9bcc32ec
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-ali1563
@@ -0,0 +1,27 @@
+Kernel driver i2c-ali1563
+
+Supported adapters:
+ * Acer Labs, Inc. ALI 1563 (south bridge)
+ Datasheet: Now under NDA
+ http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Author: Patrick Mochel <mochel@digitalimplant.org>
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1563 South Bridge.
+
+For an overview of these chips see http://www.acerlabs.com
+
+The M1563 southbridge is deceptively similar to the M1533, with a few
+notable exceptions. One of those happens to be the fact they upgraded the
+i2c core to be SMBus 2.0 compliant, and happens to be almost identical to
+the i2c controller found in the Intel 801 south bridges.
+
+Features
+--------
+
+This driver controls the SMB Host only. This driver does not use
+interrupts.
diff --git a/Documentation/i2c/busses/i2c-ali15x3 b/Documentation/i2c/busses/i2c-ali15x3
new file mode 100644
index 00000000000000..ff28d381bebe8d
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-ali15x3
@@ -0,0 +1,112 @@
+Kernel driver i2c-ali15x3
+
+Supported adapters:
+ * Acer Labs, Inc. ALI 1533 and 1543C (south bridge)
+ Datasheet: Now under NDA
+ http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Module Parameters
+-----------------
+
+* force_addr: int
+ Initialize the base address of the i2c controller
+
+
+Notes
+-----
+
+The force_addr parameter is useful for boards that don't set the address in
+the BIOS. Does not do a PCI force; the device must still be present in
+lspci. Don't use this unless the driver complains that the base address is
+not set.
+
+Example: 'modprobe i2c-ali15x3 force_addr=0xe800'
+
+SMBus periodically hangs on ASUS P5A motherboards and can only be cleared
+by a power cycle. Cause unknown (see Issues below).
+
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1541 and M1543C South Bridges.
+
+The M1543C is a South bridge for desktop systems.
+The M1541 is a South bridge for portable systems.
+They are part of the following ALI chipsets:
+
+ * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and
+ 100MHz CPU Front Side bus
+ * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz
+ CPU Front Side bus
+ Some Aladdin V motherboards:
+ Asus P5A
+ Atrend ATC-5220
+ BCM/GVC VP1541
+ Biostar M5ALA
+ Gigabyte GA-5AX (** Generally doesn't work because the BIOS doesn't
+ enable the 7101 device! **)
+ Iwill XA100 Plus
+ Micronics C200
+ Microstar (MSI) MS-5169
+
+ * "Aladdin IV" includes the M1541 Socket 7 North bridge
+ with host bus up to 83.3 MHz.
+
+For an overview of these chips see http://www.acerlabs.com. At this time the
+full data sheets on the web site are password protected, however if you
+contact the ALI office in San Jose they may give you the password.
+
+The M1533/M1543C devices appear as FOUR separate devices on the PCI bus. An
+output of lspci will show something similar to the following:
+
+ 00:02.0 USB Controller: Acer Laboratories Inc. M5237 (rev 03)
+ 00:03.0 Bridge: Acer Laboratories Inc. M7101 <= THIS IS THE ONE WE NEED
+ 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 (rev c3)
+ 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 (rev c1)
+
+** IMPORTANT **
+** If you have a M1533 or M1543C on the board and you get
+** "ali15x3: Error: Can't detect ali15x3!"
+** then run lspci.
+** If you see the 1533 and 5229 devices but NOT the 7101 device,
+** then you must enable ACPI, the PMU, SMB, or something similar
+** in the BIOS.
+** The driver won't work if it can't find the M7101 device.
+
+The SMB controller is part of the M7101 device, which is an ACPI-compliant
+Power Management Unit (PMU).
+
+The whole M7101 device has to be enabled for the SMB to work. You can't
+just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
+We make sure that the SMB is enabled. We leave the ACPI alone.
+
+Features
+--------
+
+This driver controls the SMB Host only. The SMB Slave
+controller on the M15X3 is not enabled. This driver does not use
+interrupts.
+
+
+Issues
+------
+
+This driver requests the I/O space for only the SMB
+registers. It doesn't use the ACPI region.
+
+On the ASUS P5A motherboard, there are several reports that
+the SMBus will hang and this can only be resolved by
+powering off the computer. It appears to be worse when the board
+gets hot, for example under heavy CPU load, or in the summer.
+There may be electrical problems on this board.
+On the P5A, the W83781D sensor chip is on both the ISA and
+SMBus. Therefore the SMBus hangs can generally be avoided
+by accessing the W83781D on the ISA bus only.
+
diff --git a/Documentation/i2c/busses/i2c-amd756 b/Documentation/i2c/busses/i2c-amd756
new file mode 100644
index 00000000000000..67f30874d0bfbd
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-amd756
@@ -0,0 +1,25 @@
+Kernel driver i2c-amd756
+
+Supported adapters:
+ * AMD 756
+ * AMD 766
+ * AMD 768
+ * AMD 8111
+ Datasheets: Publicly available on AMD website
+
+ * nVidia nForce
+ Datasheet: Unavailable
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver supports the AMD 756, 766, 768 and 8111 Peripheral Bus
+Controllers, and the nVidia nForce.
+
+Note that for the 8111, there are two SMBus adapters. The SMBus 1.0 adapter
+is supported by this driver, and the SMBus 2.0 adapter is supported by the
+i2c-amd8111 driver.
diff --git a/Documentation/i2c/busses/i2c-amd8111 b/Documentation/i2c/busses/i2c-amd8111
new file mode 100644
index 00000000000000..db294ee7455a44
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-amd8111
@@ -0,0 +1,41 @@
+Kernel driver i2c-adm8111
+
+Supported adapters:
+ * AMD-8111 SMBus 2.0 PCI interface
+
+Datasheets:
+ AMD datasheet not yet available, but almost everything can be found
+ in publically available ACPI 2.0 specification, which the adapter
+ follows.
+
+Author: Vojtech Pavlik <vojtech@suse.cz>
+
+Description
+-----------
+
+If you see something like this:
+
+00:07.2 SMBus: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 (rev 02)
+ Subsystem: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0
+ Flags: medium devsel, IRQ 19
+ I/O ports at d400 [size=32]
+
+in your 'lspci -v', then this driver is for your chipset.
+
+Process Call Support
+--------------------
+
+Supported.
+
+SMBus 2.0 Support
+-----------------
+
+Supported. Both PEC and block process call support is implemented. Slave
+mode or host notification are not yet implemented.
+
+Notes
+-----
+
+Note that for the 8111, there are two SMBus adapters. The SMBus 2.0 adapter
+is supported by this driver, and the SMBus 1.0 adapter is supported by the
+i2c-amd756 driver.
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
new file mode 100644
index 00000000000000..fd4b2712d570a9
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-i801
@@ -0,0 +1,80 @@
+Kernel driver i2c-i801
+
+Supported adapters:
+ * Intel 82801AA and 82801AB (ICH and ICH0 - part of the
+ '810' and '810E' chipsets)
+ * Intel 82801BA (ICH2 - part of the '815E' chipset)
+ * Intel 82801CA/CAM (ICH3)
+ * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported)
+ * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
+ * Intel 6300ESB
+ * Intel 82801FB/FR/FW/FRW (ICH6)
+ * Intel ICH7
+ Datasheets: Publicly available at the Intel website
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark Studebaker <mdsxyz123@yahoo.com>
+
+
+Module Parameters
+-----------------
+
+* force_addr: int
+ Forcibly enable the ICH at the given address. EXTREMELY DANGEROUS!
+
+
+Description
+-----------
+
+The ICH (properly known as the 82801AA), ICH0 (82801AB), ICH2 (82801BA),
+ICH3 (82801CA/CAM) and later devices are Intel chips that are a part of
+Intel's '810' chipset for Celeron-based PCs, '810E' chipset for
+Pentium-based PCs, '815E' chipset, and others.
+
+The ICH chips contain at least SEVEN separate PCI functions in TWO logical
+PCI devices. An output of lspci will show something similar to the
+following:
+
+ 00:1e.0 PCI bridge: Intel Corporation: Unknown device 2418 (rev 01)
+ 00:1f.0 ISA bridge: Intel Corporation: Unknown device 2410 (rev 01)
+ 00:1f.1 IDE interface: Intel Corporation: Unknown device 2411 (rev 01)
+ 00:1f.2 USB Controller: Intel Corporation: Unknown device 2412 (rev 01)
+ 00:1f.3 Unknown class [0c05]: Intel Corporation: Unknown device 2413 (rev 01)
+
+The SMBus controller is function 3 in device 1f. Class 0c05 is SMBus Serial
+Controller.
+
+If you do NOT see the 24x3 device at function 3, and you can't figure out
+any way in the BIOS to enable it,
+
+The ICH chips are quite similar to Intel's PIIX4 chip, at least in the
+SMBus controller.
+
+See the file i2c-piix4 for some additional information.
+
+
+Process Call Support
+--------------------
+
+Not supported.
+
+
+I2C Block Read Support
+----------------------
+
+Not supported at the moment.
+
+
+SMBus 2.0 Support
+-----------------
+
+The 82801DB (ICH4) and later chips support several SMBus 2.0 features.
+
+**********************
+The lm_sensors project gratefully acknowledges the support of Texas
+Instruments in the initial development of this driver.
+
+The lm_sensors project gratefully acknowledges the support of Intel in the
+development of SMBus 2.0 / ICH4 features of this driver.
diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810
new file mode 100644
index 00000000000000..0544eb3328879c
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-i810
@@ -0,0 +1,46 @@
+Kernel driver i2c-i810
+
+Supported adapters:
+ * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Ralph Metzler <rjkm@thp.uni-koeln.de>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Main contact: Mark Studebaker <mdsxyz123@yahoo.com>
+
+Description
+-----------
+
+WARNING: If you have an '810' or '815' motherboard, your standard I2C
+temperature sensors are most likely on the 801's I2C bus. You want the
+i2c-i801 driver for those, not this driver.
+
+Now for the i2c-i810...
+
+The GMCH chip contains two I2C interfaces.
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org .
+
+The second interface is a general-purpose I2C bus. It may be connected to a
+TV-out chip such as the BT869 or possibly to a digital flat-panel display.
+
+Features
+--------
+
+Both busses use the i2c-algo-bit driver for 'bit banging'
+and support for specific transactions is provided by i2c-algo-bit.
+
+Issues
+------
+
+If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1),
+the test may fail; if so, the i2c-i810 driver won't be inserted. However,
+we think this has been fixed.
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
new file mode 100644
index 00000000000000..e379e182e64f4f
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -0,0 +1,41 @@
+Kernel driver i2c-nforce2
+
+Supported adapters:
+ * nForce2 MCP 10de:0064
+ * nForce2 Ultra 400 MCP 10de:0084
+ * nForce3 Pro150 MCP 10de:00D4
+ * nForce3 250Gb MCP 10de:00E4
+ * nForce4 MCP 10de:0052
+
+Datasheet: not publically available, but seems to be similar to the
+ AMD-8111 SMBus 2.0 adapter.
+
+Authors:
+ Hans-Frieder Vogt <hfvogt@arcor.de>,
+ Thomas Leibold <thomas@plx.com>,
+ Patrick Dreker <patrick@dreker.de>
+
+Description
+-----------
+
+i2c-nforce2 is a driver for the SMBuses included in the nVidia nForce2 MCP.
+
+If your 'lspci -v' listing shows something like the following,
+
+00:01.1 SMBus: nVidia Corporation: Unknown device 0064 (rev a2)
+ Subsystem: Asustek Computer, Inc.: Unknown device 0c11
+ Flags: 66Mhz, fast devsel, IRQ 5
+ I/O ports at c000 [size=32]
+ Capabilities: <available only to root>
+
+then this driver should support the SMBuses of your motherboard.
+
+
+Notes
+-----
+
+The SMBus adapter in the nForce2 chipset seems to be very similar to the
+SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get
+the driver to work with direct I/O access, which is different to the EC
+interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the
+Asus A7N8X lists two SMBuses, both of which are supported by this driver.
diff --git a/Documentation/i2c/i2c-parport b/Documentation/i2c/busses/i2c-parport
index d359461ce9b239..9f1d0082da18b4 100644
--- a/Documentation/i2c/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -1,8 +1,6 @@
-==================
-i2c-parport driver
-==================
+Kernel driver i2c-parport
-2004-07-06, Jean Delvare
+Author: Jean Delvare <khali@linux-fr.org>
This is a unified driver for several i2c-over-parallel-port adapters,
such as the ones made by Philips, Velleman or ELV. This driver is
@@ -126,14 +124,14 @@ adapters do, so you won't even have to change the code.
Similar (but different) drivers
-------------------------------
-This driver is NOT the same as the i2c-pport driver found in the i2c package.
-The i2c-pport driver makes use of modern parallel port features so that
-you don't need additional electronics. It has other restrictions however, and
-was not ported to Linux 2.6 (yet).
+This driver is NOT the same as the i2c-pport driver found in the i2c
+package. The i2c-pport driver makes use of modern parallel port features so
+that you don't need additional electronics. It has other restrictions
+however, and was not ported to Linux 2.6 (yet).
This driver is also NOT the same as the i2c-pcf-epp driver found in the
-lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port
-as an I2C bus directly. Instead, it uses it to control an external I2C bus
+lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port as
+an I2C bus directly. Instead, it uses it to control an external I2C bus
master. That driver was not ported to Linux 2.6 (yet) either.
diff --git a/Documentation/i2c/busses/i2c-parport-light b/Documentation/i2c/busses/i2c-parport-light
new file mode 100644
index 00000000000000..287436478520a0
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-parport-light
@@ -0,0 +1,11 @@
+Kernel driver i2c-parport-light
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+This driver is a light version of i2c-parport. It doesn't depend
+on the parport driver, and uses direct I/O access instead. This might be
+prefered on embedded systems where wasting memory for the clean but heavy
+parport handling is not an option. The drawback is a reduced portability
+and the impossibility to daisy-chain other parallel port devices.
+
+Please see i2c-parport for documentation.
diff --git a/Documentation/i2c/busses/i2c-pca-isa b/Documentation/i2c/busses/i2c-pca-isa
new file mode 100644
index 00000000000000..6fc8f4c27c3ce5
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-pca-isa
@@ -0,0 +1,23 @@
+Kernel driver i2c-pca-isa
+
+Supported adapters:
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
+
+Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems
+
+Module Parameters
+-----------------
+
+* base int
+ I/O base address
+* irq int
+ IRQ interrupt
+* clock int
+ Clock rate as described in table 1 of PCA9564 datasheet
+
+Description
+-----------
+
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
new file mode 100644
index 00000000000000..856b4b8b962ccc
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -0,0 +1,72 @@
+Kernel driver i2c-piix4
+
+Supported adapters:
+ * Intel 82371AB PIIX4 and PIIX4E
+ * Intel 82443MX (440MX)
+ Datasheet: Publicly available at the Intel website
+ * ServerWorks OSB4, CSB5 and CSB6 southbridges
+ Datasheet: Only available via NDA from ServerWorks
+ * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
+ Datasheet: Publicly available at the SMSC website http://www.smsc.com
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>
+ Philip Edelbrock <phil@netroedge.com>
+
+
+Module Parameters
+-----------------
+
+* force: int
+ Forcibly enable the PIIX4. DANGEROUS!
+* force_addr: int
+ Forcibly enable the PIIX4 at the given address. EXTREMELY DANGEROUS!
+* fix_hstcfg: int
+ Fix config register. Needed on some boards (Force CPCI735).
+
+
+Description
+-----------
+
+The PIIX4 (properly known as the 82371AB) is an Intel chip with a lot of
+functionality. Among other things, it implements the PCI bus. One of its
+minor functions is implementing a System Management Bus. This is a true
+SMBus - you can not access it on I2C levels. The good news is that it
+natively understands SMBus commands and you do not have to worry about
+timing problems. The bad news is that non-SMBus devices connected to it can
+confuse it mightily. Yes, this is known to happen...
+
+Do 'lspci -v' and see whether it contains an entry like this:
+
+0000:00:02.3 Bridge: Intel Corp. 82371AB/EB/MB PIIX4 ACPI (rev 02)
+ Flags: medium devsel, IRQ 9
+
+Bus and device numbers may differ, but the function number must be
+identical (like many PCI devices, the PIIX4 incorporates a number of
+different 'functions', which can be considered as separate devices). If you
+find such an entry, you have a PIIX4 SMBus controller.
+
+On some computers (most notably, some Dells), the SMBus is disabled by
+default. If you use the insmod parameter 'force=1', the kernel module will
+try to enable it. THIS IS VERY DANGEROUS! If the BIOS did not set up a
+correct address for this module, you could get in big trouble (read:
+crashes, data corruption, etc.). Try this only as a last resort (try BIOS
+updates first, for example), and backup first! An even more dangerous
+option is 'force_addr=<IOPORT>'. This will not only enable the PIIX4 like
+'force' foes, but it will also set a new base I/O port address. The SMBus
+parts of the PIIX4 needs a range of 8 of these addresses to function
+correctly. If these addresses are already reserved by some other device,
+you will get into big trouble! DON'T USE THIS IF YOU ARE NOT VERY SURE
+ABOUT WHAT YOU ARE DOING!
+
+The PIIX4E is just an new version of the PIIX4; it is supported as well.
+The PIIX/PIIX3 does not implement an SMBus or I2C bus, so you can't use
+this driver on those mainboards.
+
+The ServerWorks Southbridges, the Intel 440MX, and the Victory766 are
+identical to the PIIX4 in I2C/SMBus support.
+
+A few OSB4 southbridges are known to be misconfigured by the BIOS. In this
+case, you have you use the fix_hstcfg module parameter. Do not use it
+unless you know you have to, because in some cases it also breaks
+configuration on southbridges that don't need it.
diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage
new file mode 100644
index 00000000000000..7036879025110f
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-prosavage
@@ -0,0 +1,23 @@
+Kernel driver i2c-prosavage
+
+Supported adapters:
+
+ S3/VIA KM266/VT8375 aka ProSavage8
+ S3/VIA KM133/VT8365 aka Savage4
+
+Author: Henk Vergonet <henk@god.dyndns.org>
+
+Description
+-----------
+
+The Savage4 chips contain two I2C interfaces (aka a I2C 'master' or
+'host').
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org . The second interface is a general-purpose I2C bus.
+
+Usefull for gaining access to the TV Encoder chips.
+
diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4
new file mode 100644
index 00000000000000..6ecceab618d397
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-savage4
@@ -0,0 +1,26 @@
+Kernel driver i2c-savage4
+
+Supported adapters:
+ * Savage4
+ * Savage2000
+
+Authors:
+ Alexander Wold <awold@bigfoot.com>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Description
+-----------
+
+The Savage4 chips contain two I2C interfaces (aka a I2C 'master'
+or 'host').
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org . The DDC bus is not yet supported because its register
+is not directly memory-mapped.
+
+The second interface is a general-purpose I2C bus. This is the only
+interface supported by the driver at the moment.
+
diff --git a/Documentation/i2c/busses/i2c-sis5595 b/Documentation/i2c/busses/i2c-sis5595
new file mode 100644
index 00000000000000..cc47db7d00a989
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-sis5595
@@ -0,0 +1,59 @@
+Kernel driver i2c-sis5595
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ Philip Edelbrock <phil@netroedge.com>
+
+Supported adapters:
+ * Silicon Integrated Systems Corp. SiS5595 Southbridge
+ Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
+
+Note: all have mfr. ID 0x1039.
+
+ SUPPORTED PCI ID
+ 5595 0008
+
+ Note: these chips contain a 0008 device which is incompatible with the
+ 5595. We recognize these by the presence of the listed
+ "blacklist" PCI ID and refuse to load.
+
+ NOT SUPPORTED PCI ID BLACKLIST PCI ID
+ 540 0008 0540
+ 550 0008 0550
+ 5513 0008 5511
+ 5581 0008 5597
+ 5582 0008 5597
+ 5597 0008 5597
+ 5598 0008 5597/5598
+ 630 0008 0630
+ 645 0008 0645
+ 646 0008 0646
+ 648 0008 0648
+ 650 0008 0650
+ 651 0008 0651
+ 730 0008 0730
+ 735 0008 0735
+ 745 0008 0745
+ 746 0008 0746
+
+Module Parameters
+-----------------
+
+* force_addr=0xaddr Set the I/O base address. Useful for boards
+ that don't set the address in the BIOS. Does not do a
+ PCI force; the device must still be present in lspci.
+ Don't use this unless the driver complains that the
+ base address is not set.
+
+Description
+-----------
+
+i2c-sis5595 is a true SMBus host driver for motherboards with the SiS5595
+southbridges.
+
+WARNING: If you are trying to access the integrated sensors on the SiS5595
+chip, you want the sis5595 driver for those, not this driver. This driver
+is a BUS driver, not a CHIP driver. A BUS driver is used by other CHIP
+drivers to access chips on the bus.
+
diff --git a/Documentation/i2c/busses/i2c-sis630 b/Documentation/i2c/busses/i2c-sis630
new file mode 100644
index 00000000000000..9aca6889f748e2
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-sis630
@@ -0,0 +1,49 @@
+Kernel driver i2c-sis630
+
+Supported adapters:
+ * Silicon Integrated Systems Corp (SiS)
+ 630 chipset (Datasheet: available at http://amalysh.bei.t-online.de/docs/SIS/)
+ 730 chipset
+ * Possible other SiS chipsets ?
+
+Author: Alexander Malysh <amalysh@web.de>
+
+Module Parameters
+-----------------
+
+* force = [1|0] Forcibly enable the SIS630. DANGEROUS!
+ This can be interesting for chipsets not named
+ above to check if it works for you chipset, but DANGEROUS!
+
+* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,
+ what your BIOS use). DANGEROUS! This should be a bit
+ faster, but freeze some systems (i.e. my Laptop).
+
+
+Description
+-----------
+
+This SMBus only driver is known to work on motherboards with the above
+named chipsets.
+
+If you see something like this:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 31)
+00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+
+or like this:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02)
+00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+
+in your 'lspci' output , then this driver is for your chipset.
+
+Thank You
+---------
+Philip Edelbrock <phil@netroedge.com>
+- testing SiS730 support
+Mark M. Hoffman <mhoffman@lightlink.com>
+- bug fixes
+
+To anyone else which I forgot here ;), thanks!
+
diff --git a/Documentation/i2c/busses/i2c-sis69x b/Documentation/i2c/busses/i2c-sis69x
new file mode 100644
index 00000000000000..5be48769f65bdd
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-sis69x
@@ -0,0 +1,73 @@
+Kernel driver i2c-sis96x
+
+Replaces 2.4.x i2c-sis645
+
+Supported adapters:
+ * Silicon Integrated Systems Corp (SiS)
+ Any combination of these host bridges:
+ 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746
+ and these south bridges:
+ 961, 962, 963(L)
+
+Author: Mark M. Hoffman <mhoffman@lightlink.com>
+
+Description
+-----------
+
+This SMBus only driver is known to work on motherboards with the above
+named chipset combinations. The driver was developed without benefit of a
+proper datasheet from SiS. The SMBus registers are assumed compatible with
+those of the SiS630, although they are located in a completely different
+place. Thanks to Alexander Malysh <amalysh@web.de> for providing the
+SiS630 datasheet (and driver).
+
+The command "lspci" as root should produce something like these lines:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
+00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
+
+or perhaps this...
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
+00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961
+00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
+
+(kernel versions later than 2.4.18 may fill in the "Unknown"s)
+
+If you cant see it please look on quirk_sis_96x_smbus
+(drivers/pci/quirks.c) (also if southbridge detection fails)
+
+I suspect that this driver could be made to work for the following SiS
+chipsets as well: 635, and 635T. If anyone owns a board with those chips
+AND is willing to risk crashing & burning an otherwise well-behaved kernel
+in the name of progress... please contact me at <mhoffman@lightlink.com> or
+via the project's mailing list: <sensors@stimpy.netroedge.com>. Please
+send bug reports and/or success stories as well.
+
+
+TO DOs
+------
+
+* The driver does not support SMBus block reads/writes; I may add them if a
+scenario is found where they're needed.
+
+
+Thank You
+---------
+
+Mark D. Studebaker <mdsxyz123@yahoo.com>
+ - design hints and bug fixes
+Alexander Maylsh <amalysh@web.de>
+ - ditto, plus an important datasheet... almost the one I really wanted
+Hans-Günter Lütke Uphues <hg_lu@t-online.de>
+ - patch for SiS735
+Robert Zwerus <arzie@dds.nl>
+ - testing for SiS645DX
+Kianusch Sayah Karadji <kianusch@sk-tech.net>
+ - patch for SiS645DX/962
+Ken Healy
+ - patch for SiS655
+
+To anyone else who has written w/ feedback, thanks!
+
diff --git a/Documentation/i2c/busses/i2c-via b/Documentation/i2c/busses/i2c-via
new file mode 100644
index 00000000000000..55edfe1a640be0
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-via
@@ -0,0 +1,34 @@
+Kernel driver i2c-via
+
+Supported adapters:
+ * VIA Technologies, InC. VT82C586B
+ Datasheet: Publicly available at the VIA website
+
+Author: Kyösti Mälkki <kmalkki@cc.hut.fi>
+
+Description
+-----------
+
+i2c-via is an i2c bus driver for motherboards with VIA chipset.
+
+The following VIA pci chipsets are supported:
+ - MVP3, VP3, VP2/97, VPX/97
+ - others with South bridge VT82C586B
+
+Your lspci listing must show this :
+
+ Bridge: VIA Technologies, Inc. VT82C586B ACPI (rev 10)
+
+ Problems?
+
+ Q: You have VT82C586B on the motherboard, but not in the listing.
+
+ A: Go to your BIOS setup, section PCI devices or similar.
+ Turn USB support on, and try again.
+
+ Q: No error messages, but still i2c doesn't seem to work.
+
+ A: This can happen. This driver uses the pins VIA recommends in their
+ datasheets, but there are several ways the motherboard manufacturer
+ can actually wire the lines.
+
diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro
new file mode 100644
index 00000000000000..702f5ac68c09d8
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-viapro
@@ -0,0 +1,47 @@
+Kernel driver i2c-viapro
+
+Supported adapters:
+ * VIA Technologies, Inc. VT82C596A/B
+ Datasheet: Sometimes available at the VIA website
+
+ * VIA Technologies, Inc. VT82C686A/B
+ Datasheet: Sometimes available at the VIA website
+
+ * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237
+ Datasheet: available on request from Via
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Module Parameters
+-----------------
+
+* force: int
+ Forcibly enable the SMBus controller. DANGEROUS!
+* force_addr: int
+ Forcibly enable the SMBus at the given address. EXTREMELY DANGEROUS!
+
+Description
+-----------
+
+i2c-viapro is a true SMBus host driver for motherboards with one of the
+supported VIA southbridges.
+
+Your lspci -n listing must show one of these :
+
+ device 1106:3050 (VT82C596 function 3)
+ device 1106:3051 (VT82C596 function 3)
+ device 1106:3057 (VT82C686 function 4)
+ device 1106:3074 (VT8233)
+ device 1106:3147 (VT8233A)
+ device 1106:8235 (VT8231)
+ devide 1106:3177 (VT8235)
+ devide 1106:3227 (VT8237)
+
+If none of these show up, you should look in the BIOS for settings like
+enable ACPI / SMBus or even USB.
+
+
diff --git a/Documentation/i2c/busses/i2c-voodoo3 b/Documentation/i2c/busses/i2c-voodoo3
new file mode 100644
index 00000000000000..62d90a454d399d
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-voodoo3
@@ -0,0 +1,62 @@
+Kernel driver i2c-voodoo3
+
+Supported adapters:
+ * 3dfx Voodoo3 based cards
+ * Voodoo Banshee based cards
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Ralph Metzler <rjkm@thp.uni-koeln.de>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Main contact: Philip Edelbrock <phil@netroedge.com>
+
+The code is based upon Ralph's test code (he did the hard stuff ;')
+
+Description
+-----------
+
+The 3dfx Voodoo3 chip contains two I2C interfaces (aka a I2C 'master' or
+'host').
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org .
+
+The second interface is a general-purpose I2C bus. The intent by 3dfx was
+to allow manufacturers to add extra chips to the video card such as a
+TV-out chip such as the BT869 or possibly even I2C based temperature
+sensors like the ADM1021 or LM75.
+
+Stability
+---------
+
+Seems to be stable on the test machine, but needs more testing on other
+machines. Simultaneous accesses of the DDC and I2C busses may cause errors.
+
+Supported Devices
+-----------------
+
+Specifically, this driver was written and tested on the '3dfx Voodoo3 AGP
+3000' which has a tv-out feature (s-video or composite). According to the
+docs and discussions, this code should work for any Voodoo3 based cards as
+well as Voodoo Banshee based cards. The DDC interface has been tested on a
+Voodoo Banshee card.
+
+Issues
+------
+
+Probably many, but it seems to work OK on my system. :')
+
+
+External Device Connection
+--------------------------
+
+The digital video input jumpers give availability to the I2C bus.
+Specifically, pins 13 and 25 (bottom row middle, and bottom right-end) are
+the I2C clock and I2C data lines, respectively. +5V and GND are probably
+also easily available making the addition of extra I2C/SMBus devices easy
+to implement.
diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb
new file mode 100644
index 00000000000000..08c8cd1df60c50
--- /dev/null
+++ b/Documentation/i2c/busses/scx200_acb
@@ -0,0 +1,14 @@
+Kernel driver scx200_acb
+
+Author: Christer Weinigel <wingel@nano-system.com>
+
+Module Parameters
+-----------------
+
+* base: int
+ Base addresses for the ACCESS.bus controllers
+
+Description
+-----------
+
+Enable the use of the ACCESS.bus controllers of a SCx200 processor.
diff --git a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
index cffca06ad4cefd..cb89fb3b61efd2 100644
--- a/Documentation/kernel-docs.txt
+++ b/Documentation/kernel-docs.txt
@@ -39,6 +39,13 @@
ON-LINE DOCS:
+ * Title: "Linux Device Drivers, Third Edition"
+ Author: Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
+ URL: http://lwn.net/Kernel/LDD3/
+ Description: A 600-page book covering the (2.6.10) driver
+ programming API and kernel hacking in general. Available under the
+ Creative Commons Attribution-ShareAlike 2.0 license.
+
* Title: "The Linux Kernel"
Author: David A. Rusling.
URL: http://www.tldp.org/LDP/tlk/tlk.html
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 53b58a6ace67ec..da711028e5f712 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -1,23 +1,22 @@
+NOTE: ksymoops is useless on 2.6. Please use the Oops in its original format
+(from dmesg, etc). Ignore any references in this or other docs to "decoding
+the Oops" or "running it through ksymoops". If you post an Oops fron 2.6 that
+has been run through ksymoops, people will just tell you to repost it.
+
Quick Summary
-------------
-Install ksymoops from
-ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops
-Read the ksymoops man page.
-ksymoops < the_oops.txt
-
-and send the output the maintainer of the kernel area that seems to be
-involved with the problem, not to the ksymoops maintainer. Don't worry
-too much about getting the wrong person. If you are unsure send it to
-the person responsible for the code relevant to what you were doing.
-If it occurs repeatably try and describe how to recreate it. Thats
-worth even more than the oops
+Find the Oops and send it to the maintainer of the kernel area that seems to be
+involved with the problem. Don't worry too much about getting the wrong person.
+If you are unsure send it to the person responsible for the code relevant to
+what you were doing. If it occurs repeatably try and describe how to recreate
+it. That's worth even more than the oops.
If you are totally stumped as to whom to send the report, send it to
linux-kernel@vger.kernel.org. Thanks for your help in making Linux as
stable as humanly possible.
-Where is the_oops.txt?
+Where is the Oops?
----------------------
Normally the Oops text is read from the kernel buffers by klogd and
@@ -43,15 +42,14 @@ the disk is not available then you have three options :-
them yourself. Search kernel archives for kmsgdump, lkcd and
oops+smram.
-No matter how you capture the log output, feed the resulting file to
-ksymoops along with /proc/ksyms and /proc/modules that applied at the
-time of the crash. /var/log/ksymoops can be useful to capture the
-latter, man ksymoops for details.
-
Full Information
----------------
+NOTE: the message from Linus below applies to 2.4 kernel. I have preserved it
+for historical reasons, and because some of the information in it still
+applies. Especially, please ignore any references to ksymoops.
+
From: Linus Torvalds <torvalds@osdl.org>
How to track down an Oops.. [originally a mail to linux-kernel]
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index a1d3ec6292a995..f98c2e31c143e6 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -92,6 +92,8 @@ On all - write a character to /proc/sysrq-trigger. eg:
it so that only emergency messages like PANICs or OOPSes would
make it to your console.)
+'f' - Will call oom_kill to kill a memory hog process
+
'e' - Send a SIGTERM to all processes, except for init.
'i' - Send a SIGKILL to all processes, except for init.
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 9ba4979188a820..ef6865f0b9792a 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -65,9 +65,6 @@ static void __init setup_uclinux_memory(void);
#ifdef CONFIG_CONSOLE
extern struct consw *conswitchp;
-#ifdef CONFIG_FRAMEBUFFER
-extern struct consw fb_con;
-#endif
#endif
#ifdef CONFIG_MB93090_MB00
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index 0b7e2d381a3ebd..28bb0514bb6e1c 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -8,7 +8,7 @@
#include <linux/acpi.h>
#include <linux/bootmem.h>
#include <asm/smp.h>
-
+#include <asm/tlbflush.h>
/* address in low memory of the wakeup routine. */
unsigned long acpi_wakeup_address = 0;
@@ -27,6 +27,7 @@ static void init_low_mapping(pgd_t *pgd, int pgd_limit)
set_pgd(pgd, *(pgd+USER_PTRS_PER_PGD));
pgd_ofs++, pgd++;
}
+ flush_tlb_all();
}
/**
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 190e3feeba6d5c..ebd5d8247faaee 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -21,6 +21,9 @@
DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
+DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
+EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
+
static int cachesize_override __initdata = -1;
static int disable_x86_fxsr __initdata = 0;
static int disable_x86_serial_nr __initdata = 1;
@@ -546,6 +549,7 @@ void __init cpu_init (void)
int cpu = smp_processor_id();
struct tss_struct * t = &per_cpu(init_tss, cpu);
struct thread_struct *thread = &current->thread;
+ __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
if (cpu_test_and_set(cpu, cpu_initialized)) {
printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
@@ -568,6 +572,13 @@ void __init cpu_init (void)
*/
memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
GDT_SIZE);
+
+ /* Set up GDT entry for 16bit stack */
+ *(__u64 *)&(per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_ESPFIX_SS]) |=
+ ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) |
+ ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
+ (CPU_16BIT_STACK_SIZE - 1);
+
cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
cpu_gdt_descr[cpu].address =
(unsigned long)&per_cpu(cpu_gdt_table, cpu);
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index d7c8f7b9f72a57..7d1d350bf87e8c 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -1,5 +1,18 @@
+/*
+ * Routines to indentify caches on Intel CPU.
+ *
+ * Changes:
+ * Venkatesh Pallipadi : Adding cache identification through cpuid(4)
+ */
+
#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/compiler.h>
+#include <linux/cpu.h>
+
#include <asm/processor.h>
+#include <asm/smp.h>
#define LVL_1_INST 1
#define LVL_1_DATA 2
@@ -58,10 +71,142 @@ static struct _cache_table cache_table[] __initdata =
{ 0x00, 0, 0}
};
+
+enum _cache_type
+{
+ CACHE_TYPE_NULL = 0,
+ CACHE_TYPE_DATA = 1,
+ CACHE_TYPE_INST = 2,
+ CACHE_TYPE_UNIFIED = 3
+};
+
+union _cpuid4_leaf_eax {
+ struct {
+ enum _cache_type type:5;
+ unsigned int level:3;
+ unsigned int is_self_initializing:1;
+ unsigned int is_fully_associative:1;
+ unsigned int reserved:4;
+ unsigned int num_threads_sharing:12;
+ unsigned int num_cores_on_die:6;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ebx {
+ struct {
+ unsigned int coherency_line_size:12;
+ unsigned int physical_line_partition:10;
+ unsigned int ways_of_associativity:10;
+ } split;
+ u32 full;
+};
+
+union _cpuid4_leaf_ecx {
+ struct {
+ unsigned int number_of_sets:32;
+ } split;
+ u32 full;
+};
+
+struct _cpuid4_info {
+ union _cpuid4_leaf_eax eax;
+ union _cpuid4_leaf_ebx ebx;
+ union _cpuid4_leaf_ecx ecx;
+ unsigned long size;
+ cpumask_t shared_cpu_map;
+};
+
+#define MAX_CACHE_LEAVES 4
+static unsigned short __devinitdata num_cache_leaves;
+
+static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
+{
+ unsigned int eax, ebx, ecx, edx;
+ union _cpuid4_leaf_eax cache_eax;
+
+ cpuid_count(4, index, &eax, &ebx, &ecx, &edx);
+ cache_eax.full = eax;
+ if (cache_eax.split.type == CACHE_TYPE_NULL)
+ return -1;
+
+ this_leaf->eax.full = eax;
+ this_leaf->ebx.full = ebx;
+ this_leaf->ecx.full = ecx;
+ this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) *
+ (this_leaf->ebx.split.coherency_line_size + 1) *
+ (this_leaf->ebx.split.physical_line_partition + 1) *
+ (this_leaf->ebx.split.ways_of_associativity + 1);
+ return 0;
+}
+
+static int __init find_num_cache_leaves(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+ union _cpuid4_leaf_eax cache_eax;
+ int i;
+ int retval;
+
+ retval = MAX_CACHE_LEAVES;
+ /* Do cpuid(4) loop to find out num_cache_leaves */
+ for (i = 0; i < MAX_CACHE_LEAVES; i++) {
+ cpuid_count(4, i, &eax, &ebx, &ecx, &edx);
+ cache_eax.full = eax;
+ if (cache_eax.split.type == CACHE_TYPE_NULL) {
+ retval = i;
+ break;
+ }
+ }
+ return retval;
+}
+
unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
+ unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
+ unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
+
+ if (c->cpuid_level > 4) {
+ static int is_initialized;
+
+ if (is_initialized == 0) {
+ /* Init num_cache_leaves from boot CPU */
+ num_cache_leaves = find_num_cache_leaves();
+ is_initialized++;
+ }
+
+ /*
+ * Whenever possible use cpuid(4), deterministic cache
+ * parameters cpuid leaf to find the cache details
+ */
+ for (i = 0; i < num_cache_leaves; i++) {
+ struct _cpuid4_info this_leaf;
+
+ int retval;
+ retval = cpuid4_cache_lookup(i, &this_leaf);
+ if (retval >= 0) {
+ switch(this_leaf.eax.split.level) {
+ case 1:
+ if (this_leaf.eax.split.type ==
+ CACHE_TYPE_DATA)
+ new_l1d = this_leaf.size/1024;
+ else if (this_leaf.eax.split.type ==
+ CACHE_TYPE_INST)
+ new_l1i = this_leaf.size/1024;
+ break;
+ case 2:
+ new_l2 = this_leaf.size/1024;
+ break;
+ case 3:
+ new_l3 = this_leaf.size/1024;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
if (c->cpuid_level > 1) {
/* supports eax=2 call */
int i, j, n;
@@ -114,6 +259,18 @@ unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
}
}
+ if (new_l1d)
+ l1d = new_l1d;
+
+ if (new_l1i)
+ l1i = new_l1i;
+
+ if (new_l2)
+ l2 = new_l2;
+
+ if (new_l3)
+ l3 = new_l3;
+
if ( trace )
printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
else if ( l1i )
@@ -138,3 +295,302 @@ unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
return l2;
}
+
+/* pointer to _cpuid4_info array (for each cache leaf) */
+static struct _cpuid4_info *cpuid4_info[NR_CPUS];
+#define CPUID4_INFO_IDX(x,y) (&((cpuid4_info[x])[y]))
+
+#ifdef CONFIG_SMP
+static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+{
+ struct _cpuid4_info *this_leaf;
+ unsigned long num_threads_sharing;
+
+ this_leaf = CPUID4_INFO_IDX(cpu, index);
+ num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
+
+ if (num_threads_sharing == 1)
+ cpu_set(cpu, this_leaf->shared_cpu_map);
+ else if (num_threads_sharing == smp_num_siblings)
+ this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
+ else
+ printk(KERN_INFO "Number of CPUs sharing cache didn't match "
+ "any known set of CPUs\n");
+}
+#else
+static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
+#endif
+
+static void free_cache_attributes(unsigned int cpu)
+{
+ kfree(cpuid4_info[cpu]);
+ cpuid4_info[cpu] = NULL;
+}
+
+static int __devinit detect_cache_attributes(unsigned int cpu)
+{
+ struct _cpuid4_info *this_leaf;
+ unsigned long j;
+ int retval;
+
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+ cpuid4_info[cpu] = kmalloc(
+ sizeof(struct _cpuid4_info) * num_cache_leaves, GFP_KERNEL);
+ if (unlikely(cpuid4_info[cpu] == NULL))
+ return -ENOMEM;
+ memset(cpuid4_info[cpu], 0,
+ sizeof(struct _cpuid4_info) * num_cache_leaves);
+
+ /* Do cpuid and store the results */
+ for (j = 0; j < num_cache_leaves; j++) {
+ this_leaf = CPUID4_INFO_IDX(cpu, j);
+ retval = cpuid4_cache_lookup(j, this_leaf);
+ if (unlikely(retval < 0))
+ goto err_out;
+ cache_shared_cpu_map_setup(cpu, j);
+ }
+ return 0;
+
+err_out:
+ free_cache_attributes(cpu);
+ return -ENOMEM;
+}
+
+#ifdef CONFIG_SYSFS
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+extern struct sysdev_class cpu_sysdev_class; /* from drivers/base/cpu.c */
+
+/* pointer to kobject for cpuX/cache */
+static struct kobject * cache_kobject[NR_CPUS];
+
+struct _index_kobject {
+ struct kobject kobj;
+ unsigned int cpu;
+ unsigned short index;
+};
+
+/* pointer to array of kobjects for cpuX/cache/indexY */
+static struct _index_kobject *index_kobject[NR_CPUS];
+#define INDEX_KOBJECT_PTR(x,y) (&((index_kobject[x])[y]))
+
+#define show_one_plus(file_name, object, val) \
+static ssize_t show_##file_name \
+ (struct _cpuid4_info *this_leaf, char *buf) \
+{ \
+ return sprintf (buf, "%lu\n", (unsigned long)this_leaf->object + val); \
+}
+
+show_one_plus(level, eax.split.level, 0);
+show_one_plus(coherency_line_size, ebx.split.coherency_line_size, 1);
+show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
+show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
+show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
+
+static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
+{
+ return sprintf (buf, "%luK\n", this_leaf->size / 1024);
+}
+
+static ssize_t show_shared_cpu_map(struct _cpuid4_info *this_leaf, char *buf)
+{
+ char mask_str[NR_CPUS];
+ cpumask_scnprintf(mask_str, NR_CPUS, this_leaf->shared_cpu_map);
+ return sprintf(buf, "%s\n", mask_str);
+}
+
+static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf) {
+ switch(this_leaf->eax.split.type) {
+ case CACHE_TYPE_DATA:
+ return sprintf(buf, "Data\n");
+ break;
+ case CACHE_TYPE_INST:
+ return sprintf(buf, "Instruction\n");
+ break;
+ case CACHE_TYPE_UNIFIED:
+ return sprintf(buf, "Unified\n");
+ break;
+ default:
+ return sprintf(buf, "Unknown\n");
+ break;
+ }
+}
+
+struct _cache_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct _cpuid4_info *, char *);
+ ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
+};
+
+#define define_one_ro(_name) \
+static struct _cache_attr _name = \
+ __ATTR(_name, 0444, show_##_name, NULL)
+
+define_one_ro(level);
+define_one_ro(type);
+define_one_ro(coherency_line_size);
+define_one_ro(physical_line_partition);
+define_one_ro(ways_of_associativity);
+define_one_ro(number_of_sets);
+define_one_ro(size);
+define_one_ro(shared_cpu_map);
+
+static struct attribute * default_attrs[] = {
+ &type.attr,
+ &level.attr,
+ &coherency_line_size.attr,
+ &physical_line_partition.attr,
+ &ways_of_associativity.attr,
+ &number_of_sets.attr,
+ &size.attr,
+ &shared_cpu_map.attr,
+ NULL
+};
+
+#define to_object(k) container_of(k, struct _index_kobject, kobj)
+#define to_attr(a) container_of(a, struct _cache_attr, attr)
+
+static ssize_t show(struct kobject * kobj, struct attribute * attr, char * buf)
+{
+ struct _cache_attr *fattr = to_attr(attr);
+ struct _index_kobject *this_leaf = to_object(kobj);
+ ssize_t ret;
+
+ ret = fattr->show ?
+ fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
+ buf) :
+ 0;
+ return ret;
+}
+
+static ssize_t store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count)
+{
+ return 0;
+}
+
+static struct sysfs_ops sysfs_ops = {
+ .show = show,
+ .store = store,
+};
+
+static struct kobj_type ktype_cache = {
+ .sysfs_ops = &sysfs_ops,
+ .default_attrs = default_attrs,
+};
+
+static struct kobj_type ktype_percpu_entry = {
+ .sysfs_ops = &sysfs_ops,
+};
+
+static void cpuid4_cache_sysfs_exit(unsigned int cpu)
+{
+ kfree(cache_kobject[cpu]);
+ kfree(index_kobject[cpu]);
+ cache_kobject[cpu] = NULL;
+ index_kobject[cpu] = NULL;
+ free_cache_attributes(cpu);
+}
+
+static int __devinit cpuid4_cache_sysfs_init(unsigned int cpu)
+{
+
+ if (num_cache_leaves == 0)
+ return -ENOENT;
+
+ detect_cache_attributes(cpu);
+ if (cpuid4_info[cpu] == NULL)
+ return -ENOENT;
+
+ /* Allocate all required memory */
+ cache_kobject[cpu] = kmalloc(sizeof(struct kobject), GFP_KERNEL);
+ if (unlikely(cache_kobject[cpu] == NULL))
+ goto err_out;
+ memset(cache_kobject[cpu], 0, sizeof(struct kobject));
+
+ index_kobject[cpu] = kmalloc(
+ sizeof(struct _index_kobject ) * num_cache_leaves, GFP_KERNEL);
+ if (unlikely(index_kobject[cpu] == NULL))
+ goto err_out;
+ memset(index_kobject[cpu], 0,
+ sizeof(struct _index_kobject) * num_cache_leaves);
+
+ return 0;
+
+err_out:
+ cpuid4_cache_sysfs_exit(cpu);
+ return -ENOMEM;
+}
+
+/* Add/Remove cache interface for CPU device */
+static int __devinit cache_add_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i, j;
+ struct _index_kobject *this_object;
+ int retval = 0;
+
+ retval = cpuid4_cache_sysfs_init(cpu);
+ if (unlikely(retval < 0))
+ return retval;
+
+ cache_kobject[cpu]->parent = &sys_dev->kobj;
+ kobject_set_name(cache_kobject[cpu], "%s", "cache");
+ cache_kobject[cpu]->ktype = &ktype_percpu_entry;
+ retval = kobject_register(cache_kobject[cpu]);
+
+ for (i = 0; i < num_cache_leaves; i++) {
+ this_object = INDEX_KOBJECT_PTR(cpu,i);
+ this_object->cpu = cpu;
+ this_object->index = i;
+ this_object->kobj.parent = cache_kobject[cpu];
+ kobject_set_name(&(this_object->kobj), "index%1lu", i);
+ this_object->kobj.ktype = &ktype_cache;
+ retval = kobject_register(&(this_object->kobj));
+ if (unlikely(retval)) {
+ for (j = 0; j < i; j++) {
+ kobject_unregister(
+ &(INDEX_KOBJECT_PTR(cpu,j)->kobj));
+ }
+ kobject_unregister(cache_kobject[cpu]);
+ cpuid4_cache_sysfs_exit(cpu);
+ break;
+ }
+ }
+ return retval;
+}
+
+static int __devexit cache_remove_dev(struct sys_device * sys_dev)
+{
+ unsigned int cpu = sys_dev->id;
+ unsigned long i;
+
+ for (i = 0; i < num_cache_leaves; i++)
+ kobject_unregister(&(INDEX_KOBJECT_PTR(cpu,i)->kobj));
+ kobject_unregister(cache_kobject[cpu]);
+ cpuid4_cache_sysfs_exit(cpu);
+ return 0;
+}
+
+static struct sysdev_driver cache_sysdev_driver = {
+ .add = cache_add_dev,
+ .remove = __devexit_p(cache_remove_dev),
+};
+
+/* Register/Unregister the cpu_cache driver */
+static int __devinit cache_register_driver(void)
+{
+ if (num_cache_leaves == 0)
+ return 0;
+
+ return sysdev_driver_register(&cpu_sysdev_class,&cache_sysdev_driver);
+}
+
+device_initcall(cache_register_driver);
+
+#endif
+
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 87aad70d373021..1e45ff292bc99d 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -47,6 +47,7 @@
#include <asm/segment.h>
#include <asm/smp.h>
#include <asm/page.h>
+#include <asm/desc.h>
#include "irq_vectors.h"
#define nr_syscalls ((syscall_table_size)/4)
@@ -78,7 +79,7 @@ VM_MASK = 0x00020000
#define preempt_stop cli
#else
#define preempt_stop
-#define resume_kernel restore_all
+#define resume_kernel restore_nocheck
#endif
#define SAVE_ALL \
@@ -122,24 +123,6 @@ VM_MASK = 0x00020000
.previous
-#define RESTORE_ALL \
- RESTORE_REGS \
- addl $4, %esp; \
-1: iret; \
-.section .fixup,"ax"; \
-2: sti; \
- movl $(__USER_DS), %edx; \
- movl %edx, %ds; \
- movl %edx, %es; \
- movl $11,%eax; \
- call do_exit; \
-.previous; \
-.section __ex_table,"a";\
- .align 4; \
- .long 1b,2b; \
-.previous
-
-
ENTRY(ret_from_fork)
pushl %eax
call schedule_tail
@@ -163,7 +146,7 @@ ret_from_intr:
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
testl $(VM_MASK | 3), %eax
- jz resume_kernel # returning to kernel or vm86-space
+ jz resume_kernel
ENTRY(resume_userspace)
cli # make sure we don't miss an interrupt
# setting need_resched or sigpending
@@ -178,7 +161,7 @@ ENTRY(resume_userspace)
ENTRY(resume_kernel)
cli
cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ?
- jnz restore_all
+ jnz restore_nocheck
need_resched:
movl TI_flags(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl
@@ -259,8 +242,56 @@ syscall_exit:
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work
+
restore_all:
- RESTORE_ALL
+ movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
+ movb OLDSS(%esp), %ah
+ movb CS(%esp), %al
+ andl $(VM_MASK | (4 << 8) | 3), %eax
+ cmpl $((4 << 8) | 3), %eax
+ je ldt_ss # returning to user-space with LDT SS
+restore_nocheck:
+ RESTORE_REGS
+ addl $4, %esp
+1: iret
+.section .fixup,"ax"
+iret_exc:
+ sti
+ movl $__USER_DS, %edx
+ movl %edx, %ds
+ movl %edx, %es
+ movl $11,%eax
+ call do_exit
+.previous
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
+
+ldt_ss:
+ larl OLDSS(%esp), %eax
+ jnz restore_nocheck
+ testl $0x00400000, %eax # returning to 32bit stack?
+ jnz restore_nocheck # allright, normal return
+ /* If returning to userspace with 16bit stack,
+ * try to fix the higher word of ESP, as the CPU
+ * won't restore it.
+ * This is an "official" bug of all the x86-compatible
+ * CPUs, which we can try to work around to make
+ * dosemu and wine happy. */
+ subl $8, %esp # reserve space for switch16 pointer
+ cli
+ movl %esp, %eax
+ /* Set up the 16bit stack frame with switch32 pointer on top,
+ * and a switch16 pointer on top of the current frame. */
+ call setup_x86_bogus_stack
+ RESTORE_REGS
+ lss 20+4(%esp), %esp # switch to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
# perform work that needs to be done immediately before resumption
ALIGN
@@ -336,6 +367,27 @@ syscall_badsys:
movl $-ENOSYS,EAX(%esp)
jmp resume_userspace
+#define FIXUP_ESPFIX_STACK \
+ movl %esp, %eax; \
+ /* switch to 32bit stack using the pointer on top of 16bit stack */ \
+ lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \
+ /* copy data from 16bit stack to 32bit stack */ \
+ call fixup_x86_bogus_stack; \
+ /* put ESP to the proper location */ \
+ movl %eax, %esp;
+#define UNWIND_ESPFIX_STACK \
+ pushl %eax; \
+ movl %ss, %eax; \
+ /* see if on 16bit stack */ \
+ cmpw $__ESPFIX_SS, %ax; \
+ jne 28f; \
+ movl $__KERNEL_DS, %edx; \
+ movl %edx, %ds; \
+ movl %edx, %es; \
+ /* switch to 32bit stack */ \
+ FIXUP_ESPFIX_STACK \
+28: popl %eax;
+
/*
* Build the entry stubs and pointer table with
* some assembler magic.
@@ -390,7 +442,9 @@ error_code:
pushl %ecx
pushl %ebx
cld
- movl %es, %ecx
+ pushl %es
+ UNWIND_ESPFIX_STACK
+ popl %ecx
movl ES(%esp), %edi # get the function address
movl ORIG_EAX(%esp), %edx # get the error code
movl %eax, ORIG_EAX(%esp)
@@ -472,6 +526,11 @@ debug_stack_correct:
* fault happened on the sysenter path.
*/
ENTRY(nmi)
+ pushl %eax
+ movl %ss, %eax
+ cmpw $__ESPFIX_SS, %ax
+ popl %eax
+ je nmi_16bit_stack
cmpl $sysenter_entry,(%esp)
je nmi_stack_fixup
pushl %eax
@@ -491,7 +550,7 @@ nmi_stack_correct:
xorl %edx,%edx # zero error code
movl %esp,%eax # pt_regs pointer
call do_nmi
- RESTORE_ALL
+ jmp restore_all
nmi_stack_fixup:
FIX_STACK(12,nmi_stack_correct, 1)
@@ -507,6 +566,29 @@ nmi_debug_stack_fixup:
FIX_STACK(24,nmi_stack_correct, 1)
jmp nmi_stack_correct
+nmi_16bit_stack:
+ /* create the pointer to lss back */
+ pushl %ss
+ pushl %esp
+ movzwl %sp, %esp
+ addw $4, (%esp)
+ /* copy the iret frame of 12 bytes */
+ .rept 3
+ pushl 16(%esp)
+ .endr
+ pushl %eax
+ SAVE_ALL
+ FIXUP_ESPFIX_STACK # %eax == %esp
+ xorl %edx,%edx # zero error code
+ call do_nmi
+ RESTORE_REGS
+ lss 12+4(%esp), %esp # back to 16bit stack
+1: iret
+.section __ex_table,"a"
+ .align 4
+ .long 1b,iret_exc
+.previous
+
ENTRY(int3)
pushl $-1 # mark this as an int
SAVE_ALL
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index ea1ef3a32ec5bc..d273fd74619211 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -512,7 +512,7 @@ ENTRY(cpu_gdt_table)
.quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
.quad 0x0040920000000000 /* 0xc8 APM DS data */
- .quad 0x0000000000000000 /* 0xd0 - unused */
+ .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
.quad 0x0000000000000000 /* 0xd8 - unused */
.quad 0x0000000000000000 /* 0xe0 - unused */
.quad 0x0000000000000000 /* 0xe8 - unused */
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index f74b755704c4c0..67168165924346 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -84,7 +84,11 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
- regs->eip = (unsigned long)&p->ainsn.insn;
+ /*single step inline if the instruction is an int3*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->eip = (unsigned long)p->addr;
+ else
+ regs->eip = (unsigned long)&p->ainsn.insn;
}
/*
@@ -117,6 +121,12 @@ static int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->eflags &= ~TF_MASK;
+ regs->eflags |= kprobe_saved_eflags;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -159,17 +169,16 @@ static int kprobe_handler(struct pt_regs *regs)
if (is_IF_modifier(p->opcode))
kprobe_saved_eflags &= ~IF_MASK;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
- ss_probe:
+ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
return 1;
- no_kprobe:
+no_kprobe:
preempt_enable_no_resched();
return ret;
}
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 90cfff176251e1..c36fedf40e9580 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -73,7 +73,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
void disable_hlt(void)
{
@@ -146,15 +146,14 @@ static void poll_idle (void)
*/
void cpu_idle (void)
{
- int cpu = _smp_processor_id();
-
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
void (*idle)(void);
- if (cpu_isset(cpu, cpu_idle_map))
- cpu_clear(cpu, cpu_idle_map);
+ if (__get_cpu_var(cpu_idle_state))
+ __get_cpu_var(cpu_idle_state) = 0;
+
rmb();
idle = pm_idle;
@@ -170,16 +169,28 @@ void cpu_idle (void)
void cpu_idle_wait(void)
{
- int cpu;
+ unsigned int cpu, this_cpu = get_cpu();
cpumask_t map;
- for_each_online_cpu(cpu)
- cpu_set(cpu, cpu_idle_map);
+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ put_cpu();
+
+ cpus_clear(map);
+ for_each_online_cpu(cpu) {
+ per_cpu(cpu_idle_state, cpu) = 1;
+ cpu_set(cpu, map);
+ }
+
+ __get_cpu_var(cpu_idle_state) = 0;
wmb();
do {
ssleep(1);
- cpus_and(map, cpu_idle_map, cpu_online_map);
+ for_each_online_cpu(cpu) {
+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+ cpu_clear(cpu, map);
+ }
+ cpus_and(map, map, cpu_online_map);
} while (!cpus_empty(map));
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 0ac1d19c7739f0..6223c33ac91cc6 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -188,7 +188,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
local_irq_restore(flags);
}
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
+void send_IPI_mask_sequence(cpumask_t mask, int vector)
{
unsigned long cfg, flags;
unsigned int query_cpu;
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 7b5b97f209b7f3..6c0e383915b6a0 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -887,6 +887,51 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
#endif
}
+fastcall void setup_x86_bogus_stack(unsigned char * stk)
+{
+ unsigned long *switch16_ptr, *switch32_ptr;
+ struct pt_regs *regs;
+ unsigned long stack_top, stack_bot;
+ unsigned short iret_frame16_off;
+ int cpu = smp_processor_id();
+ /* reserve the space on 32bit stack for the magic switch16 pointer */
+ memmove(stk, stk + 8, sizeof(struct pt_regs));
+ switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
+ regs = (struct pt_regs *)stk;
+ /* now the switch32 on 16bit stack */
+ stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+ stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
+ switch32_ptr = (unsigned long *)(stack_top - 8);
+ iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
+ /* copy iret frame on 16bit stack */
+ memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
+ /* fill in the switch pointers */
+ switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
+ switch16_ptr[1] = __ESPFIX_SS;
+ switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
+ 8 - CPU_16BIT_STACK_SIZE;
+ switch32_ptr[1] = __KERNEL_DS;
+}
+
+fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
+{
+ unsigned long *switch32_ptr;
+ unsigned char *stack16, *stack32;
+ unsigned long stack_top, stack_bot;
+ int len;
+ int cpu = smp_processor_id();
+ stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
+ stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
+ switch32_ptr = (unsigned long *)(stack_top - 8);
+ /* copy the data from 16bit stack to 32bit stack */
+ len = CPU_16BIT_STACK_SIZE - 8 - sp;
+ stack16 = (unsigned char *)(stack_bot + sp);
+ stack32 = (unsigned char *)
+ (switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len);
+ memcpy(stack32, stack16, len);
+ return stack32;
+}
+
/*
* 'math_state_restore()' saves the current math information in the
* old math state array, and gets the new ones from the current task
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index a337879e981da8..33fcb205fcb7ad 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -169,6 +169,7 @@ config NUMA
bool "NUMA support"
depends on !IA64_HP_SIM
default y if IA64_SGI_SN2
+ select ACPI_NUMA
help
Say Y to compile the kernel to support NUMA (Non-Uniform Memory
Access). This option is for configuring high-end multiprocessor
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index ca062b9628ab3c..a8e99c56a76894 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -771,7 +771,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-#ifdef CONFIG_NUMA
+#ifdef CONFIG_ACPI_NUMA
acpi_status __init
acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
{
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 111dad9175ba10..c15be5c38f5605 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -91,7 +91,6 @@
#undef DEBUG_INTERRUPT_ROUTING
-#undef OVERRIDE_DEBUG
#ifdef DEBUG_INTERRUPT_ROUTING
#define DBG(fmt...) printk(fmt)
@@ -499,14 +498,14 @@ get_target_cpu (unsigned int gsi, int vector)
* distribute interrupts.
*/
if (smp_int_redirect & SMP_IRQ_REDIRECTION)
- return hard_smp_processor_id();
+ return cpu_physical_id(smp_processor_id());
/*
* Some interrupts (ACPI SCI, for instance) are registered
* before the BSP is marked as online.
*/
if (!cpu_online(smp_processor_id()))
- return hard_smp_processor_id();
+ return cpu_physical_id(smp_processor_id());
#ifdef CONFIG_NUMA
{
@@ -553,7 +552,7 @@ skip_numa_setup:
return cpu_physical_id(cpu);
#else
- return hard_smp_processor_id();
+ return cpu_physical_id(smp_processor_id());
#endif
}
@@ -740,7 +739,7 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
unsigned long trigger)
{
int vector;
- unsigned int dest = hard_smp_processor_id();
+ unsigned int dest = cpu_physical_id(smp_processor_id());
vector = isa_irq_to_vector(isa_irq);
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index b3ed949a4f8609..d9c05d53435bd1 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -957,6 +957,8 @@ END(ia64_syscall_setup)
* element, followed by the arguments.
*/
ENTRY(dispatch_illegal_op_fault)
+ .prologue
+ .body
SAVE_MIN_WITH_COVER
ssm psr.ic | PSR_DEFAULT_BITS
;;
@@ -969,6 +971,7 @@ ENTRY(dispatch_illegal_op_fault)
mov out0=ar.ec
;;
SAVE_REST
+ PT_REGS_UNWIND_INFO(0)
;;
br.call.sptk.many rp=ia64_illegal_op_fault
.ret0: ;;
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index a01c2cd060380b..1dbc7b2497c90d 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -26,7 +26,7 @@
(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
;; \
(pUStk) mov r18=ar.bsp; \
-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
+(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */
#define MINSTATE_END_SAVE_MIN_VIRT \
bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 9891effcf4c3cb..f05650c801d2a4 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -646,6 +646,15 @@ cpu_init (void)
ia64_set_kr(IA64_KR_FPU_OWNER, 0);
/*
+ * Initialize the page-table base register to a global
+ * directory with all zeroes. This ensure that we can handle
+ * TLB-misses to user address-space even before we created the
+ * first user address-space. This may happen, e.g., due to
+ * aggressive use of lfetch.fault.
+ */
+ ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page)));
+
+ /*
* Initialize default control register to defer all speculative faults. The
* kernel MUST NOT depend on a particular setting of these bits (in other words,
* the kernel must have recovery code for all speculative accesses). Turn on
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index 46dad0d215a3dc..43b45b65ee5a9d 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -1380,6 +1380,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
* - ldX.spill
* - stX.spill
* Reason: RNATs are based on addresses
+ * - ld16
+ * - st16
+ * Reason: ld16 and st16 are supposed to occur in a single
+ * memory op
*
* synchronization:
* - cmpxchg
@@ -1401,6 +1405,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
switch (opcode) {
case LDS_OP:
case LDSA_OP:
+ if (u.insn.x)
+ /* oops, really a semaphore op (cmpxchg, etc) */
+ goto failure;
+ /* no break */
case LDS_IMM_OP:
case LDSA_IMM_OP:
case LDFS_OP:
@@ -1425,6 +1433,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
case LDCCLR_OP:
case LDCNC_OP:
case LDCCLRACQ_OP:
+ if (u.insn.x)
+ /* oops, really a semaphore op (cmpxchg, etc) */
+ goto failure;
+ /* no break */
case LD_IMM_OP:
case LDA_IMM_OP:
case LDBIAS_IMM_OP:
@@ -1437,6 +1449,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
case ST_OP:
case STREL_OP:
+ if (u.insn.x)
+ /* oops, really a semaphore op (cmpxchg, etc) */
+ goto failure;
+ /* no break */
case ST_IMM_OP:
case STREL_IMM_OP:
ret = emulate_store_int(ifa, u.insn, regs);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 61d8dd3c9c93a0..88641e5095b5f9 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -178,30 +178,6 @@ alloc_pci_controller (int seg)
return controller;
}
-static int __devinit
-alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end,
- unsigned long flags)
-{
- struct resource *res;
-
- res = kmalloc(sizeof(*res), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
- memset(res, 0, sizeof(*res));
- res->name = name;
- res->start = start;
- res->end = end;
- res->flags = flags;
-
- if (insert_resource(root, res)) {
- kfree(res);
- return -EBUSY;
- }
-
- return 0;
-}
-
static u64 __devinit
add_io_space (struct acpi_resource_address64 *addr)
{
@@ -254,10 +230,9 @@ struct pci_root_info {
char *name;
};
-static acpi_status __devinit
-add_window (struct acpi_resource *res, void *data)
+static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
{
- struct pci_root_info *info = (struct pci_root_info *) data;
+ struct pci_root_info *info = data;
struct pci_window *window;
struct acpi_resource_address64 addr;
acpi_status status;
@@ -265,45 +240,71 @@ add_window (struct acpi_resource *res, void *data)
struct resource *root;
status = acpi_resource_to_address64(res, &addr);
- if (ACPI_SUCCESS(status)) {
- if (!addr.address_length)
- return AE_OK;
-
- if (addr.resource_type == ACPI_MEMORY_RANGE) {
- flags = IORESOURCE_MEM;
- root = &iomem_resource;
- offset = addr.address_translation_offset;
- } else if (addr.resource_type == ACPI_IO_RANGE) {
- flags = IORESOURCE_IO;
- root = &ioport_resource;
- offset = add_io_space(&addr);
- if (offset == ~0)
- return AE_OK;
- } else
+ if (!ACPI_SUCCESS(status))
+ return AE_OK;
+
+ if (!addr.address_length)
+ return AE_OK;
+
+ if (addr.resource_type == ACPI_MEMORY_RANGE) {
+ flags = IORESOURCE_MEM;
+ root = &iomem_resource;
+ offset = addr.address_translation_offset;
+ } else if (addr.resource_type == ACPI_IO_RANGE) {
+ flags = IORESOURCE_IO;
+ root = &ioport_resource;
+ offset = add_io_space(&addr);
+ if (offset == ~0)
return AE_OK;
-
- window = &info->controller->window[info->controller->windows++];
- window->resource.flags = flags;
- window->resource.start = addr.min_address_range;
- window->resource.end = addr.max_address_range;
- window->offset = offset;
-
- if (alloc_resource(info->name, root, addr.min_address_range + offset,
- addr.max_address_range + offset, flags))
- printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n",
- addr.min_address_range + offset, addr.max_address_range + offset,
- root->name, info->name);
+ } else
+ return AE_OK;
+
+ window = &info->controller->window[info->controller->windows++];
+ window->resource.name = info->name;
+ window->resource.flags = flags;
+ window->resource.start = addr.min_address_range + offset;
+ window->resource.end = addr.max_address_range + offset;
+ window->resource.child = NULL;
+ window->offset = offset;
+
+ if (insert_resource(root, &window->resource)) {
+ printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n",
+ window->resource.start, window->resource.end,
+ root->name, info->name);
}
return AE_OK;
}
+static void __devinit
+pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl)
+{
+ int i, j;
+
+ j = 0;
+ for (i = 0; i < ctrl->windows; i++) {
+ struct resource *res = &ctrl->window[i].resource;
+ /* HP's firmware has a hack to work around a Windows bug.
+ * Ignore these tiny memory ranges */
+ if ((res->flags & IORESOURCE_MEM) &&
+ (res->end - res->start < 16))
+ continue;
+ if (j >= PCI_BUS_NUM_RESOURCES) {
+ printk("Ignoring range [%lx-%lx] (%lx)\n", res->start,
+ res->end, res->flags);
+ continue;
+ }
+ bus->resource[j++] = res;
+ }
+}
+
struct pci_bus * __devinit
-pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
+pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
{
struct pci_root_info info;
struct pci_controller *controller;
unsigned int windows = 0;
+ struct pci_bus *pbus;
char *name;
controller = alloc_pci_controller(domain);
@@ -312,8 +313,10 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
controller->acpi_handle = device->handle;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows);
- controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
+ &windows);
+ controller->window = kmalloc(sizeof(*controller->window) * windows,
+ GFP_KERNEL);
if (!controller->window)
goto out2;
@@ -324,9 +327,14 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
sprintf(name, "PCI Bus %04x:%02x", domain, bus);
info.controller = controller;
info.name = name;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, &info);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
+ &info);
+
+ pbus = pci_scan_bus(bus, &pci_root_ops, controller);
+ if (pbus)
+ pcibios_setup_root_windows(pbus, controller);
- return pci_scan_bus(bus, &pci_root_ops, controller);
+ return pbus;
out3:
kfree(controller->window);
@@ -347,9 +355,9 @@ void pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_window *window = &controller->window[i];
if (!(window->resource.flags & res->flags))
continue;
- if (window->resource.start > res->start - window->offset)
+ if (window->resource.start > res->start)
continue;
- if (window->resource.end < res->end - window->offset)
+ if (window->resource.end < res->end)
continue;
offset = window->offset;
break;
@@ -371,9 +379,9 @@ void pcibios_bus_to_resource(struct pci_dev *dev,
struct pci_window *window = &controller->window[i];
if (!(window->resource.flags & res->flags))
continue;
- if (window->resource.start > region->start)
+ if (window->resource.start - window->offset > region->start)
continue;
- if (window->resource.end < region->end)
+ if (window->resource.end - window->offset < region->end)
continue;
offset = window->offset;
break;
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index a852077940fe03..f0306b516afba5 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -67,15 +67,27 @@ extern void snidle(int);
extern unsigned char acpi_kbd_controller_present;
unsigned long sn_rtc_cycles_per_second;
-
EXPORT_SYMBOL(sn_rtc_cycles_per_second);
+DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
+EXPORT_PER_CPU_SYMBOL(__sn_hub_info);
+
partid_t sn_partid = -1;
EXPORT_SYMBOL(sn_partid);
char sn_system_serial_number_string[128];
EXPORT_SYMBOL(sn_system_serial_number_string);
u64 sn_partition_serial_number;
EXPORT_SYMBOL(sn_partition_serial_number);
+u8 sn_partition_id;
+EXPORT_SYMBOL(sn_partition_id);
+u8 sn_system_size;
+EXPORT_SYMBOL(sn_system_size);
+u8 sn_sharing_domain_size;
+EXPORT_SYMBOL(sn_sharing_domain_size);
+u8 sn_coherency_id;
+EXPORT_SYMBOL(sn_coherency_id);
+u8 sn_region_size;
+EXPORT_SYMBOL(sn_region_size);
short physical_node_map[MAX_PHYSNODE_ID];
@@ -232,7 +244,7 @@ static void __init sn_check_for_wars(void)
} else {
for_each_online_node(cnode) {
if (is_shub_1_1(cnodeid_to_nasid(cnode)))
- shub_1_1_found = 1;
+ sn_hub_info->shub_1_1_found = 1;
}
}
}
@@ -424,16 +436,14 @@ void __init sn_cpu_init(void)
int slice;
int cnode;
int i;
- u64 shubtype, nasid_bitmask, nasid_shift;
static int wars_have_been_checked;
memset(pda, 0, sizeof(pda));
- if (ia64_sn_get_hub_info(0, &shubtype, &nasid_bitmask, &nasid_shift))
+ if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift,
+ &sn_system_size, &sn_sharing_domain_size, &sn_partition_id,
+ &sn_coherency_id, &sn_region_size))
BUG();
- pda->shub2 = (u8)shubtype;
- pda->nasid_bitmask = (u16)nasid_bitmask;
- pda->nasid_shift = (u8)nasid_shift;
- pda->as_shift = pda->nasid_shift - 2;
+ sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;
/*
* The boot cpu makes this call again after platform initialization is
@@ -482,7 +492,7 @@ void __init sn_cpu_init(void)
sn_check_for_wars();
wars_have_been_checked = 1;
}
- pda->shub_1_1_found = shub_1_1_found;
+ sn_hub_info->shub_1_1_found = shub_1_1_found;
/*
* Set up addresses of PIO/MEM write status registers.
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index fb03be1a0c94c2..4826cd6e40e8ee 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -7,8 +7,6 @@
* Hitoshi Yamamoto
*/
-/* $Id$ */
-
#include <linux/config.h>
#include <linux/init.h>
#include <linux/stddef.h>
@@ -24,6 +22,9 @@
#include <linux/seq_file.h>
#include <linux/timex.h>
#include <linux/tty.h>
+#include <linux/cpu.h>
+#include <linux/nodemask.h>
+
#include <asm/processor.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -52,7 +53,7 @@ struct cpuinfo_m32r boot_cpu_data;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_image_start; /* starting block # of image */
+extern int rd_image_start; /* starting block # of image */
#endif
#if defined(CONFIG_VGA_CONSOLE)
@@ -273,6 +274,21 @@ void __init setup_arch(char **cmdline_p)
paging_init();
}
+static struct cpu cpu[NR_CPUS];
+
+static int __init topology_init(void)
+{
+ int cpu_id;
+
+ for (cpu_id = 0; cpu_id < NR_CPUS; cpu_id++)
+ if (cpu_possible(cpu_id))
+ register_cpu(&cpu[cpu_id], cpu_id, NULL);
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
+
#ifdef CONFIG_PROC_FS
/*
* Get CPU information for use by the procfs.
@@ -285,7 +301,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
#ifdef CONFIG_SMP
if (!cpu_online(cpu))
return 0;
-#endif /* CONFIG_SMP */
+#endif /* CONFIG_SMP */
seq_printf(m, "processor\t: %ld\n", cpu);
@@ -359,7 +375,7 @@ struct seq_operations cpuinfo_op = {
stop: c_stop,
show: show_cpuinfo,
};
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_PROC_FS */
unsigned long cpu_initialized __initdata = 0;
@@ -399,7 +415,6 @@ void __init cpu_init (void)
#endif
/* Set up ICUIMASK */
- outl(0x00070000, M32R_ICU_IMASK_PORTL); /* imask=111 */
+ outl(0x00070000, M32R_ICU_IMASK_PORTL); /* imask=111 */
}
-#endif /* defined(CONFIG_CHIP_VDEC2) ... */
-
+#endif /* defined(CONFIG_CHIP_VDEC2) ... */
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c
index bf3104a1590878..1d1a01e54b3fa2 100644
--- a/arch/m32r/mm/discontig.c
+++ b/arch/m32r/mm/discontig.c
@@ -11,6 +11,7 @@
#include <linux/bootmem.h>
#include <linux/mmzone.h>
#include <linux/initrd.h>
+#include <linux/nodemask.h>
#include <asm/setup.h>
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 930103cf2b3394..59995a4308683d 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -816,7 +816,7 @@ config MPC10X_BRIDGE
config FSL_OCP
bool
- depends on MPC10X_BRIDGE || PPC_MPC52xx
+ depends on MPC10X_BRIDGE
default y
config MPC10X_OPENPIC
diff --git a/arch/ppc/boot/simple/mpc52xx_tty.c b/arch/ppc/boot/simple/mpc52xx_tty.c
index 5bf4f0c7932234..3acc6b7c0727cc 100644
--- a/arch/ppc/boot/simple/mpc52xx_tty.c
+++ b/arch/ppc/boot/simple/mpc52xx_tty.c
@@ -20,32 +20,31 @@
#include <asm/io.h>
#include <asm/time.h>
-#if MPC52xx_PF_CONSOLE_PORT == 0
-#define MPC52xx_CONSOLE MPC52xx_PSC1
-#define MPC52xx_PSC_CONFIG_SHIFT 0
-#elif MPC52xx_PF_CONSOLE_PORT == 1
-#define MPC52xx_CONSOLE MPC52xx_PSC2
-#define MPC52xx_PSC_CONFIG_SHIFT 4
-#elif MPC52xx_PF_CONSOLE_PORT == 2
-#define MPC52xx_CONSOLE MPC52xx_PSC3
-#define MPC52xx_PSC_CONFIG_SHIFT 8
+
+#ifdef MPC52xx_PF_CONSOLE_PORT
+#define MPC52xx_CONSOLE MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT)
+#define MPC52xx_PSC_CONFIG_SHIFT ((MPC52xx_PF_CONSOLE_PORT-1)<<2)
#else
#error "MPC52xx_PF_CONSOLE_PORT not defined"
#endif
static struct mpc52xx_psc __iomem *psc =
- (struct mpc52xx_psc __iomem *) MPC52xx_CONSOLE;
+ (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE);
/* The decrementer counts at the system bus clock frequency
* divided by four. The most accurate time base is connected to the
- * rtc. We read the decrementer change during one rtc tick (one second)
- * and multiply by 4 to get the system bus clock frequency.
+ * rtc. We read the decrementer change during one rtc tick
+ * and multiply by 4 to get the system bus clock frequency. Since a
+ * rtc tick is one seconds, and that's pretty long, we change the rtc
+ * dividers temporarly to set them 64x faster ;)
*/
static int
mpc52xx_ipbfreq(void)
{
- struct mpc52xx_rtc __iomem *rtc = (struct mpc52xx_rtc __iomem *)MPC52xx_RTC;
- struct mpc52xx_cdm __iomem *cdm = (struct mpc52xx_cdm __iomem *)MPC52xx_CDM;
+ struct mpc52xx_rtc __iomem *rtc =
+ (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET);
+ struct mpc52xx_cdm __iomem *cdm =
+ (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET);
int current_time, previous_time;
int tbl_start, tbl_end;
int xlbfreq, ipbfreq;
@@ -68,7 +67,8 @@ mpc52xx_ipbfreq(void)
unsigned long
serial_init(int ignored, void *ignored2)
{
- struct mpc52xx_gpio __iomem *gpio = (struct mpc52xx_gpio __iomem *)MPC52xx_GPIO;
+ struct mpc52xx_gpio __iomem *gpio =
+ (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET);
int divisor;
int mode1;
int mode2;
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 370ee2a59c1f57..035217d6c0f115 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -45,40 +45,37 @@
#endif
#ifdef CONFIG_BOOKE
-#define COR r8 /* Critical Offset Register (COR) */
-#define BOOKE_LOAD_COR lis COR,crit_save@ha
-#define BOOKE_REST_COR mfspr COR,SPRN_SPRG2
-#define BOOKE_SAVE_COR mtspr SPRN_SPRG2,COR
-#else
-#define COR 0
-#define BOOKE_LOAD_COR
-#define BOOKE_REST_COR
-#define BOOKE_SAVE_COR
-#endif
-
-#ifdef CONFIG_BOOKE
+#include "head_booke.h"
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
- mtspr SPRN_SPRG6W,r8
- lis r8,mcheck_save@ha
- lwz r0,mcheck_r10@l(r8)
+ mtspr MCHECK_SPRG,r8
+ BOOKE_LOAD_MCHECK_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
stw r0,GPR10(r11)
- lwz r0,mcheck_r11@l(r8)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
stw r0,GPR11(r11)
- mfspr r8,SPRN_SPRG6R
+ mfspr r8,MCHECK_SPRG
b transfer_to_handler_full
+
+ .globl crit_transfer_to_handler
+crit_transfer_to_handler:
+ mtspr CRIT_SPRG,r8
+ BOOKE_LOAD_CRIT_STACK
+ lwz r0,GPR10-INT_FRAME_SIZE(r8)
+ stw r0,GPR10(r11)
+ lwz r0,GPR11-INT_FRAME_SIZE(r8)
+ stw r0,GPR11(r11)
+ mfspr r8,CRIT_SPRG
+ /* fall through */
#endif
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_40x
.globl crit_transfer_to_handler
crit_transfer_to_handler:
- BOOKE_SAVE_COR
- BOOKE_LOAD_COR
- lwz r0,crit_r10@l(COR)
+ lwz r0,crit_r10@l(0)
stw r0,GPR10(r11)
- lwz r0,crit_r11@l(COR)
+ lwz r0,crit_r11@l(0)
stw r0,GPR11(r11)
- BOOKE_REST_COR
/* fall through */
#endif
@@ -724,8 +721,6 @@ exc_exit_restart_end:
* We have to restore various SPRs that may have been in use at the
* time of the critical interrupt.
*
- * Note that SPRG6 is used for machine check on CONFIG_BOOKE parts and
- * thus not saved in the critical handler
*/
.globl ret_from_crit_exc
ret_from_crit_exc:
@@ -770,32 +765,9 @@ ret_from_crit_exc:
mtspr SPRN_CSRR1,r12
lwz r9,GPR9(r1)
lwz r12,GPR12(r1)
- BOOKE_SAVE_COR
- BOOKE_LOAD_COR
- lwz r10,crit_sprg0@l(COR)
- mtspr SPRN_SPRG0,r10
- lwz r10,crit_sprg1@l(COR)
- mtspr SPRN_SPRG1,r10
- lwz r10,crit_sprg4@l(COR)
- mtspr SPRN_SPRG4,r10
- lwz r10,crit_sprg5@l(COR)
- mtspr SPRN_SPRG5,r10
-#ifdef CONFIG_40x
- lwz r10,crit_sprg6@l(COR)
- mtspr SPRN_SPRG6,r10
-#endif
- lwz r10,crit_sprg7@l(COR)
- mtspr SPRN_SPRG7,r10
- lwz r10,crit_srr0@l(COR)
- mtspr SPRN_SRR0,r10
- lwz r10,crit_srr1@l(COR)
- mtspr SPRN_SRR1,r10
- lwz r10,crit_pid@l(COR)
- mtspr SPRN_PID,r10
lwz r10,GPR10(r1)
lwz r11,GPR11(r1)
lwz r1,GPR1(r1)
- BOOKE_REST_COR
PPC405_ERR77_SYNC
rfci
b . /* prevent prefetch past rfci */
@@ -839,32 +811,9 @@ ret_from_mcheck_exc:
mtspr SPRN_MCSRR1,r12
lwz r9,GPR9(r1)
lwz r12,GPR12(r1)
- mtspr SPRN_SPRG6W,r8
- lis r8,mcheck_save@ha
- lwz r10,mcheck_sprg0@l(r8)
- mtspr SPRN_SPRG0,r10
- lwz r10,mcheck_sprg1@l(r8)
- mtspr SPRN_SPRG1,r10
- lwz r10,mcheck_sprg4@l(r8)
- mtspr SPRN_SPRG4,r10
- lwz r10,mcheck_sprg5@l(r8)
- mtspr SPRN_SPRG5,r10
- lwz r10,mcheck_sprg7@l(r8)
- mtspr SPRN_SPRG7,r10
- lwz r10,mcheck_srr0@l(r8)
- mtspr SPRN_SRR0,r10
- lwz r10,mcheck_srr1@l(r8)
- mtspr SPRN_SRR1,r10
- lwz r10,mcheck_csrr0@l(r8)
- mtspr SPRN_CSRR0,r10
- lwz r10,mcheck_csrr1@l(r8)
- mtspr SPRN_CSRR1,r10
- lwz r10,mcheck_pid@l(r8)
- mtspr SPRN_PID,r10
lwz r10,GPR10(r1)
lwz r11,GPR11(r1)
lwz r1,GPR1(r1)
- mfspr r8,SPRN_SPRG6R
RFMCI
#endif /* CONFIG_BOOKE */
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index e61f3be049feb7..9ed8165a3d6c62 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -728,78 +728,13 @@ _GLOBAL(empty_zero_page)
_GLOBAL(swapper_pg_dir)
.space 8192
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
.section .bss
-/* Stack for handling critical exceptions from kernel mode */
-critical_stack_bottom:
- .space 4096
-critical_stack_top:
- .previous
-
-/* Stack for handling machine check exceptions from kernel mode */
-mcheck_stack_bottom:
- .space 4096
-mcheck_stack_top:
- .previous
-
-/*
- * This area is used for temporarily saving registers during the
- * critical and machine check exception prologs. It must always
- * follow the page aligned allocations, so it starts on a page
- * boundary, ensuring that all crit_save areas are in a single
- * page.
- */
-
-/* crit_save */
-_GLOBAL(crit_save)
- .space 4
-_GLOBAL(crit_r10)
- .space 4
-_GLOBAL(crit_r11)
- .space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
-
-/* mcheck_save */
-_GLOBAL(mcheck_save)
- .space 4
-_GLOBAL(mcheck_r10)
- .space 4
-_GLOBAL(mcheck_r11)
- .space 4
-_GLOBAL(mcheck_sprg0)
- .space 4
-_GLOBAL(mcheck_sprg1)
- .space 4
-_GLOBAL(mcheck_sprg4)
- .space 4
-_GLOBAL(mcheck_sprg5)
- .space 4
-_GLOBAL(mcheck_sprg7)
- .space 4
-_GLOBAL(mcheck_pid)
- .space 4
-_GLOBAL(mcheck_srr0)
- .space 4
-_GLOBAL(mcheck_srr1)
- .space 4
-_GLOBAL(mcheck_csrr0)
- .space 4
-_GLOBAL(mcheck_csrr1)
- .space 4
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE
+_GLOBAL(exception_stack_top)
/*
* This space gets a copy of optional info passed to us by the bootstrap
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index dd23e90ac81667..6f5d380e234503 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -95,24 +95,6 @@ _GLOBAL(crit_r10)
.space 4
_GLOBAL(crit_r11)
.space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg6)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
/*
* Exception vector entry code. This code runs with address translation
@@ -165,24 +147,6 @@ _GLOBAL(crit_srr1)
#define CRITICAL_EXCEPTION_PROLOG \
stw r10,crit_r10@l(0); /* save two registers to work with */\
stw r11,crit_r11@l(0); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,crit_sprg0@l(0); \
- mfspr r10,SPRN_SPRG1; \
- stw r10,crit_sprg1@l(0); \
- mfspr r10,SPRN_SPRG4; \
- stw r10,crit_sprg4@l(0); \
- mfspr r10,SPRN_SPRG5; \
- stw r10,crit_sprg5@l(0); \
- mfspr r10,SPRN_SPRG6; \
- stw r10,crit_sprg6@l(0); \
- mfspr r10,SPRN_SPRG7; \
- stw r10,crit_sprg7@l(0); \
- mfspr r10,SPRN_PID; \
- stw r10,crit_pid@l(0); \
- mfspr r10,SPRN_SRR0; \
- stw r10,crit_srr0@l(0); \
- mfspr r10,SPRN_SRR1; \
- stw r10,crit_srr1@l(0); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_SRR3; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
@@ -221,9 +185,6 @@ _GLOBAL(crit_srr1)
* r11 saved in crit_r11 and in stack frame,
* now phys stack/exception frame pointer
* r12 saved in stack frame, now saved SRR2
- * SPRG0,1,4,5,6,7 saved in crit_sprg0,1,4,5,6,7
- * PID saved in crit_pid
- * SRR0,1 saved in crit_srr0,1
* CR saved in stack frame, CR0.EQ = !SRR3.PR
* LR, DEAR, ESR in stack frame
* r1 saved in stack frame, now virt stack/excframe pointer
@@ -1030,10 +991,11 @@ _GLOBAL(swapper_pg_dir)
/* Stack for handling critical exceptions from kernel mode */
.section .bss
-critical_stack_bottom:
+ .align 12
+exception_stack_bottom:
.space 4096
critical_stack_top:
- .previous
+_GLOBAL(exception_stack_top)
/* This space gets a copy of optional info passed to us by the bootstrap
* which is used to pass parameters into the kernel like root=/dev/sda1, etc.
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
index b69813a9f9e93f..884dac916bce77 100644
--- a/arch/ppc/kernel/head_booke.h
+++ b/arch/ppc/kernel/head_booke.h
@@ -22,7 +22,7 @@
lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\
addi r1,r1,THREAD_SIZE; \
1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\
- tophys(r11,r1); \
+ mr r11,r1; \
stw r10,_CCR(r11); /* save various registers */\
stw r12,GPR12(r11); \
stw r9,GPR9(r11); \
@@ -42,45 +42,71 @@
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
+/* To handle the additional exception priority levels on 40x and Book-E
+ * processors we allocate a 4k stack per additional priority level. The various
+ * head_xxx.S files allocate space (exception_stack_top) for each priority's
+ * stack times the number of CPUs
+ *
+ * On 40x critical is the only additional level
+ * On 44x/e500 we have critical and machine check
+ *
+ * Additionally we reserve a SPRG for each priority level so we can free up a
+ * GPR to use as the base for indirect access to the exception stacks. This
+ * is necessary since the MMU is always on, for Book-E parts, and the stacks
+ * are offset from KERNELBASE.
+ *
+ */
+#define BOOKE_EXCEPTION_STACK_SIZE (8192)
+
+/* CRIT_SPRG only used in critical exception handling */
+#define CRIT_SPRG SPRN_SPRG2
+/* MCHECK_SPRG only used in critical exception handling */
+#define MCHECK_SPRG SPRN_SPRG6W
+
+#define MCHECK_STACK_TOP (exception_stack_top - 4096)
+#define CRIT_STACK_TOP (exception_stack_top)
+
+#ifdef CONFIG_SMP
+#define BOOKE_LOAD_CRIT_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,CRIT_STACK_TOP@ha; \
+ addi r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ mfspr r8,SPRN_PIR; \
+ mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
+ neg r8,r8; \
+ addis r8,r8,MCHECK_STACK_TOP@ha; \
+ addi r8,r8,MCHECK_STACK_TOP@l
+#else
+#define BOOKE_LOAD_CRIT_STACK \
+ lis r8,CRIT_STACK_TOP@h; \
+ ori r8,r8,CRIT_STACK_TOP@l
+#define BOOKE_LOAD_MCHECK_STACK \
+ lis r8,MCHECK_STACK_TOP@h; \
+ ori r8,r8,MCHECK_STACK_TOP@l
+#endif
+
/*
* Exception prolog for critical exceptions. This is a little different
* from the normal exception prolog above since a critical exception
* can potentially occur at any point during normal exception processing.
* Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area. This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
+ * Instead we use a portion of the critical exception stack at low physical
+ * addresses.
*/
+
#define CRITICAL_EXCEPTION_PROLOG \
- mtspr SPRN_SPRG2,r8; /* SPRG2 only used in criticals */ \
- lis r8,crit_save@ha; \
- stw r10,crit_r10@l(r8); \
- stw r11,crit_r11@l(r8); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,crit_sprg0@l(r8); \
- mfspr r10,SPRN_SPRG1; \
- stw r10,crit_sprg1@l(r8); \
- mfspr r10,SPRN_SPRG4R; \
- stw r10,crit_sprg4@l(r8); \
- mfspr r10,SPRN_SPRG5R; \
- stw r10,crit_sprg5@l(r8); \
- mfspr r10,SPRN_SPRG7R; \
- stw r10,crit_sprg7@l(r8); \
- mfspr r10,SPRN_PID; \
- stw r10,crit_pid@l(r8); \
- mfspr r10,SPRN_SRR0; \
- stw r10,crit_srr0@l(r8); \
- mfspr r10,SPRN_SRR1; \
- stw r10,crit_srr1@l(r8); \
- mfspr r8,SPRN_SPRG2; /* SPRG2 only used in criticals */ \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
- lis r11,critical_stack_top@h; \
- ori r11,r11,critical_stack_top@l; \
+ mr r11,r8; \
+ mfspr r8,CRIT_SPRG; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
@@ -100,7 +126,7 @@
stw r1,GPR1(r11); \
mfspr r9,SPRN_CSRR1; \
stw r1,0(r11); \
- tovirt(r1,r11); \
+ mr r1,r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
@@ -109,43 +135,18 @@
/*
* Exception prolog for machine check exceptions. This is similar to
* the critical exception prolog, except that machine check exceptions
- * have their own save area. For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area. This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
+ * have their stack.
*/
#define MCHECK_EXCEPTION_PROLOG \
- mtspr SPRN_SPRG6W,r8; /* SPRG6 used in machine checks */ \
- lis r8,mcheck_save@ha; \
- stw r10,mcheck_r10@l(r8); \
- stw r11,mcheck_r11@l(r8); \
- mfspr r10,SPRN_SPRG0; \
- stw r10,mcheck_sprg0@l(r8); \
- mfspr r10,SPRN_SPRG1; \
- stw r10,mcheck_sprg1@l(r8); \
- mfspr r10,SPRN_SPRG4R; \
- stw r10,mcheck_sprg4@l(r8); \
- mfspr r10,SPRN_SPRG5R; \
- stw r10,mcheck_sprg5@l(r8); \
- mfspr r10,SPRN_SPRG7R; \
- stw r10,mcheck_sprg7@l(r8); \
- mfspr r10,SPRN_PID; \
- stw r10,mcheck_pid@l(r8); \
- mfspr r10,SPRN_SRR0; \
- stw r10,mcheck_srr0@l(r8); \
- mfspr r10,SPRN_SRR1; \
- stw r10,mcheck_srr1@l(r8); \
- mfspr r10,SPRN_CSRR0; \
- stw r10,mcheck_csrr0@l(r8); \
- mfspr r10,SPRN_CSRR1; \
- stw r10,mcheck_csrr1@l(r8); \
- mfspr r8,SPRN_SPRG6R; /* SPRG6 used in machine checks */ \
+ mtspr MCHECK_SPRG,r8; \
+ BOOKE_LOAD_MCHECK_STACK; /* r8 points to the mcheck stack */\
+ stw r10,GPR10-INT_FRAME_SIZE(r8); \
+ stw r11,GPR11-INT_FRAME_SIZE(r8); \
mfcr r10; /* save CR in r10 for now */\
mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
- lis r11,mcheck_stack_top@h; \
- ori r11,r11,mcheck_stack_top@l; \
+ mr r11,r8; \
+ mfspr r8,MCHECK_SPRG; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
@@ -165,7 +166,7 @@
stw r1,GPR1(r11); \
mfspr r9,SPRN_MCSRR1; \
stw r1,0(r11); \
- tovirt(r1,r11); \
+ mr r1,r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
stw r0,GPR0(r11); \
SAVE_4GPRS(3, r11); \
@@ -289,11 +290,11 @@ label:
mtspr SPRN_CSRR1,r9; \
lwz r9,GPR9(r11); \
lwz r12,GPR12(r11); \
- mtspr SPRN_SPRG2,r8; /* SPRG2 only used in criticals */ \
- lis r8,crit_save@ha; \
- lwz r10,crit_r10@l(r8); \
- lwz r11,crit_r11@l(r8); \
- mfspr r8,SPRN_SPRG2; \
+ mtspr CRIT_SPRG,r8; \
+ BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ lwz r10,GPR10-INT_FRAME_SIZE(r8); \
+ lwz r11,GPR11-INT_FRAME_SIZE(r8); \
+ mfspr r8,CRIT_SPRG; \
\
rfci; \
b .; \
diff --git a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S
index d83353d5eab563..e478de5a92d32c 100644
--- a/arch/ppc/kernel/head_e500.S
+++ b/arch/ppc/kernel/head_e500.S
@@ -33,6 +33,7 @@
*/
#include <linux/config.h>
+#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
@@ -789,8 +790,6 @@ load_up_spe:
SYNC
rfi
-
-
/*
* SPE unavailable trap from kernel - print a message, but let
* the task use SPE in the kernel until it returns to user mode.
@@ -929,78 +928,13 @@ _GLOBAL(empty_zero_page)
_GLOBAL(swapper_pg_dir)
.space 4096
+/* Reserved 4k for the critical exception stack & 4k for the machine
+ * check stack per CPU for kernel mode exceptions */
.section .bss
-/* Stack for handling critical exceptions from kernel mode */
-critical_stack_bottom:
- .space 4096
-critical_stack_top:
- .previous
-
-/* Stack for handling machine check exceptions from kernel mode */
-mcheck_stack_bottom:
- .space 4096
-mcheck_stack_top:
- .previous
-
-/*
- * This area is used for temporarily saving registers during the
- * critical and machine check exception prologs. It must always
- * follow the page aligned allocations, so it starts on a page
- * boundary, ensuring that all crit_save areas are in a single
- * page.
- */
-
-/* crit_save */
-_GLOBAL(crit_save)
- .space 4
-_GLOBAL(crit_r10)
- .space 4
-_GLOBAL(crit_r11)
- .space 4
-_GLOBAL(crit_sprg0)
- .space 4
-_GLOBAL(crit_sprg1)
- .space 4
-_GLOBAL(crit_sprg4)
- .space 4
-_GLOBAL(crit_sprg5)
- .space 4
-_GLOBAL(crit_sprg7)
- .space 4
-_GLOBAL(crit_pid)
- .space 4
-_GLOBAL(crit_srr0)
- .space 4
-_GLOBAL(crit_srr1)
- .space 4
-
-/* mcheck_save */
-_GLOBAL(mcheck_save)
- .space 4
-_GLOBAL(mcheck_r10)
- .space 4
-_GLOBAL(mcheck_r11)
- .space 4
-_GLOBAL(mcheck_sprg0)
- .space 4
-_GLOBAL(mcheck_sprg1)
- .space 4
-_GLOBAL(mcheck_sprg4)
- .space 4
-_GLOBAL(mcheck_sprg5)
- .space 4
-_GLOBAL(mcheck_sprg7)
- .space 4
-_GLOBAL(mcheck_pid)
- .space 4
-_GLOBAL(mcheck_srr0)
- .space 4
-_GLOBAL(mcheck_srr1)
- .space 4
-_GLOBAL(mcheck_csrr0)
- .space 4
-_GLOBAL(mcheck_csrr1)
- .space 4
+ .align 12
+exception_stack_bottom:
+ .space BOOKE_EXCEPTION_STACK_SIZE * NR_CPUS
+_GLOBAL(exception_stack_top)
/*
* This space gets a copy of optional info passed to us by the bootstrap
@@ -1016,4 +950,3 @@ _GLOBAL(cmd_line)
abatron_pteptrs:
.space 8
-
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 513c5ecdcd4f5a..761b8c7b25d275 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -135,25 +135,11 @@ static struct irqaction cpm2_irqaction = {
static void __init
mpc8560_ads_init_IRQ(void)
{
- int i;
- volatile cpm2_map_t *immap = cpm2_immr;
-
/* Setup OpenPIC */
mpc85xx_ads_init_IRQ();
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /* Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 5e80b9dc4ed4f3..6c020d67ad7044 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -181,10 +181,6 @@ void __init
mpc85xx_cds_init_IRQ(void)
{
bd_t *binfo = (bd_t *) __res;
-#ifdef CONFIG_CPM2
- volatile cpm2_map_t *immap = cpm2_immr;
- int i;
-#endif
/* Determine the Physical Address of the OpenPIC regs */
phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
@@ -203,19 +199,8 @@ mpc85xx_cds_init_IRQ(void)
openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
#ifdef CONFIG_CPM2
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /* Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
#endif
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 6184b533035a12..bc95836e417c51 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -201,7 +201,6 @@ static void __init
gp3_init_IRQ(void)
{
int i;
- volatile cpm2_map_t *immap = cpm2_immr;
bd_t *binfo = (bd_t *) __res;
/*
@@ -227,24 +226,8 @@ gp3_init_IRQ(void)
*/
openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
- /*
- * Setup CPM2 PIC
- */
-
- /* disable all CPM interupts */
- immap->im_intctl.ic_simrh = 0x0;
- immap->im_intctl.ic_simrl = 0x0;
-
- for (i = CPM_IRQ_OFFSET; i < (NR_CPM_INTS + CPM_IRQ_OFFSET); i++)
- irq_desc[i].handler = &cpm2_pic;
-
- /*
- * Initialize the default interrupt mapping priorities,
- * in case the boot rom changed something on us.
- */
- immap->im_intctl.ic_sicr = 0;
- immap->im_intctl.ic_scprrh = 0x05309770;
- immap->im_intctl.ic_scprrl = 0x05309770;
+ /* Setup CPM2 PIC */
+ cpm2_init_IRQ();
setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 7bc10c88c8240f..5488a053f4155f 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -45,7 +45,7 @@ obj-$(CONFIG_RADSTONE_PPC7D) += radstone_ppc7d.o
obj-$(CONFIG_SANDPOINT) += sandpoint.o
obj-$(CONFIG_SBC82xx) += sbc82xx.o
obj-$(CONFIG_SPRUCE) += spruce.o
-obj-$(CONFIG_LITE5200) += lite5200.o mpc5200.o
+obj-$(CONFIG_LITE5200) += lite5200.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index 77fa7545bb0a56..b604cf8b3cae91 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -13,7 +13,7 @@
* Dale Farnsworth <dale.farnsworth@mvista.com> and
* Wolfgang Denk <wd@denx.de>
*
- * Copyright 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright 2003 Motorola Inc.
* Copyright 2003 MontaVista Software Inc.
* Copyright 2003 DENX Software Engineering (wd@denx.de)
@@ -29,11 +29,12 @@
#include <linux/kdev_t.h>
#include <linux/root_dev.h>
#include <linux/console.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/io.h>
-#include <asm/ocp.h>
#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
#include <syslib/mpc52xx_pci.h>
@@ -46,33 +47,19 @@ EXPORT_SYMBOL(__res); /* For modules */
/* ======================================================================== */
-/* OCP device definition */
-/* For board/shared resources like PSCs */
+/* Platform specific code */
/* ======================================================================== */
-/* Be sure not to load conficting devices : e.g. loading the UART drivers for
- * PSC1 and then also loading a AC97 for this same PSC.
- * For details about how to create an entry, look in the doc of the concerned
- * driver ( eg drivers/serial/mpc52xx_uart.c for the PSC in uart mode )
- */
-
-static struct ocp_def board_ocp[] = {
- {
- .vendor = OCP_VENDOR_FREESCALE,
- .function = OCP_FUNC_PSC_UART,
- .index = 0,
- .paddr = MPC52xx_PSC1,
- .irq = MPC52xx_PSC1_IRQ,
- .pm = OCP_CPM_NA,
- },
- { /* Terminating entry */
- .vendor = OCP_VENDOR_INVALID
- }
-};
+/* Supported PSC function in "preference" order */
+struct mpc52xx_psc_func mpc52xx_psc_functions[] = {
+ { .id = 0,
+ .func = "uart",
+ },
+ { .id = -1, /* End entry */
+ .func = NULL,
+ }
+ };
-/* ======================================================================== */
-/* Platform specific code */
-/* ======================================================================== */
static int
lite5200_show_cpuinfo(struct seq_file *m)
@@ -92,21 +79,47 @@ lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
static void __init
lite5200_setup_cpu(void)
{
+ struct mpc52xx_cdm __iomem *cdm;
+ struct mpc52xx_gpio __iomem *gpio;
struct mpc52xx_intr __iomem *intr;
struct mpc52xx_xlb __iomem *xlb;
+ u32 port_config;
u32 intr_ctrl;
/* Map zones */
- xlb = ioremap(MPC52xx_XLB,sizeof(struct mpc52xx_xlb));
- intr = ioremap(MPC52xx_INTR,sizeof(struct mpc52xx_intr));
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+ gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+ xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE);
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
- if (!xlb || !intr) {
- printk("lite5200.c: Error while mapping XLB/INTR during "
+ if (!cdm || !gpio || !xlb || !intr) {
+ printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during"
"lite5200_setup_cpu\n");
goto unmap_regs;
}
+ /* Use internal 48 Mhz */
+ out_8(&cdm->ext_48mhz_en, 0x00);
+ out_8(&cdm->fd_enable, 0x01);
+ if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */
+ out_be16(&cdm->fd_counters, 0x0001);
+ else
+ out_be16(&cdm->fd_counters, 0x5555);
+
+ /* Get port mux config */
+ port_config = in_be32(&gpio->port_config);
+
+ /* 48Mhz internal, pin is GPIO */
+ port_config &= ~0x00800000;
+
+ /* USB port */
+ port_config &= ~0x00007000; /* Differential mode - USB1 only */
+ port_config |= 0x00001000;
+
+ /* Commit port config */
+ out_be32(&gpio->port_config, port_config);
+
/* Configure the XLB Arbiter */
out_be32(&xlb->master_pri_enable, 0xff);
out_be32(&xlb->master_priority, 0x11111111);
@@ -124,6 +137,8 @@ lite5200_setup_cpu(void)
/* Unmap reg zone */
unmap_regs:
+ if (cdm) iounmap(cdm);
+ if (gpio) iounmap(gpio);
if (xlb) iounmap(xlb);
if (intr) iounmap(intr);
}
@@ -131,9 +146,6 @@ unmap_regs:
static void __init
lite5200_setup_arch(void)
{
- /* Add board OCP definitions */
- mpc52xx_add_board_devices(board_ocp);
-
/* CPU & Port mux setup */
lite5200_setup_cpu();
@@ -176,6 +188,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
}
}
+ /* PPC Sys identification */
+ identify_ppc_sys_by_id(mfspr(SPRN_SVR));
+
/* BAT setup */
mpc52xx_set_bat();
@@ -184,7 +199,11 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
isa_mem_base = 0;
/* Powersave */
- powersave_nap = 1; /* We allow this platform to NAP */
+ /* This is provided as an example on how to do it. But you
+ need to be aware that NAP disable bus snoop and that may
+ be required for some devices to work properly, like USB ... */
+ /* powersave_nap = 1; */
+
/* Setup the ppc_md struct */
ppc_md.setup_arch = lite5200_setup_arch;
diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h
index 833134b19c791e..c1de2aa47175f6 100644
--- a/arch/ppc/platforms/lite5200.h
+++ b/arch/ppc/platforms/lite5200.h
@@ -17,7 +17,7 @@
#define __PLATFORMS_LITE5200_H__
/* Serial port used for low-level debug */
-#define MPC52xx_PF_CONSOLE_PORT 0 /* PSC1 */
+#define MPC52xx_PF_CONSOLE_PORT 1 /* PSC1 */
#endif /* __PLATFORMS_LITE5200_H__ */
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c
index e0c797f59ac997..ed2b1cebc19ae3 100644
--- a/arch/ppc/platforms/pmac_backlight.c
+++ b/arch/ppc/platforms/pmac_backlight.c
@@ -12,6 +12,7 @@
#include <linux/stddef.h>
#include <linux/reboot.h>
#include <linux/nvram.h>
+#include <linux/console.h>
#include <asm/sections.h>
#include <asm/ptrace.h>
#include <asm/io.h>
@@ -25,14 +26,19 @@
#include <linux/adb.h>
#include <linux/pmu.h>
-static struct backlight_controller *backlighter = NULL;
-static void* backlighter_data = NULL;
-static int backlight_autosave = 0;
+static struct backlight_controller *backlighter;
+static void* backlighter_data;
+static int backlight_autosave;
static int backlight_level = BACKLIGHT_MAX;
static int backlight_enabled = 1;
+static int backlight_req_level = -1;
+static int backlight_req_enable = -1;
-void __pmac
-register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type)
+static void backlight_callback(void *);
+static DECLARE_WORK(backlight_work, backlight_callback, NULL);
+
+void __pmac register_backlight_controller(struct backlight_controller *ctrler,
+ void *data, char *type)
{
struct device_node* bk_node;
char *prop;
@@ -83,16 +89,18 @@ register_backlight_controller(struct backlight_controller *ctrler, void *data, c
backlight_level = req.reply[0] >> 4;
}
#endif
+ acquire_console_sem();
if (!backlighter->set_enable(1, backlight_level, data))
backlight_enabled = 1;
+ release_console_sem();
- printk(KERN_INFO "Registered \"%s\" backlight controller, level: %d/15\n",
- type, backlight_level);
+ printk(KERN_INFO "Registered \"%s\" backlight controller,"
+ "level: %d/15\n", type, backlight_level);
}
EXPORT_SYMBOL(register_backlight_controller);
-void __pmac
-unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
+void __pmac unregister_backlight_controller(struct backlight_controller
+ *ctrler, void *data)
{
/* We keep the current backlight level (for now) */
if (ctrler == backlighter && data == backlighter_data)
@@ -100,22 +108,32 @@ unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
}
EXPORT_SYMBOL(unregister_backlight_controller);
-int __pmac
-set_backlight_enable(int enable)
+static int __pmac __set_backlight_enable(int enable)
{
int rc;
if (!backlighter)
return -ENODEV;
- rc = backlighter->set_enable(enable, backlight_level, backlighter_data);
+ acquire_console_sem();
+ rc = backlighter->set_enable(enable, backlight_level,
+ backlighter_data);
if (!rc)
backlight_enabled = enable;
+ release_console_sem();
return rc;
}
+int __pmac set_backlight_enable(int enable)
+{
+ if (!backlighter)
+ return -ENODEV;
+ backlight_req_enable = enable;
+ schedule_work(&backlight_work);
+ return 0;
+}
+
EXPORT_SYMBOL(set_backlight_enable);
-int __pmac
-get_backlight_enable(void)
+int __pmac get_backlight_enable(void)
{
if (!backlighter)
return -ENODEV;
@@ -123,8 +141,7 @@ get_backlight_enable(void)
}
EXPORT_SYMBOL(get_backlight_enable);
-int __pmac
-set_backlight_level(int level)
+static int __pmac __set_backlight_level(int level)
{
int rc = 0;
@@ -134,10 +151,12 @@ set_backlight_level(int level)
level = BACKLIGHT_OFF;
if (level > BACKLIGHT_MAX)
level = BACKLIGHT_MAX;
+ acquire_console_sem();
if (backlight_enabled)
rc = backlighter->set_level(level, backlighter_data);
if (!rc)
backlight_level = level;
+ release_console_sem();
if (!rc && !backlight_autosave) {
level <<=1;
if (level & 0x10)
@@ -146,13 +165,38 @@ set_backlight_level(int level)
}
return rc;
}
+int __pmac set_backlight_level(int level)
+{
+ if (!backlighter)
+ return -ENODEV;
+ backlight_req_level = level;
+ schedule_work(&backlight_work);
+ return 0;
+}
+
EXPORT_SYMBOL(set_backlight_level);
-int __pmac
-get_backlight_level(void)
+int __pmac get_backlight_level(void)
{
if (!backlighter)
return -ENODEV;
return backlight_level;
}
EXPORT_SYMBOL(get_backlight_level);
+
+static void backlight_callback(void *dummy)
+{
+ int level, enable;
+
+ do {
+ level = backlight_req_level;
+ enable = backlight_req_enable;
+ mb();
+
+ if (level >= 0)
+ __set_backlight_level(level);
+ if (enable >= 0)
+ __set_backlight_enable(enable);
+ } while(cmpxchg(&backlight_req_level, level, -1) != level ||
+ cmpxchg(&backlight_req_enable, enable, -1) != enable);
+}
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 830d00da5db0bc..dd418ea3426c70 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -108,7 +108,8 @@ ifeq ($(CONFIG_83xx),y)
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
endif
obj-$(CONFIG_MPC8555_CDS) += todc_time.o
-obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o
+obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o \
+ mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o
ifeq ($(CONFIG_PPC_MPC52xx),y)
obj-$(CONFIG_PCI) += mpc52xx_pci.o
endif
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
index bd8335b84d93af..954b07fc1df391 100644
--- a/arch/ppc/syslib/cpm2_pic.c
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -32,15 +32,17 @@ static u_char irq_to_siureg[] = {
0, 0, 0, 0, 0, 0, 0, 0
};
+/* bit numbers do not match the docs, these are precomputed so the bit for
+ * a given irq is (1 << irq_to_siubit[irq]) */
static u_char irq_to_siubit[] = {
- 31, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 27, 28, 29, 30,
- 29, 30, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 31,
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 15, 14, 13, 12, 11, 10, 9, 8,
- 7, 6, 5, 4, 3, 2, 1, 0
+ 0, 15, 14, 13, 12, 11, 10, 9,
+ 8, 7, 6, 5, 4, 3, 2, 1,
+ 2, 1, 15, 14, 13, 12, 11, 10,
+ 9, 8, 7, 6, 5, 4, 3, 0,
+ 31, 30, 29, 28, 27, 26, 25, 24,
+ 23, 22, 21, 20, 19, 18, 17, 16,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
};
static void cpm2_mask_irq(unsigned int irq_nr)
@@ -48,11 +50,13 @@ static void cpm2_mask_irq(unsigned int irq_nr)
int bit, word;
volatile uint *simr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
}
@@ -61,11 +65,13 @@ static void cpm2_unmask_irq(unsigned int irq_nr)
int bit, word;
volatile uint *simr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
}
@@ -74,14 +80,16 @@ static void cpm2_mask_and_ack(unsigned int irq_nr)
int bit, word;
volatile uint *simr, *sipnr;
+ irq_nr -= CPM_IRQ_OFFSET;
+
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
sipnr = &(cpm2_immr->im_intctl.ic_sipnrh);
- ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+ ppc_cached_irq_mask[word] &= ~(1 << bit);
simr[word] = ppc_cached_irq_mask[word];
- sipnr[word] = 1 << (31 - bit);
+ sipnr[word] = 1 << bit;
}
static void cpm2_end_irq(unsigned int irq_nr)
@@ -92,29 +100,25 @@ static void cpm2_end_irq(unsigned int irq_nr)
if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
&& irq_desc[irq_nr].action) {
+ irq_nr -= CPM_IRQ_OFFSET;
bit = irq_to_siubit[irq_nr];
word = irq_to_siureg[irq_nr];
simr = &(cpm2_immr->im_intctl.ic_simrh);
- ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+ ppc_cached_irq_mask[word] |= 1 << bit;
simr[word] = ppc_cached_irq_mask[word];
}
}
-struct hw_interrupt_type cpm2_pic = {
- " CPM2 SIU ",
- NULL,
- NULL,
- cpm2_unmask_irq,
- cpm2_mask_irq,
- cpm2_mask_and_ack,
- cpm2_end_irq,
- 0
+static struct hw_interrupt_type cpm2_pic = {
+ .typename = " CPM2 SIU ",
+ .enable = cpm2_unmask_irq,
+ .disable = cpm2_mask_irq,
+ .ack = cpm2_mask_and_ack,
+ .end = cpm2_end_irq,
};
-
-int
-cpm2_get_irq(struct pt_regs *regs)
+int cpm2_get_irq(struct pt_regs *regs)
{
int irq;
unsigned long bits;
@@ -126,5 +130,43 @@ cpm2_get_irq(struct pt_regs *regs)
if (irq == 0)
return(-1);
- return irq;
+ return irq+CPM_IRQ_OFFSET;
+}
+
+void cpm2_init_IRQ(void)
+{
+ int i;
+
+ /* Clear the CPM IRQ controller, in case it has any bits set
+ * from the bootloader
+ */
+
+ /* Mask out everything */
+ cpm2_immr->im_intctl.ic_simrh = 0x00000000;
+ cpm2_immr->im_intctl.ic_simrl = 0x00000000;
+ wmb();
+
+ /* Ack everything */
+ cpm2_immr->im_intctl.ic_sipnrh = 0xffffffff;
+ cpm2_immr->im_intctl.ic_sipnrl = 0xffffffff;
+ wmb();
+
+ /* Dummy read of the vector */
+ i = cpm2_immr->im_intctl.ic_sivec;
+ rmb();
+
+ /* Initialize the default interrupt mapping priorities,
+ * in case the boot rom changed something on us.
+ */
+ cpm2_immr->im_intctl.ic_sicr = 0;
+ cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
+ cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
+
+
+ /* Enable chaining to OpenPIC, and make everything level
+ */
+ for (i = 0; i < NR_CPM_INTS; i++) {
+ irq_desc[i+CPM_IRQ_OFFSET].handler = &cpm2_pic;
+ irq_desc[i+CPM_IRQ_OFFSET].status |= IRQ_LEVEL;
+ }
}
diff --git a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h
index d05003b091f531..97cab8f13a1a0c 100644
--- a/arch/ppc/syslib/cpm2_pic.h
+++ b/arch/ppc/syslib/cpm2_pic.h
@@ -1,7 +1,8 @@
#ifndef _PPC_KERNEL_CPM2_H
#define _PPC_KERNEL_CPM2_H
-extern struct hw_interrupt_type cpm2_pic;
extern int cpm2_get_irq(struct pt_regs *regs);
+extern void cpm2_init_IRQ(void);
+
#endif /* _PPC_KERNEL_CPM2_H */
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index f3c12a51bf3e08..23ea3f694de206 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -167,18 +167,12 @@ m8260_show_cpuinfo(struct seq_file *m)
static void __init
m8260_init_IRQ(void)
{
- int i;
-
- for ( i = 0 ; i < NR_SIU_INTS ; i++ )
- irq_desc[i].handler = &cpm2_pic;
+ cpm2_init_IRQ();
/* Initialize the default interrupt mapping priorities,
* in case the boot rom changed something on us.
*/
- cpm2_immr->im_intctl.ic_sicr = 0;
cpm2_immr->im_intctl.ic_siprr = 0x05309770;
- cpm2_immr->im_intctl.ic_scprrh = 0x05309770;
- cpm2_immr->im_intctl.ic_scprrl = 0x05309770;
}
/*
diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c
new file mode 100644
index 00000000000000..ad5182efca1dd3
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_devices.c
@@ -0,0 +1,318 @@
+/*
+ * arch/ppc/syslib/mpc52xx_devices.c
+ *
+ * Freescale MPC52xx device descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.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.
+ */
+
+#include <linux/fsl_devices.h>
+#include <linux/resource.h>
+#include <asm/mpc52xx.h>
+#include <asm/ppc_sys.h>
+
+
+static u64 mpc52xx_dma_mask = 0xffffffffULL;
+
+static struct fsl_i2c_platform_data mpc52xx_fsl_i2c_pdata = {
+ .device_flags = FSL_I2C_DEV_CLOCK_5200,
+};
+
+
+/* We use relative offsets for IORESOURCE_MEM to be independent from the
+ * MBAR location at compile time
+ */
+
+/* TODO Add the BestComm initiator channel to the device definitions,
+ possibly using IORESOURCE_DMA. But that's when BestComm is ready ... */
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC52xx_MSCAN1] = {
+ .name = "mpc52xx-mscan",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0900,
+ .end = 0x097f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN1_IRQ,
+ .end = MPC52xx_MSCAN1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_MSCAN2] = {
+ .name = "mpc52xx-mscan",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0980,
+ .end = 0x09ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_MSCAN2_IRQ,
+ .end = MPC52xx_MSCAN2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_SPI] = {
+ .name = "mpc52xx-spi",
+ .id = -1,
+ .num_resources = 3,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x0f00,
+ .end = 0x0f1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "modf",
+ .start = MPC52xx_SPI_MODF_IRQ,
+ .end = MPC52xx_SPI_MODF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "spif",
+ .start = MPC52xx_SPI_SPIF_IRQ,
+ .end = MPC52xx_SPI_SPIF_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_USB] = {
+ .name = "ppc-soc-ohci",
+ .id = -1,
+ .num_resources = 2,
+ .dev.dma_mask = &mpc52xx_dma_mask,
+ .dev.coherent_dma_mask = 0xffffffffULL,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1000,
+ .end = 0x10ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_USB_IRQ,
+ .end = MPC52xx_USB_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_BDLC] = {
+ .name = "mpc52xx-bdlc",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x1300,
+ .end = 0x130f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_BDLC_IRQ,
+ .end = MPC52xx_BDLC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC1] = {
+ .name = "mpc52xx-psc",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2000,
+ .end = 0x209f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC1_IRQ,
+ .end = MPC52xx_PSC1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC2] = {
+ .name = "mpc52xx-psc",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2200,
+ .end = 0x229f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC2_IRQ,
+ .end = MPC52xx_PSC2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC3] = {
+ .name = "mpc52xx-psc",
+ .id = 2,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2400,
+ .end = 0x249f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC3_IRQ,
+ .end = MPC52xx_PSC3_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC4] = {
+ .name = "mpc52xx-psc",
+ .id = 3,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2600,
+ .end = 0x269f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC4_IRQ,
+ .end = MPC52xx_PSC4_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC5] = {
+ .name = "mpc52xx-psc",
+ .id = 4,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2800,
+ .end = 0x289f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC5_IRQ,
+ .end = MPC52xx_PSC5_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_PSC6] = {
+ .name = "mpc52xx-psc",
+ .id = 5,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x2c00,
+ .end = 0x2c9f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_PSC6_IRQ,
+ .end = MPC52xx_PSC6_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_FEC] = {
+ .name = "mpc52xx-fec",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3000,
+ .end = 0x33ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_FEC_IRQ,
+ .end = MPC52xx_FEC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_ATA] = {
+ .name = "mpc52xx-ata",
+ .id = -1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3a00,
+ .end = 0x3aff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_ATA_IRQ,
+ .end = MPC52xx_ATA_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C1] = {
+ .name = "fsl-i2c",
+ .id = 0,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d00,
+ .end = 0x3d1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C1_IRQ,
+ .end = MPC52xx_I2C1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC52xx_I2C2] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc52xx_fsl_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x3d40,
+ .end = 0x3d5f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC52xx_I2C2_IRQ,
+ .end = MPC52xx_I2C2_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+};
+
+
+static int __init mach_mpc52xx_fixup(struct platform_device *pdev)
+{
+ ppc_sys_fixup_mem_resource(pdev, MPC52xx_MBAR);
+ return 0;
+}
+
+static int __init mach_mpc52xx_init(void)
+{
+ ppc_sys_device_fixup = mach_mpc52xx_fixup;
+ return 0;
+}
+
+postcore_initcall(mach_mpc52xx_init);
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c
index 347be33954cd5a..c723efd954a6a0 100644
--- a/arch/ppc/syslib/mpc52xx_pci.c
+++ b/arch/ppc/syslib/mpc52xx_pci.c
@@ -183,7 +183,7 @@ mpc52xx_find_bridges(void)
pci_assign_all_busses = 1;
- pci_regs = ioremap(MPC52xx_PCI, sizeof(struct mpc52xx_pci));
+ pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
if (!pci_regs)
return;
diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
index 1c5838f9d292a8..4c4497e62517da 100644
--- a/arch/ppc/syslib/mpc52xx_pic.c
+++ b/arch/ppc/syslib/mpc52xx_pic.c
@@ -180,8 +180,8 @@ mpc52xx_init_irq(void)
u32 intr_ctrl;
/* Remap the necessary zones */
- intr = ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr));
- sdma = ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma));
+ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+ sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
if ((intr==NULL) || (sdma==NULL))
panic("Can't ioremap PIC/SDMA register for init_irq !");
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index c0ecb24210c392..bb2374585a7b9d 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -23,7 +23,6 @@
#include <asm/time.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
-#include <asm/ocp.h>
#include <asm/pgtable.h>
#include <asm/ppcboot.h>
@@ -39,18 +38,14 @@ static int core_mult[] = { /* CPU Frequency multiplier, taken */
void
mpc52xx_restart(char *cmd)
{
- struct mpc52xx_gpt __iomem *gpt0 =
- (struct mpc52xx_gpt __iomem *) MPC52xx_GPTx(0);
+ struct mpc52xx_gpt __iomem *gpt0 = MPC52xx_VA(MPC52xx_GPTx_OFFSET(0));
local_irq_disable();
/* Turn on the watchdog and wait for it to expire. It effectively
does a reset */
- if (gpt0 != NULL) {
- out_be32(&gpt0->count, 0x000000ff);
- out_be32(&gpt0->mode, 0x00009004);
- } else
- printk(KERN_ERR "mpc52xx_restart: Unable to ioremap GPT0 registers, -> looping ...");
+ out_be32(&gpt0->count, 0x000000ff);
+ out_be32(&gpt0->mode, 0x00009004);
while (1);
}
@@ -96,9 +91,7 @@ mpc52xx_map_io(void)
#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#ifdef MPC52xx_PF_CONSOLE_PORT
-#define MPC52xx_CONSOLE MPC52xx_PSCx(MPC52xx_PF_CONSOLE_PORT)
-#else
+#ifndef MPC52xx_PF_CONSOLE_PORT
#error "mpc52xx PSC for console not selected"
#endif
@@ -114,8 +107,9 @@ void
mpc52xx_progress(char *s, unsigned short hex)
{
char c;
- struct mpc52xx_psc __iomem *psc =
- (struct mpc52xx_psc __iomem *)MPC52xx_CONSOLE;
+ struct mpc52xx_psc __iomem *psc;
+
+ psc = MPC52xx_VA(MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT));
while ((c = *s++) != 0) {
if (c == '\n')
@@ -144,7 +138,7 @@ mpc52xx_find_end_of_memory(void)
u32 sdram_config_0, sdram_config_1;
/* Temp BAT2 mapping active when this is called ! */
- mmap_ctl = (struct mpc52xx_mmap_ctl __iomem *) MPC52xx_MMAP_CTL;
+ mmap_ctl = MPC52xx_VA(MPC52xx_MMAP_CTL_OFFSET);
sdram_config_0 = in_be32(&mmap_ctl->sdram0);
sdram_config_1 = in_be32(&mmap_ctl->sdram1);
@@ -174,8 +168,8 @@ mpc52xx_calibrate_decr(void)
struct mpc52xx_rtc __iomem *rtc;
struct mpc52xx_cdm __iomem *cdm;
- rtc = ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
- cdm = ioremap(MPC52xx_CDM, sizeof(struct mpc52xx_cdm));
+ rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE);
+ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
if ((rtc==NULL) || (cdm==NULL))
panic("Can't ioremap RTC/CDM while computing bus freq");
@@ -222,11 +216,15 @@ mpc52xx_calibrate_decr(void)
tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000);
}
+int mpc52xx_match_psc_function(int psc_idx, const char *func)
+{
+ struct mpc52xx_psc_func *cf = mpc52xx_psc_functions;
-void __init
-mpc52xx_add_board_devices(struct ocp_def board_ocp[]) {
- while (board_ocp->vendor != OCP_VENDOR_INVALID)
- if(ocp_add_one_device(board_ocp++))
- printk("mpc5200-ocp: Failed to add board device !\n");
-}
+ while ((cf->id != -1) && (cf->func != NULL)) {
+ if ((cf->id == psc_idx) && !strcmp(cf->func,func))
+ return 1;
+ cf++;
+ }
+ return 0;
+}
diff --git a/arch/ppc/syslib/mpc52xx_sys.c b/arch/ppc/syslib/mpc52xx_sys.c
new file mode 100644
index 00000000000000..9a0f90aa8aac8e
--- /dev/null
+++ b/arch/ppc/syslib/mpc52xx_sys.c
@@ -0,0 +1,38 @@
+/*
+ * arch/ppc/syslib/mpc52xx_sys.c
+ *
+ * Freescale MPC52xx system descriptions
+ *
+ *
+ * Maintainer : Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Copyright (C) 2005 Sylvain Munaut <tnt@246tNt.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.
+ */
+
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "5200",
+ .mask = 0xffff0000,
+ .value = 0x80110000,
+ .num_devices = 15,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC52xx_MSCAN1, MPC52xx_MSCAN2, MPC52xx_SPI,
+ MPC52xx_USB, MPC52xx_BDLC, MPC52xx_PSC1, MPC52xx_PSC2,
+ MPC52xx_PSC3, MPC52xx_PSC4, MPC52xx_PSC5, MPC52xx_PSC6,
+ MPC52xx_FEC, MPC52xx_ATA, MPC52xx_I2C1, MPC52xx_I2C2,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
+};
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c
index 389c509d858231..d806a92a9401be 100644
--- a/arch/ppc/syslib/mpc85xx_sys.c
+++ b/arch/ppc/syslib/mpc85xx_sys.c
@@ -80,7 +80,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8555",
.mask = 0xFFFF0000,
.value = 0x80710000,
- .num_devices = 20,
+ .num_devices = 19,
.device_list = (enum ppc_sys_devices[])
{
MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -88,7 +88,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC85xx_PERFMON, MPC85xx_DUART,
MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
- MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
MPC85xx_CPM_USB,
},
@@ -97,7 +97,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
.ppc_sys_name = "8555E",
.mask = 0xFFFF0000,
.value = 0x80790000,
- .num_devices = 21,
+ .num_devices = 20,
.device_list = (enum ppc_sys_devices[])
{
MPC85xx_TSEC1, MPC85xx_TSEC2, MPC85xx_IIC1,
@@ -105,7 +105,7 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
MPC85xx_CPM_SPI, MPC85xx_CPM_I2C, MPC85xx_CPM_SCC1,
MPC85xx_CPM_SCC2, MPC85xx_CPM_SCC3,
- MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2, MPC85xx_CPM_FCC3,
+ MPC85xx_CPM_FCC1, MPC85xx_CPM_FCC2,
MPC85xx_CPM_SMC1, MPC85xx_CPM_SMC2,
MPC85xx_CPM_USB,
},
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index eeb9c2ec911822..15c4a1455caee7 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -278,6 +278,23 @@ config LPARCFG
Provide system capacity information via human readable
<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ depends on PROC_FS
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y. Only embedded should say N here.
+
endmenu
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 3db6ef3fed53b3..da20120f226175 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -285,7 +285,7 @@ static unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
return mem_blocks;
}
-static void __init iSeries_parse_cmdline(void)
+static void __init iSeries_get_cmdline(void)
{
char *p, *q;
@@ -305,6 +305,8 @@ static void __init iSeries_parse_cmdline(void)
static void __init iSeries_init_early(void)
{
+ extern unsigned long memory_limit;
+
DBG(" -> iSeries_init_early()\n");
ppcdbg_initialize();
@@ -352,6 +354,31 @@ static void __init iSeries_init_early(void)
*/
build_iSeries_Memory_Map();
+ iSeries_get_cmdline();
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+
+ /* Parse early parameters, in particular mem=x */
+ parse_early_param();
+
+ if (memory_limit) {
+ if (memory_limit < systemcfg->physicalMemorySize)
+ systemcfg->physicalMemorySize = memory_limit;
+ else {
+ printk("Ignoring mem=%lu >= ram_top.\n", memory_limit);
+ memory_limit = 0;
+ }
+ }
+
+ /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
+ iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
+
+ lmb_init();
+ lmb_add(0, systemcfg->physicalMemorySize);
+ lmb_analyze();
+ lmb_reserve(0, __pa(klimit));
+
/* Initialize machine-dependency vectors */
#ifdef CONFIG_SMP
smp_init_iSeries();
@@ -377,9 +404,6 @@ static void __init iSeries_init_early(void)
initrd_start = initrd_end = 0;
#endif /* CONFIG_BLK_DEV_INITRD */
-
- iSeries_parse_cmdline();
-
DBG(" <- iSeries_init_early()\n");
}
@@ -540,14 +564,6 @@ static void __init build_iSeries_Memory_Map(void)
* nextPhysChunk
*/
systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
-
- /* Bolt kernel mappings for all of memory */
- iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
-
- lmb_init();
- lmb_add(0, systemcfg->physicalMemorySize);
- lmb_analyze(); /* ?? */
- lmb_reserve(0, __pa(klimit));
}
/*
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 4f5c16d4cc6dd6..103daaf735734e 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -71,7 +71,11 @@ static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->msr |= MSR_SE;
- regs->nip = (unsigned long)&p->ainsn.insn;
+ /*single step inline if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->nip = (unsigned long)p->addr;
+ else
+ regs->nip = (unsigned long)&p->ainsn.insn;
}
static inline int kprobe_handler(struct pt_regs *regs)
@@ -86,6 +90,12 @@ static inline int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->msr &= ~MSR_SE;
+ regs->msr |= kprobe_saved_msr;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -128,10 +138,9 @@ static inline int kprobe_handler(struct pt_regs *regs)
kprobe_status = KPROBE_HIT_ACTIVE;
current_kprobe = p;
kprobe_saved_msr = regs->msr;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
ss_probe:
prepare_singlestep(p, regs);
diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
index 56d7ba87fe608d..d6c6bd03d2a42c 100644
--- a/arch/ppc64/kernel/lmb.c
+++ b/arch/ppc64/kernel/lmb.c
@@ -344,3 +344,29 @@ lmb_abs_to_phys(unsigned long aa)
return pa;
}
+
+/*
+ * Truncate the lmb list to memory_limit if it's set
+ * You must call lmb_analyze() after this.
+ */
+void __init lmb_enforce_memory_limit(void)
+{
+ extern unsigned long memory_limit;
+ unsigned long i, limit;
+ struct lmb_region *mem = &(lmb.memory);
+
+ if (! memory_limit)
+ return;
+
+ limit = memory_limit;
+ for (i = 0; i < mem->cnt; i++) {
+ if (limit > mem->region[i].size) {
+ limit -= mem->region[i].size;
+ continue;
+ }
+
+ mem->region[i].size = limit;
+ mem->cnt = i + 1;
+ break;
+ }
+}
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 3e3c40f248cb9c..1a5f59b769b915 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -912,6 +912,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
const char *full_path, void *data)
{
u32 *prop;
+ u64 *prop64;
+ extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
if (strcmp(full_path, "/chosen") != 0)
return 0;
@@ -928,6 +930,18 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
iommu_force_on = 1;
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,memory-limit", NULL);
+ if (prop64)
+ memory_limit = *prop64;
+
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
+ if (prop64)
+ tce_alloc_start = *prop64;
+
+ prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
+ if (prop64)
+ tce_alloc_end = *prop64;
+
#ifdef CONFIG_PPC_RTAS
/* To help early debugging via the front panel, we retreive a minimal
* set of RTAS infos now if available
@@ -1067,6 +1081,7 @@ void __init early_init_devtree(void *params)
lmb_init();
scan_flat_dt(early_init_dt_scan_root, NULL);
scan_flat_dt(early_init_dt_scan_memory, NULL);
+ lmb_enforce_memory_limit();
lmb_analyze();
systemcfg->physicalMemorySize = lmb_phys_mem_size();
lmb_reserve(0, __pa(klimit));
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index d3ebe99915182f..8dffa9ae2623df 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -177,6 +177,10 @@ static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
+static unsigned long __initdata prom_memory_limit;
+static unsigned long __initdata prom_tce_alloc_start;
+static unsigned long __initdata prom_tce_alloc_end;
+
static unsigned long __initdata alloc_top;
static unsigned long __initdata alloc_top_high;
static unsigned long __initdata alloc_bottom;
@@ -384,10 +388,70 @@ static int __init prom_setprop(phandle node, const char *pname,
(u32)(unsigned long) value, (u32) valuelen);
}
+/* We can't use the standard versions because of RELOC headaches. */
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'f') \
+ || ('A' <= (c) && (c) <= 'F'))
+
+#define isdigit(c) ('0' <= (c) && (c) <= '9')
+#define islower(c) ('a' <= (c) && (c) <= 'z')
+#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
+
+unsigned long prom_strtoul(const char *cp, const char **endp)
+{
+ unsigned long result = 0, base = 10, value;
+
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if (toupper(*cp) == 'X') {
+ cp++;
+ base = 16;
+ }
+ }
+
+ while (isxdigit(*cp) &&
+ (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
+ result = result * base + value;
+ cp++;
+ }
+
+ if (endp)
+ *endp = cp;
+
+ return result;
+}
+
+unsigned long prom_memparse(const char *ptr, const char **retptr)
+{
+ unsigned long ret = prom_strtoul(ptr, retptr);
+ int shift = 0;
+
+ /*
+ * We can't use a switch here because GCC *may* generate a
+ * jump table which won't work, because we're not running at
+ * the address we're linked at.
+ */
+ if ('G' == **retptr || 'g' == **retptr)
+ shift = 30;
+
+ if ('M' == **retptr || 'm' == **retptr)
+ shift = 20;
+
+ if ('K' == **retptr || 'k' == **retptr)
+ shift = 10;
+
+ if (shift) {
+ ret <<= shift;
+ (*retptr)++;
+ }
+
+ return ret;
+}
/*
* Early parsing of the command line passed to the kernel, used for
- * the options that affect the iommu
+ * "mem=x" and the options that affect the iommu
*/
static void __init early_cmdline_parse(void)
{
@@ -418,6 +482,14 @@ static void __init early_cmdline_parse(void)
else if (!strncmp(opt, RELOC("force"), 5))
RELOC(iommu_force_on) = 1;
}
+
+ opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
+ if (opt) {
+ opt += 4;
+ RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
+ /* Align to 16 MB == size of large page */
+ RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
+ }
}
/*
@@ -664,15 +736,7 @@ static void __init prom_init_mem(void)
}
}
- /* Setup our top/bottom alloc points, that is top of RMO or top of
- * segment 0 when running non-LPAR
- */
- if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
- RELOC(alloc_top) = RELOC(rmo_top);
- else
- RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000);
- RELOC(alloc_top_high) = RELOC(ram_top);
/* Check if we have an initrd after the kernel, if we do move our bottom
* point to after it
@@ -682,7 +746,40 @@ static void __init prom_init_mem(void)
RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
}
+ /*
+ * If prom_memory_limit is set we reduce the upper limits *except* for
+ * alloc_top_high. This must be the real top of RAM so we can put
+ * TCE's up there.
+ */
+
+ RELOC(alloc_top_high) = RELOC(ram_top);
+
+ if (RELOC(prom_memory_limit)) {
+ if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
+ prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
+ RELOC(prom_memory_limit));
+ RELOC(prom_memory_limit) = 0;
+ } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
+ prom_printf("Ignoring mem=%x >= ram_top.\n",
+ RELOC(prom_memory_limit));
+ RELOC(prom_memory_limit) = 0;
+ } else {
+ RELOC(ram_top) = RELOC(prom_memory_limit);
+ RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
+ }
+ }
+
+ /*
+ * Setup our top alloc point, that is top of RMO or top of
+ * segment 0 when running non-LPAR.
+ */
+ if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
+ RELOC(alloc_top) = RELOC(rmo_top);
+ else
+ RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top));
+
prom_printf("memory layout at init:\n");
+ prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
@@ -871,6 +968,16 @@ static void __init prom_initialize_tce_table(void)
reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
+ if (RELOC(prom_memory_limit)) {
+ /*
+ * We align the start to a 16MB boundary so we can map the TCE area
+ * using large pages if possible. The end should be the top of RAM
+ * so no need to align it.
+ */
+ RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000);
+ RELOC(prom_tce_alloc_end) = local_alloc_top;
+ }
+
/* Flag the first invalid entry */
prom_debug("ending prom_initialize_tce_table\n");
}
@@ -1684,9 +1791,21 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
*/
if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
+
if (RELOC(iommu_force_on))
prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
+ if (RELOC(prom_memory_limit))
+ prom_setprop(_prom->chosen, "linux,memory-limit",
+ PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit)));
+
+ if (RELOC(prom_tce_alloc_start)) {
+ prom_setprop(_prom->chosen, "linux,tce-alloc-start",
+ PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start)));
+ prom_setprop(_prom->chosen, "linux,tce-alloc-end",
+ PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end)));
+ }
+
/*
* Now finally create the flattened device-tree
*/
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index ac89fbdb65b441..354a287c67eb84 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -27,6 +27,7 @@
#include <linux/user.h>
#include <linux/security.h>
#include <linux/audit.h>
+#include <linux/seccomp.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -315,6 +316,8 @@ void do_syscall_trace_enter(struct pt_regs *regs)
void do_syscall_trace_leave(struct pt_regs *regs)
{
+ secure_computing(regs->gpr[0]);
+
if (unlikely(current->audit_context))
audit_syscall_exit(current, regs->result);
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index e0c547a9cfd31d..21c57f539c2930 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -636,12 +636,11 @@ void __init setup_system(void)
early_console_initialized = 1;
register_console(&udbg_console);
-#endif /* !CONFIG_PPC_ISERIES */
-
/* Save unparsed command line copy for /proc/cmdline */
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
parse_early_param();
+#endif /* !CONFIG_PPC_ISERIES */
#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
/*
@@ -800,20 +799,31 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-#if 0 /* XXX not currently used */
+/*
+ * These three variables are used to save values passed to us by prom_init()
+ * via the device tree. The TCE variables are needed because with a memory_limit
+ * in force we may need to explicitly map the TCE are at the top of RAM.
+ */
unsigned long memory_limit;
+unsigned long tce_alloc_start;
+unsigned long tce_alloc_end;
+#ifdef CONFIG_PPC_ISERIES
+/*
+ * On iSeries we just parse the mem=X option from the command line.
+ * On pSeries it's a bit more complicated, see prom_init_mem()
+ */
static int __init early_parsemem(char *p)
{
if (!p)
return 0;
- memory_limit = memparse(p, &p);
+ memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
return 0;
}
early_param("mem", early_parsemem);
-#endif
+#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
static int __init set_preferred_console(void)
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 5fc27d0c5ed192..e48be12f518c48 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -149,6 +149,8 @@ void __init htab_initialize(void)
unsigned long pteg_count;
unsigned long mode_rw;
int i, use_largepages = 0;
+ unsigned long base = 0, size = 0;
+ extern unsigned long tce_alloc_start, tce_alloc_end;
DBG(" -> htab_initialize()\n");
@@ -204,8 +206,6 @@ void __init htab_initialize(void)
/* create bolted the linear mapping in the hash table */
for (i=0; i < lmb.memory.cnt; i++) {
- unsigned long base, size;
-
base = lmb.memory.region[i].physbase + KERNELBASE;
size = lmb.memory.region[i].size;
@@ -234,6 +234,25 @@ void __init htab_initialize(void)
#endif /* CONFIG_U3_DART */
create_pte_mapping(base, base + size, mode_rw, use_largepages);
}
+
+ /*
+ * If we have a memory_limit and we've allocated TCEs then we need to
+ * explicitly map the TCE area at the top of RAM. We also cope with the
+ * case that the TCEs start below memory_limit.
+ * tce_alloc_start/end are 16MB aligned so the mapping should work
+ * for either 4K or 16MB pages.
+ */
+ if (tce_alloc_start) {
+ tce_alloc_start += KERNELBASE;
+ tce_alloc_end += KERNELBASE;
+
+ if (base + size >= tce_alloc_start)
+ tce_alloc_start = base + size + 1;
+
+ create_pte_mapping(tce_alloc_start, tce_alloc_end,
+ mode_rw, use_largepages);
+ }
+
DBG(" <- htab_initialize()\n");
}
#undef KB
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index 5c603ba9823108..ea862ec643d3a9 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -285,6 +285,35 @@ static int cpu_numa_callback(struct notifier_block *nfb,
return ret;
}
+/*
+ * Check and possibly modify a memory region to enforce the memory limit.
+ *
+ * Returns the size the region should have to enforce the memory limit.
+ * This will either be the original value of size, a truncated value,
+ * or zero. If the returned value of size is 0 the region should be
+ * discarded as it lies wholy above the memory limit.
+ */
+static unsigned long __init numa_enforce_memory_limit(unsigned long start, unsigned long size)
+{
+ /*
+ * We use lmb_end_of_DRAM() in here instead of memory_limit because
+ * we've already adjusted it for the limit and it takes care of
+ * having memory holes below the limit.
+ */
+ extern unsigned long memory_limit;
+
+ if (! memory_limit)
+ return size;
+
+ if (start + size <= lmb_end_of_DRAM())
+ return size;
+
+ if (start >= lmb_end_of_DRAM())
+ return 0;
+
+ return lmb_end_of_DRAM() - start;
+}
+
static int __init parse_numa_properties(void)
{
struct device_node *cpu = NULL;
@@ -373,6 +402,13 @@ new_range:
if (max_domain < numa_domain)
max_domain = numa_domain;
+ if (! (size = numa_enforce_memory_limit(start, size))) {
+ if (--ranges)
+ goto new_range;
+ else
+ continue;
+ }
+
/*
* Initialize new node struct, or add to an existing one.
*/
@@ -405,8 +441,7 @@ new_range:
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
numa_domain;
- ranges--;
- if (ranges)
+ if (--ranges)
goto new_range;
}
@@ -614,8 +649,11 @@ new_range:
if (numa_domain != nid)
continue;
- dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
- free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
+ mem_size = numa_enforce_memory_limit(mem_start, mem_size);
+ if (mem_size) {
+ dbg("free_bootmem %lx %lx\n", mem_start, mem_size);
+ free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);
+ }
if (--ranges) /* process all ranges in cell */
goto new_range;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index b1de24775c31ef..80306bc8c799b7 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -62,8 +62,8 @@ void bust_spinlocks(int yes)
oops_in_progress = 1;
} else {
int loglevel_save = console_loglevel;
- oops_in_progress = 0;
console_unblank();
+ oops_in_progress = 0;
/*
* OK, the message is on the console. Now we call printk()
* without oops_in_progress set so that printk will give klogd
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 7d97138f5d2e65..7066d7ba667a5e 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -68,8 +68,14 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
regs->tstate |= TSTATE_PIL;
- regs->tpc = (unsigned long) &p->ainsn.insn[0];
- regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ /*single step inline, if it a breakpoint instruction*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION) {
+ regs->tpc = (unsigned long) p->addr;
+ regs->tnpc = current_kprobe_orig_tnpc;
+ } else {
+ regs->tpc = (unsigned long) &p->ainsn.insn[0];
+ regs->tnpc = (unsigned long) &p->ainsn.insn[1];
+ }
}
static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
@@ -97,6 +103,12 @@ static int kprobe_handler(struct pt_regs *regs)
*/
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
+ current_kprobe_orig_tstate_pil);
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -128,7 +140,7 @@ static int kprobe_handler(struct pt_regs *regs)
kprobe_status = KPROBE_HIT_ACTIVE;
current_kprobe = p;
- if (p->pre_handler(p, regs))
+ if (p->pre_handler && p->pre_handler(p, regs))
return 1;
ss_probe:
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index c27cab081ad28a..b89989de364d1d 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -16,7 +16,7 @@ config PT_PROXY
config GPROF
bool "Enable gprof support"
- depends on DEBUG_INFO && MODE_SKAS
+ depends on DEBUG_INFO && MODE_SKAS && !MODE_TT
help
This allows profiling of a User-Mode Linux kernel with the gprof
utility.
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index b760b5a2a34350..1f77deb3fd237a 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -248,11 +248,8 @@ int write_chan(struct list_head *chans, const char *buf, int len,
n = chan->ops->write(chan->fd, buf, len, chan->data);
if (chan->primary) {
ret = n;
- if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))){
+ if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len)))
reactivate_fd(chan->fd, write_irq);
- if (ret == -EAGAIN)
- ret = 0;
- }
}
}
return(ret);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index d4286de17f0700..6924f273ced9fd 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -128,7 +128,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
ret = buffer_data(line, buf, len);
err = flush_buffer(line);
local_irq_restore(flags);
- if(err <= 0)
+ if(err <= 0 && (err != -EAGAIN || !ret))
ret = err;
}
else {
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index b514ea28d16c4b..661d495e204488 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -9,15 +9,11 @@
#include "uml-config.h"
#include "user_constants.h"
-#ifdef UML_CONFIG_MODE_TT
-#include "sysdep/sc.h"
-#endif
-
-#ifdef UML_CONFIG_MODE_SKAS
-
#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+extern void update_debugregs(int seq);
+
/* syscall emulation path in ptrace */
#ifndef PTRACE_SYSEMU
@@ -28,9 +24,13 @@ void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
-#include "skas_ptregs.h"
+#ifdef UML_CONFIG_MODE_TT
+#include "sysdep/sc.h"
+#endif
-extern void update_debugregs(int seq);
+#ifdef UML_CONFIG_MODE_SKAS
+
+#include "skas_ptregs.h"
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 36d9beec431b8b..5db81ec9087d2f 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -23,6 +23,9 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff);
+/* On i386 they choose a meaningless naming.*/
+#define __NR_kexec_load __NR_sys_kexec_load
+
#define ARCH_SYSCALLS \
[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, \
[ __NR_break ] = (syscall_handler_t *) sys_ni_syscall, \
@@ -74,7 +77,7 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
[ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64, \
[ __NR_select ] = (syscall_handler_t *) old_select, \
[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+ [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
[ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
[ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
[ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
@@ -97,19 +100,16 @@ extern long sys_mmap2(unsigned long addr, unsigned long len,
[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
- [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ 222 ] = (syscall_handler_t *) sys_ni_syscall, \
[ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
[ 251 ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
- [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
- [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
-
+ [ 285 ] = (syscall_handler_t *) sys_ni_syscall,
+
/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
-#define LAST_ARCH_SYSCALL __NR_vserver
+#define LAST_ARCH_SYSCALL 285
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 5eac9bed21ad39..915c82daffbd6b 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -10,6 +10,9 @@
#include "uml-config.h"
#include "user_constants.h"
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
+
#ifdef UML_CONFIG_MODE_TT
#include "sysdep/sc.h"
#endif
@@ -17,9 +20,6 @@
#ifdef UML_CONFIG_MODE_SKAS
#include "skas_ptregs.h"
-#define MAX_REG_OFFSET (UM_FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
-
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index 65fd494420f990..b187a4157ff367 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -71,12 +71,7 @@ extern syscall_handler_t sys_arch_prctl;
[ __NR_iopl ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_set_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
[ __NR_get_thread_area ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages, \
[ __NR_semtimedop ] = (syscall_handler_t *) sys_semtimedop, \
- [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64, \
- [ 223 ] = (syscall_handler_t *) sys_ni_syscall, \
- [ __NR_utimes ] = (syscall_handler_t *) sys_utimes, \
- [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall, \
[ 251 ] = (syscall_handler_t *) sys_ni_syscall,
#define LAST_ARCH_SYSCALL 251
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 82d19b451d5eae..668df13d8c9d67 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -108,12 +108,14 @@ static void tty_output(int master, int slave)
panic("check_sigio : write failed, errno = %d\n", errno);
while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
- if(got_sigio){
+ if (got_sigio) {
printk("Yes\n");
pty_output_sigio = 1;
+ } else if (n == -EAGAIN) {
+ printk("No, enabling workaround\n");
+ } else {
+ panic("check_sigio : read failed, err = %d\n", n);
}
- else if(n == -EAGAIN) printk("No, enabling workaround\n");
- else panic("check_sigio : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
@@ -235,6 +237,8 @@ static int need_poll(int n)
return(0);
}
+/* Must be called with sigio_lock held, because it's needed by the marked
+ * critical section. */
static void update_thread(void)
{
unsigned long flags;
@@ -257,7 +261,7 @@ static void update_thread(void)
set_signals(flags);
return;
fail:
- sigio_lock();
+ /* Critical section start */
if(write_sigio_pid != -1)
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
@@ -265,7 +269,7 @@ static void update_thread(void)
os_close_file(sigio_private[1]);
os_close_file(write_sigio_fds[0]);
os_close_file(write_sigio_fds[1]);
- sigio_unlock();
+ /* Critical section end */
set_signals(flags);
}
@@ -418,19 +422,10 @@ int read_sigio_fd(int fd)
static void sigio_cleanup(void)
{
- if(write_sigio_pid != -1)
+ if (write_sigio_pid != -1) {
os_kill_process(write_sigio_pid, 1);
+ write_sigio_pid = -1;
+ }
}
__uml_exitcall(sigio_cleanup);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index c8e5fe49583aee..7575ec489b6302 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -61,7 +61,8 @@ static void do_buffer_op(void *jmpbuf, void *arg_ptr)
void *arg;
int *res;
- va_copy(args, *(va_list *)arg_ptr);
+ /* Some old gccs recognize __va_copy, but not va_copy */
+ __va_copy(args, *(va_list *)arg_ptr);
addr = va_arg(args, unsigned long);
len = va_arg(args, int);
is_write = va_arg(args, int);
diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
index 202662a4e52515..7fc06c85b29d93 100644
--- a/arch/um/kernel/sys_call_table.c
+++ b/arch/um/kernel/sys_call_table.c
@@ -47,7 +47,6 @@ extern syscall_handler_t sys_vfork;
extern syscall_handler_t old_select;
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_vserver;
extern syscall_handler_t sys_mbind;
extern syscall_handler_t sys_get_mempolicy;
extern syscall_handler_t sys_set_mempolicy;
@@ -241,7 +240,8 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_epoll_create ] = (syscall_handler_t *) sys_epoll_create,
[ __NR_epoll_ctl ] = (syscall_handler_t *) sys_epoll_ctl,
[ __NR_epoll_wait ] = (syscall_handler_t *) sys_epoll_wait,
- [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
+ [ __NR_remap_file_pages ] = (syscall_handler_t *) sys_remap_file_pages,
+ [ __NR_set_tid_address ] = (syscall_handler_t *) sys_set_tid_address,
[ __NR_timer_create ] = (syscall_handler_t *) sys_timer_create,
[ __NR_timer_settime ] = (syscall_handler_t *) sys_timer_settime,
[ __NR_timer_gettime ] = (syscall_handler_t *) sys_timer_gettime,
@@ -251,12 +251,10 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_clock_gettime ] = (syscall_handler_t *) sys_clock_gettime,
[ __NR_clock_getres ] = (syscall_handler_t *) sys_clock_getres,
[ __NR_clock_nanosleep ] = (syscall_handler_t *) sys_clock_nanosleep,
- [ __NR_statfs64 ] = (syscall_handler_t *) sys_statfs64,
- [ __NR_fstatfs64 ] = (syscall_handler_t *) sys_fstatfs64,
[ __NR_tgkill ] = (syscall_handler_t *) sys_tgkill,
[ __NR_utimes ] = (syscall_handler_t *) sys_utimes,
- [ __NR_fadvise64_64 ] = (syscall_handler_t *) sys_fadvise64_64,
- [ __NR_vserver ] = (syscall_handler_t *) sys_vserver,
+ [ __NR_fadvise64 ] = (syscall_handler_t *) sys_fadvise64,
+ [ __NR_vserver ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_mbind ] = (syscall_handler_t *) sys_mbind,
[ __NR_get_mempolicy ] = (syscall_handler_t *) sys_get_mempolicy,
[ __NR_set_mempolicy ] = (syscall_handler_t *) sys_set_mempolicy,
@@ -266,14 +264,13 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_mq_timedreceive ] = (syscall_handler_t *) sys_mq_timedreceive,
[ __NR_mq_notify ] = (syscall_handler_t *) sys_mq_notify,
[ __NR_mq_getsetattr ] = (syscall_handler_t *) sys_mq_getsetattr,
- [ __NR_sys_kexec_load ] = (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_kexec_load ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_waitid ] = (syscall_handler_t *) sys_waitid,
- [ 285 ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_add_key ] = (syscall_handler_t *) sys_add_key,
[ __NR_request_key ] = (syscall_handler_t *) sys_request_key,
[ __NR_keyctl ] = (syscall_handler_t *) sys_keyctl,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
- (syscall_handler_t *) sys_ni_syscall
+ (syscall_handler_t *) sys_ni_syscall
};
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index c75d1db0efc312..5c49d88eed3d07 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -47,7 +47,7 @@ char command_line[COMMAND_LINE_SIZE] = { 0 };
void add_arg(char *arg)
{
if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) {
- printf("add_arg: Too much command line!\n");
+ printf("add_arg: Too many command line arguments!\n");
exit(1);
}
if(strlen(command_line) > 0)
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index f0c459a4bfd581..68a9ab06ee7c21 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -65,7 +65,6 @@
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
-#include <asm/ipc.h>
#include <asm/atomic.h>
#include <asm/ldt.h>
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 131d24ef9a63db..4f2a852299b63d 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -25,6 +25,8 @@
* interface to access function arguments.
* 2004-Oct Jim Keniston <kenistoj@us.ibm.com> and Prasanna S Panchamukhi
* <prasanna@in.ibm.com> adapted for x86_64
+ * 2005-Mar Roland McGrath <roland@redhat.com>
+ * Fixed to handle %rip-relative addressing mode correctly.
*/
#include <linux/config.h>
@@ -34,7 +36,7 @@
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/preempt.h>
-#include <linux/vmalloc.h>
+#include <linux/moduleloader.h>
#include <asm/pgtable.h>
#include <asm/kdebug.h>
@@ -86,9 +88,132 @@ int arch_prepare_kprobe(struct kprobe *p)
return 0;
}
+/*
+ * Determine if the instruction uses the %rip-relative addressing mode.
+ * If it does, return the address of the 32-bit displacement word.
+ * If not, return null.
+ */
+static inline s32 *is_riprel(u8 *insn)
+{
+#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf) \
+ (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) | \
+ (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) | \
+ (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) | \
+ (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf)) \
+ << (row % 64))
+ static const u64 onebyte_has_modrm[256 / 64] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ W(0x00, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 00 */
+ W(0x10, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 10 */
+ W(0x20, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0)| /* 20 */
+ W(0x30, 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0), /* 30 */
+ W(0x40, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 40 */
+ W(0x50, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 50 */
+ W(0x60, 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0)| /* 60 */
+ W(0x70, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 70 */
+ W(0x80, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 80 */
+ W(0x90, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 90 */
+ W(0xa0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* a0 */
+ W(0xb0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* b0 */
+ W(0xc0, 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0)| /* c0 */
+ W(0xd0, 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1)| /* d0 */
+ W(0xe0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* e0 */
+ W(0xf0, 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1) /* f0 */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+ static const u64 twobyte_has_modrm[256 / 64] = {
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ /* ------------------------------- */
+ W(0x00, 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1)| /* 0f */
+ W(0x10, 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0)| /* 1f */
+ W(0x20, 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1)| /* 2f */
+ W(0x30, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 3f */
+ W(0x40, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 4f */
+ W(0x50, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 5f */
+ W(0x60, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 6f */
+ W(0x70, 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1), /* 7f */
+ W(0x80, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 8f */
+ W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 9f */
+ W(0xa0, 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1)| /* af */
+ W(0xb0, 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1), /* bf */
+ W(0xc0, 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0)| /* cf */
+ W(0xd0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* df */
+ W(0xe0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* ef */
+ W(0xf0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0) /* ff */
+ /* ------------------------------- */
+ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+ };
+#undef W
+ int need_modrm;
+
+ /* Skip legacy instruction prefixes. */
+ while (1) {
+ switch (*insn) {
+ case 0x66:
+ case 0x67:
+ case 0x2e:
+ case 0x3e:
+ case 0x26:
+ case 0x64:
+ case 0x65:
+ case 0x36:
+ case 0xf0:
+ case 0xf3:
+ case 0xf2:
+ ++insn;
+ continue;
+ }
+ break;
+ }
+
+ /* Skip REX instruction prefix. */
+ if ((*insn & 0xf0) == 0x40)
+ ++insn;
+
+ if (*insn == 0x0f) { /* Two-byte opcode. */
+ ++insn;
+ need_modrm = test_bit(*insn, twobyte_has_modrm);
+ } else { /* One-byte opcode. */
+ need_modrm = test_bit(*insn, onebyte_has_modrm);
+ }
+
+ if (need_modrm) {
+ u8 modrm = *++insn;
+ if ((modrm & 0xc7) == 0x05) { /* %rip+disp32 addressing mode */
+ /* Displacement follows ModRM byte. */
+ return (s32 *) ++insn;
+ }
+ }
+
+ /* No %rip-relative addressing mode here. */
+ return NULL;
+}
+
void arch_copy_kprobe(struct kprobe *p)
{
+ s32 *ripdisp;
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE);
+ ripdisp = is_riprel(p->ainsn.insn);
+ if (ripdisp) {
+ /*
+ * The copied instruction uses the %rip-relative
+ * addressing mode. Adjust the displacement for the
+ * difference between the original location of this
+ * instruction and the location of the copy that will
+ * actually be run. The tricky bit here is making sure
+ * that the sign extension happens correctly in this
+ * calculation, since we need a signed 32-bit result to
+ * be sign-extended to 64 bits when it's added to the
+ * %rip value and yield the same 64-bit result that the
+ * sign-extension of the original signed 32-bit
+ * displacement would have given.
+ */
+ s64 disp = (u8 *) p->addr + *ripdisp - (u8 *) p->ainsn.insn;
+ BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
+ *ripdisp = disp;
+ }
}
void arch_remove_kprobe(struct kprobe *p)
@@ -108,8 +233,11 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
-
- regs->rip = (unsigned long)p->ainsn.insn;
+ /*single step inline if the instruction is an int3*/
+ if (p->opcode == BREAKPOINT_INSTRUCTION)
+ regs->rip = (unsigned long)p->addr;
+ else
+ regs->rip = (unsigned long)p->ainsn.insn;
}
/*
@@ -131,6 +259,12 @@ int kprobe_handler(struct pt_regs *regs)
Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ regs->eflags &= ~TF_MASK;
+ regs->eflags |= kprobe_saved_rflags;
+ unlock_kprobes();
+ goto no_kprobe;
+ }
disarm_kprobe(p, regs);
ret = 1;
} else {
@@ -168,17 +302,16 @@ int kprobe_handler(struct pt_regs *regs)
if (is_IF_modifier(p->ainsn.insn))
kprobe_saved_rflags &= ~IF_MASK;
- if (p->pre_handler(p, regs)) {
+ if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
return 1;
- }
- ss_probe:
+ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
return 1;
- no_kprobe:
+no_kprobe:
preempt_enable_no_resched();
return ret;
}
@@ -439,8 +572,15 @@ static kprobe_opcode_t *get_insn_slot(void)
if (!kip) {
return NULL;
}
- kip->insns = (kprobe_opcode_t*) __vmalloc(PAGE_SIZE,
- GFP_KERNEL|__GFP_HIGHMEM, __pgprot(__PAGE_KERNEL_EXEC));
+
+ /*
+ * For the %rip-relative displacement fixups to be doable, we
+ * need our instruction copy to be within +/- 2GB of any data it
+ * might access via %rip. That is, within 2GB of where the
+ * kernel image and loaded module images reside. So we allocate
+ * a page in the module loading area.
+ */
+ kip->insns = module_alloc(PAGE_SIZE);
if (!kip->insns) {
kfree(kip);
return NULL;
@@ -481,7 +621,7 @@ static void free_insn_slot(kprobe_opcode_t *slot)
hlist_add_head(&kip->hlist,
&kprobe_insn_pages);
} else {
- vfree(kip->insns);
+ module_free(NULL, kip->insns);
kfree(kip);
}
}
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 33feab9c75691e..171931ea7eaae8 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -62,7 +62,7 @@ EXPORT_SYMBOL(boot_option_idle_override);
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void);
-static cpumask_t cpu_idle_map;
+static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
void disable_hlt(void)
{
@@ -125,20 +125,31 @@ static void poll_idle (void)
}
}
-
void cpu_idle_wait(void)
{
- int cpu;
- cpumask_t map;
+ unsigned int cpu, this_cpu = get_cpu();
+ cpumask_t map;
+
+ set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
+ put_cpu();
+
+ cpus_clear(map);
+ for_each_online_cpu(cpu) {
+ per_cpu(cpu_idle_state, cpu) = 1;
+ cpu_set(cpu, map);
+ }
- for_each_online_cpu(cpu)
- cpu_set(cpu, cpu_idle_map);
+ __get_cpu_var(cpu_idle_state) = 0;
- wmb();
- do {
- ssleep(1);
- cpus_and(map, cpu_idle_map, cpu_online_map);
- } while (!cpus_empty(map));
+ wmb();
+ do {
+ ssleep(1);
+ for_each_online_cpu(cpu) {
+ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu))
+ cpu_clear(cpu, map);
+ }
+ cpus_and(map, map, cpu_online_map);
+ } while (!cpus_empty(map));
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -150,21 +161,21 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
*/
void cpu_idle (void)
{
- int cpu = smp_processor_id();
-
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
void (*idle)(void);
- if (cpu_isset(cpu, cpu_idle_map))
- cpu_clear(cpu, cpu_idle_map);
+ if (__get_cpu_var(cpu_idle_state))
+ __get_cpu_var(cpu_idle_state) = 0;
+
rmb();
idle = pm_idle;
if (!idle)
idle = default_idle;
idle();
}
+
schedule();
}
}
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index d0725cd1b9d68b..e3cdbf9a88bd7a 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -373,7 +373,10 @@ void smp_send_stop(void)
__smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
if (!nolock)
spin_unlock(&call_lock);
- smp_stop_cpu();
+
+ local_irq_disable();
+ disable_local_APIC();
+ local_irq_enable();
}
/*
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c
index 624bcf8e54731e..477d8be57d64f0 100644
--- a/arch/x86_64/kernel/sys_x86_64.c
+++ b/arch/x86_64/kernel/sys_x86_64.c
@@ -18,7 +18,6 @@
#include <linux/personality.h>
#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/ia32.h>
/*
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 894128bffc58c3..0400a52d508557 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -331,6 +331,26 @@ config ACPI_CONTAINER
This is the ACPI generic container driver which supports
ACPI0004, PNP0A05 and PNP0A06 devices
+config ACPI_HOTPLUG_MEMORY
+ tristate "Memory Hotplug"
+ depends on ACPI
+ depends on MEMORY_HOTPLUG
+ default n
+ help
+ This driver adds supports for ACPI Memory Hotplug. This driver
+ provides support for fielding notifications on ACPI memory
+ devices (PNP0C80) which represent memory ranges that may be
+ onlined or offlined during runtime.
+
+ Enabling this driver assumes that your platform hardware
+ and firmware have support for hot-plugging physical memory. If
+ your system does not support physically adding or ripping out
+ memory DIMMs at some platfrom defined granularity (individually
+ or as a bank) at runtime, then you need not enable this driver.
+
+ If one selects "m," this driver can be loaded using the following
+ command:
+ $>modprobe acpi_memhotplug
endif # ACPI
endmenu
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 1ae0d89c2d3fbc..65c92e20566d58 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o
+obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index e0f498c7b343c7..23ab761dd72176 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -51,8 +51,8 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
MODULE_LICENSE("GPL");
-int acpi_ac_add (struct acpi_device *device);
-int acpi_ac_remove (struct acpi_device *device, int type);
+static int acpi_ac_add (struct acpi_device *device);
+static int acpi_ac_remove (struct acpi_device *device, int type);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_ac_driver = {
@@ -108,9 +108,9 @@ acpi_ac_get_state (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_ac_dir;
+static struct proc_dir_entry *acpi_ac_dir;
-int acpi_ac_seq_show(struct seq_file *seq, void *offset)
+static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_ac *ac = (struct acpi_ac *) seq->private;
@@ -200,7 +200,7 @@ acpi_ac_remove_fs (
Driver Model
-------------------------------------------------------------------------- */
-void
+static void
acpi_ac_notify (
acpi_handle handle,
u32 event,
@@ -232,7 +232,7 @@ acpi_ac_notify (
}
-int
+static int
acpi_ac_add (
struct acpi_device *device)
{
@@ -286,7 +286,7 @@ end:
}
-int
+static int
acpi_ac_remove (
struct acpi_device *device,
int type)
@@ -315,7 +315,7 @@ acpi_ac_remove (
}
-int __init
+static int __init
acpi_ac_init (void)
{
int result = 0;
@@ -337,7 +337,7 @@ acpi_ac_init (void)
}
-void __exit
+static void __exit
acpi_ac_exit (void)
{
ACPI_FUNCTION_TRACE("acpi_ac_exit");
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
new file mode 100644
index 00000000000000..77285ffe41c5cb
--- /dev/null
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * ACPI based HotPlug driver that supports Memory Hotplug
+ * This driver fields notifications from firmare for memory add
+ * and remove operations and alerts the VM of the affected memory
+ * ranges.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/memory_hotplug.h>
+#include <acpi/acpi_drivers.h>
+
+
+#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL
+#define ACPI_MEMORY_DEVICE_CLASS "memory"
+#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
+#define ACPI_MEMORY_DEVICE_DRIVER_NAME "Hotplug Mem Driver"
+#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device"
+
+#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
+
+ACPI_MODULE_NAME ("acpi_memory")
+MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
+MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+/* ACPI _STA method values */
+#define ACPI_MEMORY_STA_PRESENT (0x00000001UL)
+#define ACPI_MEMORY_STA_ENABLED (0x00000002UL)
+#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL)
+
+/* Memory Device States */
+#define MEMORY_INVALID_STATE 0
+#define MEMORY_POWER_ON_STATE 1
+#define MEMORY_POWER_OFF_STATE 2
+
+static int acpi_memory_device_add (struct acpi_device *device);
+static int acpi_memory_device_remove (struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_memory_device_driver = {
+ .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
+ .class = ACPI_MEMORY_DEVICE_CLASS,
+ .ids = ACPI_MEMORY_DEVICE_HID,
+ .ops = {
+ .add = acpi_memory_device_add,
+ .remove = acpi_memory_device_remove,
+ },
+};
+
+struct acpi_memory_device {
+ acpi_handle handle;
+ unsigned int state; /* State of the memory device */
+ unsigned short cache_attribute; /* memory cache attribute */
+ unsigned short read_write_attribute;/* memory read/write attribute */
+ u64 start_addr; /* Memory Range start physical addr */
+ u64 end_addr; /* Memory Range end physical addr */
+};
+
+
+static int
+acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_resource *resource = NULL;
+ struct acpi_resource_address64 address64;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_get_device_resources");
+
+ /* Get the range from the _CRS */
+ status = acpi_get_current_resources(mem_device->handle, &buffer);
+ if (ACPI_FAILURE(status))
+ return_VALUE(-EINVAL);
+
+ resource = (struct acpi_resource *) buffer.pointer;
+ status = acpi_resource_to_address64(resource, &address64);
+ if (ACPI_SUCCESS(status)) {
+ if (address64.resource_type == ACPI_MEMORY_RANGE) {
+ /* Populate the structure */
+ mem_device->cache_attribute =
+ address64.attribute.memory.cache_attribute;
+ mem_device->read_write_attribute =
+ address64.attribute.memory.read_write_attribute;
+ mem_device->start_addr = address64.min_address_range;
+ mem_device->end_addr = address64.max_address_range;
+ }
+ }
+
+ acpi_os_free(buffer.pointer);
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_get_device(acpi_handle handle,
+ struct acpi_memory_device **mem_device)
+{
+ acpi_status status;
+ acpi_handle phandle;
+ struct acpi_device *device = NULL;
+ struct acpi_device *pdevice = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_get_device");
+
+ if (!acpi_bus_get_device(handle, &device) && device)
+ goto end;
+
+ status = acpi_get_parent(handle, &phandle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_get_parent\n"));
+ return_VALUE(-EINVAL);
+ }
+
+ /* Get the parent device */
+ status = acpi_bus_get_device(phandle, &pdevice);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_bus_get_device\n"));
+ return_VALUE(-EINVAL);
+ }
+
+ /*
+ * Now add the notified device. This creates the acpi_device
+ * and invokes .add function
+ */
+ status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_bus_add\n"));
+ return_VALUE(-EINVAL);
+ }
+
+end:
+ *mem_device = acpi_driver_data(device);
+ if (!(*mem_device)) {
+ printk(KERN_ERR "\n driver data not found" );
+ return_VALUE(-ENODEV);
+ }
+
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_check_device(struct acpi_memory_device *mem_device)
+{
+ unsigned long current_status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_check_device");
+
+ /* Get device present/absent information from the _STA */
+ if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA",
+ NULL, &current_status)))
+ return_VALUE(-ENODEV);
+ /*
+ * Check for device status. Device should be
+ * present/enabled/functioning.
+ */
+ if (!((current_status & ACPI_MEMORY_STA_PRESENT)
+ && (current_status & ACPI_MEMORY_STA_ENABLED)
+ && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
+ return_VALUE(-ENODEV);
+
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_enable_device(struct acpi_memory_device *mem_device)
+{
+ int result;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_enable_device");
+
+ /* Get the range from the _CRS */
+ result = acpi_memory_get_device_resources(mem_device);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "\nget_device_resources failed\n"));
+ mem_device->state = MEMORY_INVALID_STATE;
+ return result;
+ }
+
+ /*
+ * Tell the VM there is more memory here...
+ * Note: Assume that this function returns zero on success
+ */
+ result = add_memory(mem_device->start_addr,
+ (mem_device->end_addr - mem_device->start_addr) + 1,
+ mem_device->read_write_attribute);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "\nadd_memory failed\n"));
+ mem_device->state = MEMORY_INVALID_STATE;
+ return result;
+ }
+
+ return result;
+}
+
+static int
+acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
+{
+ acpi_status status;
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ unsigned long current_status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_powerdown_device");
+
+ /* Issue the _EJ0 command */
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = 1;
+ status = acpi_evaluate_object(mem_device->handle,
+ "_EJ0", &arg_list, NULL);
+ /* Return on _EJ0 failure */
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"_EJ0 failed.\n"));
+ return_VALUE(-ENODEV);
+ }
+
+ /* Evalute _STA to check if the device is disabled */
+ status = acpi_evaluate_integer(mem_device->handle, "_STA",
+ NULL, &current_status);
+ if (ACPI_FAILURE(status))
+ return_VALUE(-ENODEV);
+
+ /* Check for device status. Device should be disabled */
+ if (current_status & ACPI_MEMORY_STA_ENABLED)
+ return_VALUE(-EINVAL);
+
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_disable_device(struct acpi_memory_device *mem_device)
+{
+ int result;
+ u64 start = mem_device->start_addr;
+ u64 len = mem_device->end_addr - start + 1;
+ unsigned long attr = mem_device->read_write_attribute;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_disable_device");
+
+ /*
+ * Ask the VM to offline this memory range.
+ * Note: Assume that this function returns zero on success
+ */
+ result = remove_memory(start, len, attr);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n"));
+ return_VALUE(result);
+ }
+
+ /* Power-off and eject the device */
+ result = acpi_memory_powerdown_device(mem_device);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device Power Down failed.\n"));
+ /* Set the status of the device to invalid */
+ mem_device->state = MEMORY_INVALID_STATE;
+ return result;
+ }
+
+ mem_device->state = MEMORY_POWER_OFF_STATE;
+ return result;
+}
+
+static void
+acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct acpi_memory_device *mem_device;
+ struct acpi_device *device;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_notify");
+
+ switch (event) {
+ case ACPI_NOTIFY_BUS_CHECK:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "\nReceived BUS CHECK notification for device\n"));
+ /* Fall Through */
+ case ACPI_NOTIFY_DEVICE_CHECK:
+ if (event == ACPI_NOTIFY_DEVICE_CHECK)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "\nReceived DEVICE CHECK notification for device\n"));
+ if (acpi_memory_get_device(handle, &mem_device)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in finding driver data\n"));
+ return_VOID;
+ }
+
+ if (!acpi_memory_check_device(mem_device)) {
+ if (acpi_memory_enable_device(mem_device))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_memory_enable_device\n"));
+ }
+ break;
+ case ACPI_NOTIFY_EJECT_REQUEST:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "\nReceived EJECT REQUEST notification for device\n"));
+
+ if (acpi_bus_get_device(handle, &device)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device doesn't exist\n"));
+ break;
+ }
+ mem_device = acpi_driver_data(device);
+ if (!mem_device) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Driver Data is NULL\n"));
+ break;
+ }
+
+ /*
+ * Currently disabling memory device from kernel mode
+ * TBD: Can also be disabled from user mode scripts
+ * TBD: Can also be disabled by Callback registration
+ * with generic sysfs driver
+ */
+ if (acpi_memory_disable_device(mem_device))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_memory_disable_device\n"));
+ /*
+ * TBD: Invoke acpi_bus_remove to cleanup data structures
+ */
+ break;
+ default:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Unsupported event [0x%x]\n", event));
+ break;
+ }
+
+ return_VOID;
+}
+
+static int
+acpi_memory_device_add(struct acpi_device *device)
+{
+ int result;
+ struct acpi_memory_device *mem_device = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_add");
+
+ if (!device)
+ return_VALUE(-EINVAL);
+
+ mem_device = kmalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
+ if (!mem_device)
+ return_VALUE(-ENOMEM);
+ memset(mem_device, 0, sizeof(struct acpi_memory_device));
+
+ mem_device->handle = device->handle;
+ sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
+ sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
+ acpi_driver_data(device) = mem_device;
+
+ /* Get the range from the _CRS */
+ result = acpi_memory_get_device_resources(mem_device);
+ if (result) {
+ kfree(mem_device);
+ return_VALUE(result);
+ }
+
+ /* Set the device state */
+ mem_device->state = MEMORY_POWER_ON_STATE;
+
+ printk(KERN_INFO "%s \n", acpi_device_name(device));
+
+ return_VALUE(result);
+}
+
+static int
+acpi_memory_device_remove (struct acpi_device *device, int type)
+{
+ struct acpi_memory_device *mem_device = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_remove");
+
+ if (!device || !acpi_driver_data(device))
+ return_VALUE(-EINVAL);
+
+ mem_device = (struct acpi_memory_device *) acpi_driver_data(device);
+ kfree(mem_device);
+
+ return_VALUE(0);
+}
+
+/*
+ * Helper function to check for memory device
+ */
+static acpi_status
+is_memory_device(acpi_handle handle)
+{
+ char *hardware_id;
+ acpi_status status;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_device_info *info;
+
+ ACPI_FUNCTION_TRACE("is_memory_device");
+
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(AE_ERROR);
+
+ info = buffer.pointer;
+ if (!(info->valid & ACPI_VALID_HID)) {
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(AE_ERROR);
+ }
+
+ hardware_id = info->hardware_id.value;
+ if ((hardware_id == NULL) ||
+ (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
+ status = AE_ERROR;
+
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(status);
+}
+
+static acpi_status
+acpi_memory_register_notify_handler (acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_register_notify_handler");
+
+ status = is_memory_device(handle);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(AE_OK); /* continue */
+
+ status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ acpi_memory_device_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error installing notify handler\n"));
+ return_ACPI_STATUS(AE_OK); /* continue */
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+static acpi_status
+acpi_memory_deregister_notify_handler (acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_deregister_notify_handler");
+
+ status = is_memory_device(handle);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(AE_OK); /* continue */
+
+ status = acpi_remove_notify_handler(handle,
+ ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error removing notify handler\n"));
+ return_ACPI_STATUS(AE_OK); /* continue */
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+static int __init
+acpi_memory_device_init (void)
+{
+ int result;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_init");
+
+ result = acpi_bus_register_driver(&acpi_memory_device_driver);
+
+ if (result < 0)
+ return_VALUE(-ENODEV);
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_memory_register_notify_handler,
+ NULL, NULL);
+
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+ acpi_bus_unregister_driver(&acpi_memory_device_driver);
+ return_VALUE(-ENODEV);
+ }
+
+ return_VALUE(0);
+}
+
+static void __exit
+acpi_memory_device_exit (void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_exit");
+
+ /*
+ * Adding this to un-install notification handlers for all the device
+ * handles.
+ */
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_memory_deregister_notify_handler,
+ NULL, NULL);
+
+ if (ACPI_FAILURE (status))
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+
+ acpi_bus_unregister_driver(&acpi_memory_device_driver);
+
+ return_VOID;
+}
+
+module_init(acpi_memory_device_init);
+module_exit(acpi_memory_device_exit);
+
+
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index a10de067dbb631..c55feca9b7d5e0 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -341,7 +341,7 @@ acpi_battery_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_battery_dir;
+static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
int result = 0;
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 31aded126ce88c..ec4430e3053ffb 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -275,7 +275,7 @@ acpi_button_remove_fs (
Driver Interface
-------------------------------------------------------------------------- */
-void
+static void
acpi_button_notify (
acpi_handle handle,
u32 event,
@@ -302,7 +302,7 @@ acpi_button_notify (
}
-acpi_status
+static acpi_status
acpi_button_notify_fixed (
void *data)
{
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 060251b5e49c83..5a0adbf8bc0454 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -177,13 +177,18 @@ container_notify_cb(acpi_handle handle, u32 type, void *context)
printk("Container driver received %s event\n",
(type == ACPI_NOTIFY_BUS_CHECK)?
"ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
+ status = acpi_bus_get_device(handle, &device);
if (present) {
- status = acpi_bus_get_device(handle, &device);
if (ACPI_FAILURE(status) || !device) {
result = container_device_add(&device, handle);
if (!result)
- kobject_hotplug(&device->kobj, KOBJ_ONLINE);
- } else {
+ kobject_hotplug(&device->kobj,
+ KOBJ_ONLINE);
+ else
+ printk("Failed to add container\n");
+ }
+ } else {
+ if (ACPI_SUCCESS(status)) {
/* device exist and this is a remove request */
kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
}
@@ -255,7 +260,7 @@ end:
}
-int __init
+static int __init
acpi_container_init(void)
{
int result = 0;
@@ -276,7 +281,7 @@ acpi_container_init(void)
return(0);
}
-void __exit
+static void __exit
acpi_container_exit(void)
{
int action = UNINSTALL_NOTIFY_HANDLER;
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index d947e2a0a46291..2c0dac559f1636 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -35,7 +35,7 @@ struct acpi_dlevel {
};
#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
-const struct acpi_dlayer acpi_debug_layers[] =
+static const struct acpi_dlayer acpi_debug_layers[] =
{
ACPI_DEBUG_INIT(ACPI_UTILITIES),
ACPI_DEBUG_INIT(ACPI_HARDWARE),
@@ -53,7 +53,7 @@ const struct acpi_dlayer acpi_debug_layers[] =
ACPI_DEBUG_INIT(ACPI_TOOLS),
};
-const struct acpi_dlevel acpi_debug_levels[] =
+static const struct acpi_dlevel acpi_debug_levels[] =
{
ACPI_DEBUG_INIT(ACPI_LV_ERROR),
ACPI_DEBUG_INIT(ACPI_LV_WARN),
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index fac39ba4a7b44d..9f0456cb9bb55c 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -448,7 +448,16 @@ acpi_ds_restart_control_method (
*/
walk_state->return_desc = return_desc;
}
- else {
+
+ /*
+ * The following code is the
+ * optional support for a so-called "implicit return". Some AML code
+ * assumes that the last value of the method is "implicitly" returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not actually
+ * support this behavior.
+ */
+ else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) {
/*
* Delete the return value if it will not be used by the
* calling method
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 66fc7549c68830..5c987a0e7b75e8 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -1010,6 +1010,10 @@ acpi_ds_exec_end_control_op (
* has been bubbled up the tree
*/
if (op->common.value.arg) {
+ /* Since we have a real Return(), delete any implicit return */
+
+ acpi_ds_clear_implicit_return (walk_state);
+
/* Return statement has an immediate operand */
status = acpi_ds_create_operands (walk_state, op->common.value.arg);
@@ -1036,6 +1040,10 @@ acpi_ds_exec_end_control_op (
}
else if ((walk_state->results) &&
(walk_state->results->results.num_results > 0)) {
+ /* Since we have a real Return(), delete any implicit return */
+
+ acpi_ds_clear_implicit_return (walk_state);
+
/*
* The return value has come from a previous calculation.
*
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index df6b0018677905..462c5d83e747fe 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -54,10 +54,120 @@
ACPI_MODULE_NAME ("dsutils")
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_clear_implicit_return
+ *
+ * PARAMETERS: walk_state - Current State
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
+ * to delete "stale" return values (if enabled, the return value
+ * from every operator is saved at least momentarily, in case the
+ * parent method exits.)
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_clear_implicit_return (
+ struct acpi_walk_state *walk_state)
+{
+ ACPI_FUNCTION_NAME ("ds_clear_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature
+ */
+ if (!acpi_gbl_enable_interpreter_slack) {
+ return;
+ }
+
+ if (walk_state->implicit_return_obj) {
+ /*
+ * Delete any "stale" implicit return. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Removing reference on stale implicit return obj %p\n",
+ walk_state->implicit_return_obj));
+
+ acpi_ut_remove_reference (walk_state->implicit_return_obj);
+ walk_state->implicit_return_obj = NULL;
+ }
+}
+
+
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
+ * FUNCTION: acpi_ds_do_implicit_return
+ *
+ * PARAMETERS: return_desc - The return value
+ * walk_state - Current State
+ * add_reference - True if a reference should be added to the
+ * return object
+ *
+ * RETURN: TRUE if implicit return enabled, FALSE otherwise
+ *
+ * DESCRIPTION: Implements the optional "implicit return". We save the result
+ * of every ASL operator and control method invocation in case the
+ * parent method exit. Before storing a new return value, we
+ * delete the previous return value.
+ *
+ ******************************************************************************/
+
+u8
+acpi_ds_do_implicit_return (
+ union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference)
+{
+ ACPI_FUNCTION_NAME ("ds_do_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature, and we must
+ * have a valid return object
+ */
+ if ((!acpi_gbl_enable_interpreter_slack) ||
+ (!return_desc)) {
+ return (FALSE);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Result %p will be implicitly returned; Prev=%p\n",
+ return_desc,
+ walk_state->implicit_return_obj));
+
+ /*
+ * Delete any "stale" implicit return value first. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels, so we don't clear the value if it
+ * is the same as the return_desc.
+ */
+ if (walk_state->implicit_return_obj) {
+ if (walk_state->implicit_return_obj == return_desc) {
+ return (TRUE);
+ }
+ acpi_ds_clear_implicit_return (walk_state);
+ }
+
+ /* Save the implicit return value, add a reference if requested */
+
+ walk_state->implicit_return_obj = return_desc;
+ if (add_reference) {
+ acpi_ut_add_reference (return_desc);
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ds_is_result_used
*
* PARAMETERS: Op - Current Op
@@ -76,7 +186,6 @@ acpi_ds_is_result_used (
{
const struct acpi_opcode_info *parent_info;
-
ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
@@ -88,6 +197,19 @@ acpi_ds_is_result_used (
}
/*
+ * We know that this operator is not a
+ * Return() operator (would not come here.) The following code is the
+ * optional support for a so-called "implicit return". Some AML code
+ * assumes that the last value of the method is "implicitly" returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not actually
+ * support this behavior.
+ */
+ acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE);
+
+ /*
+ * Now determine if the parent will use the result
+ *
* If there is no parent, or the parent is a scope_op, we are executing
* at the method level. An executing method typically has no parent,
* since each method is parsed separately. A method invoked externally
@@ -95,29 +217,10 @@ acpi_ds_is_result_used (
*/
if ((!op->common.parent) ||
(op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
- /*
- * If this is the last statement in the method, we know it is not a
- * Return() operator (would not come here.) The following code is the
- * optional support for a so-called "implicit return". Some AML code
- * assumes that the last value of the method is "implicitly" returned
- * to the caller. Just save the last result as the return value.
- * NOTE: this is optional because the ASL language does not actually
- * support this behavior.
- */
- if ((acpi_gbl_enable_interpreter_slack) &&
- (walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result of [%s] will be implicitly returned\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode)));
-
- /* Use the top of the result stack as the implicit return value */
-
- walk_state->return_desc = walk_state->results->results.obj_desc[0];
- return_VALUE (TRUE);
- }
-
/* No parent, the return value cannot possibly be used */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n",
+ acpi_ps_get_opcode_name (op->common.aml_opcode)));
return_VALUE (FALSE);
}
@@ -262,9 +365,8 @@ acpi_ds_delete_result_if_not_used (
}
if (!acpi_ds_is_result_used (op, walk_state)) {
- /*
- * Must pop the result stack (obj_desc should be equal to result_obj)
- */
+ /* Must pop the result stack (obj_desc should be equal to result_obj) */
+
status = acpi_ds_result_pop (&obj_desc, walk_state);
if (ACPI_SUCCESS (status)) {
acpi_ut_remove_reference (result_obj);
@@ -338,9 +440,8 @@ acpi_ds_clear_operands (
ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state);
- /*
- * Remove a reference on each operand on the stack
- */
+ /* Remove a reference on each operand on the stack */
+
for (i = 0; i < walk_state->num_operands; i++) {
/*
* Remove a reference to all operands, including both
@@ -407,11 +508,7 @@ acpi_ds_create_operand (
return_ACPI_STATUS (status);
}
- /*
- * All prefixes have been handled, and the name is
- * in name_string
- */
-
+ /* All prefixes have been handled, and the name is in name_string */
/*
* Special handling for buffer_field declarations. This is a deferred
@@ -586,7 +683,8 @@ acpi_ds_create_operand (
*
* FUNCTION: acpi_ds_create_operands
*
- * PARAMETERS: first_arg - First argument of a parser argument tree
+ * PARAMETERS: walk_state - Current state
+ * first_arg - First argument of a parser argument tree
*
* RETURN: Status
*
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index b02322e213de9d..2071a0d2bbbb95 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -91,6 +91,7 @@ acpi_ds_get_predicate_value (
union acpi_operand_object *result_obj) {
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
+ union acpi_operand_object *local_obj_desc = NULL;
ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state);
@@ -130,12 +131,17 @@ acpi_ds_get_predicate_value (
}
/*
- * Result of predicate evaluation currently must
- * be a number
+ * Result of predicate evaluation must be an Integer
+ * object. Implicitly convert the argument if necessary.
*/
- if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER) {
+ status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad predicate (not a number) obj_desc=%p State=%p Type=%X\n",
+ "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc)));
status = AE_AML_OPERAND_TYPE;
@@ -144,13 +150,13 @@ acpi_ds_get_predicate_value (
/* Truncate the predicate to 32-bits if necessary */
- acpi_ex_truncate_for32bit_table (obj_desc);
+ acpi_ex_truncate_for32bit_table (local_obj_desc);
/*
* Save the result of the predicate evaluation on
* the control stack
*/
- if (obj_desc->integer.value) {
+ if (local_obj_desc->integer.value) {
walk_state->control_state->common.value = TRUE;
}
else {
@@ -170,12 +176,15 @@ cleanup:
/* Break to debugger to display result */
- ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state));
+ ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state));
/*
* Delete the predicate result object (we know that
* we don't need it anymore)
*/
+ if (local_obj_desc != obj_desc) {
+ acpi_ut_remove_reference (local_obj_desc);
+ }
acpi_ut_remove_reference (obj_desc);
walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
@@ -306,9 +315,10 @@ acpi_ds_exec_begin_op (
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
- /* most operators with arguments */
- /* Start a new result/operand state */
-
+ /*
+ * Most operators with arguments.
+ * Start a new result/operand state
+ */
status = acpi_ds_result_stack_push (walk_state);
break;
@@ -471,20 +481,41 @@ acpi_ds_exec_end_op (
/* 1 Operand, 0 external_result, 0 internal_result */
status = acpi_ds_exec_end_control_op (walk_state, op);
- if (ACPI_FAILURE (status)) {
- break;
- }
- status = acpi_ds_result_stack_pop (walk_state);
+ /* Make sure to properly pop the result stack */
+
+ if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ }
+ else if (status == AE_CTRL_PENDING) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ if (ACPI_SUCCESS (status)) {
+ status = AE_CTRL_PENDING;
+ }
+ }
break;
case AML_TYPE_METHOD_CALL:
+ /*
+ * If the method is referenced from within a package
+ * declaration, it is not a invocation of the method, just
+ * a reference to it.
+ */
+ if ((op->asl.parent) &&
+ ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) ||
+ (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", op));
+ op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object;
+ acpi_ut_add_reference (op->asl.value.arg->asl.node->object);
+ return_ACPI_STATUS (AE_OK);
+ }
+
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op));
/*
- * (AML_METHODCALL) Op->Value->Arg->Node contains
+ * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
* the method Node pointer
*/
/* next_op points to the op that holds the method name */
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 8d4219388c9a8d..fdf143b405be7f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -514,7 +514,7 @@ out:
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_ec_dir;
+static struct proc_dir_entry *acpi_ec_dir;
static int
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index a48820152ccdc8..0bfec10a5f1e90 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -149,7 +149,9 @@ acpi_install_fixed_event_handler (
acpi_gbl_fixed_event_handlers[event].handler = handler;
acpi_gbl_fixed_event_handlers[event].context = context;
- status = acpi_enable_event (event, 0);
+ status = acpi_clear_event (event);
+ if (ACPI_SUCCESS(status))
+ status = acpi_enable_event (event, 0);
if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index fc54d4d0ccabea..b542dcd58c0742 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -95,6 +95,7 @@ acpi_ex_get_object_reference (
switch (obj_desc->reference.opcode) {
case AML_LOCAL_OP:
case AML_ARG_OP:
+ case AML_DEBUG_OP:
/* The referenced object is the pseudo-node for the local/arg */
@@ -103,7 +104,7 @@ acpi_ex_get_object_reference (
default:
- ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n",
+ ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n",
obj_desc->reference.opcode));
return_ACPI_STATUS (AE_AML_INTERNAL);
}
@@ -121,7 +122,7 @@ acpi_ex_get_object_reference (
default:
- ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n",
+ ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n",
ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
return_ACPI_STATUS (AE_TYPE);
}
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 23964e70a89bf5..8be4d80ceed594 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -442,6 +442,12 @@ acpi_ex_opcode_2A_1T_1R (
return_desc->reference.object = operand[0];
}
+ /*
+ * Add a reference to the target package/buffer/string for the life
+ * of the index.
+ */
+ acpi_ut_add_reference (operand[0]);
+
/* Complete the Index reference object */
return_desc->reference.opcode = AML_INDEX_OP;
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 9cccf8299dd835..7be60491115684 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -422,6 +422,12 @@ acpi_ex_resolve_multiple (
* This could of course in turn be another reference object.
*/
obj_desc = *(obj_desc->reference.where);
+ if (!obj_desc) {
+ /* NULL package elements are allowed */
+
+ type = 0; /* Uninitialized */
+ goto exit;
+ }
break;
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index e663a48f8a1cb6..d3677feb07fd9b 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -206,7 +206,6 @@ acpi_ex_store_object_to_object (
{
union acpi_operand_object *actual_src_desc;
acpi_status status = AE_OK;
- acpi_object_type original_src_type;
ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc);
@@ -223,8 +222,7 @@ acpi_ex_store_object_to_object (
return_ACPI_STATUS (status);
}
- original_src_type = ACPI_GET_OBJECT_TYPE (source_desc);
- if (original_src_type != ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) {
/*
* The source type does not match the type of the destination.
* Perform the "implicit conversion" of the source to the current type
@@ -275,8 +273,7 @@ acpi_ex_store_object_to_object (
* Note: There is different store behavior depending on the original
* source type
*/
- status = acpi_ex_store_buffer_to_buffer (original_src_type, actual_src_desc,
- dest_desc);
+ status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc);
break;
case ACPI_TYPE_PACKAGE:
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index 4e2b442ee5a391..05e1ecae8d92be 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -66,7 +66,6 @@
acpi_status
acpi_ex_store_buffer_to_buffer (
- acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc)
{
@@ -77,9 +76,8 @@ acpi_ex_store_buffer_to_buffer (
ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc);
- /*
- * We know that source_desc is a buffer by now
- */
+ /* We know that source_desc is a buffer by now */
+
buffer = (u8 *) source_desc->buffer.pointer;
length = source_desc->buffer.length;
@@ -105,7 +103,17 @@ acpi_ex_store_buffer_to_buffer (
ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length);
ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
+#ifdef ACPI_OBSOLETE_BEHAVIOR
+ /*
+ * NOTE: ACPI versions up to 3.0 specified that the buffer must be
+ * truncated if the string is smaller than the buffer. However, "other"
+ * implementations of ACPI never did this and thus became the defacto
+ * standard. ACPi 3.0_a changes this behavior such that the buffer
+ * is no longer truncated.
+ */
+
/*
+ * OBSOLETE BEHAVIOR:
* If the original source was a string, we must truncate the buffer,
* according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
* copy must not truncate the original buffer.
@@ -115,6 +123,7 @@ acpi_ex_store_buffer_to_buffer (
target_desc->buffer.length = length;
}
+#endif
}
else {
/* Truncate the source, copy only what will fit */
@@ -159,9 +168,8 @@ acpi_ex_store_string_to_string (
ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc);
- /*
- * We know that source_desc is a string by now.
- */
+ /* We know that source_desc is a string by now */
+
buffer = (u8 *) source_desc->string.pointer;
length = source_desc->string.length;
@@ -185,9 +193,8 @@ acpi_ex_store_string_to_string (
*/
if (target_desc->string.pointer &&
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
- /*
- * Only free if not a pointer into the DSDT
- */
+ /* Only free if not a pointer into the DSDT */
+
ACPI_MEM_FREE (target_desc->string.pointer);
}
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 2c5422dfecb5af..14192ee55f8f1d 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -50,8 +50,8 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
MODULE_LICENSE("GPL");
-int acpi_fan_add (struct acpi_device *device);
-int acpi_fan_remove (struct acpi_device *device, int type);
+static int acpi_fan_add (struct acpi_device *device);
+static int acpi_fan_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_fan_driver = {
.name = ACPI_FAN_DRIVER_NAME,
@@ -72,27 +72,24 @@ struct acpi_fan {
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_fan_dir;
+static struct proc_dir_entry *acpi_fan_dir;
static int
acpi_fan_read_state (struct seq_file *seq, void *offset)
{
- struct acpi_fan *fan = (struct acpi_fan *) seq->private;
+ struct acpi_fan *fan = seq->private;
int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_read_state");
- if (!fan)
- goto end;
-
- if (acpi_bus_get_power(fan->handle, &state))
- goto end;
-
- seq_printf(seq, "status: %s\n",
- !state?"on":"off");
-
-end:
+ if (fan) {
+ if (acpi_bus_get_power(fan->handle, &state))
+ seq_printf(seq, "status: ERROR\n");
+ else
+ seq_printf(seq, "status: %s\n",
+ !state?"on":"off");
+ }
return_VALUE(0);
}
@@ -197,7 +194,7 @@ acpi_fan_remove_fs (
Driver Interface
-------------------------------------------------------------------------- */
-int
+static int
acpi_fan_add (
struct acpi_device *device)
{
@@ -243,7 +240,7 @@ end:
}
-int
+static int
acpi_fan_remove (
struct acpi_device *device,
int type)
@@ -265,7 +262,7 @@ acpi_fan_remove (
}
-int __init
+static int __init
acpi_fan_init (void)
{
int result = 0;
@@ -287,7 +284,7 @@ acpi_fan_init (void)
}
-void __exit
+static void __exit
acpi_fan_exit (void)
{
ACPI_FUNCTION_TRACE("acpi_fan_exit");
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 94a76e520e213e..0fb731a470dce9 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -155,7 +155,7 @@ struct ibm_struct {
int experimental;
};
-struct proc_dir_entry *proc_dir = NULL;
+static struct proc_dir_entry *proc_dir = NULL;
#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -856,7 +856,7 @@ static int beep_write(struct ibm_struct *ibm, char *buf)
return 0;
}
-struct ibm_struct ibms[] = {
+static struct ibm_struct ibms[] = {
{
.name = "driver",
.init = driver_init,
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 9bfce46cd435e2..a82834b32752b0 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -170,7 +170,7 @@ acpi_table_parse_srat (
int __init
-acpi_numa_init()
+acpi_numa_init(void)
{
int result;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 94a511315c8ba9..5a9128de62261f 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -563,7 +563,7 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ
}
/* TODO: Change code to take advantage of driver model more */
-void
+static void
acpi_os_derive_pci_id_2 (
acpi_handle rhandle, /* upper bound */
acpi_handle chandle, /* current node */
@@ -1071,7 +1071,7 @@ acpi_os_signal (
}
EXPORT_SYMBOL(acpi_os_signal);
-int __init
+static int __init
acpi_os_name_setup(char *str)
{
char *p = acpi_os_name;
@@ -1101,7 +1101,7 @@ __setup("acpi_os_name=", acpi_os_name_setup);
* empty string disables _OSI
* TBD additional string adds to _OSI
*/
-int __init
+static int __init
acpi_osi_setup(char *str)
{
if (str == NULL || *str == '\0') {
@@ -1119,7 +1119,7 @@ acpi_osi_setup(char *str)
__setup("acpi_osi=", acpi_osi_setup);
/* enable serialization to combat AE_ALREADY_EXISTS errors */
-int __init
+static int __init
acpi_serialize_setup(char *str)
{
printk(KERN_INFO PREFIX "serialize enabled\n");
@@ -1140,7 +1140,7 @@ __setup("acpi_serialize", acpi_serialize_setup);
* Run-time events on the same GPE this flag is available
* to tell Linux to keep the wake-time GPEs enabled at run-time.
*/
-int __init
+static int __init
acpi_wake_gpes_always_on_setup(char *str)
{
printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index c1360fc23cee18..03e33fedc11a2f 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -522,7 +522,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
-/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R),
/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index fd2751f512e37d..e79edb53cb3b96 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -1187,8 +1187,8 @@ acpi_ps_parse_aml (
previous_walk_state = walk_state;
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, State=%p\n",
- walk_state->return_desc, walk_state));
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, implicit_value=%p State=%p\n",
+ walk_state->return_desc, walk_state->implicit_return_obj, walk_state));
/* Check if we have restarted a preempted walk */
@@ -1200,8 +1200,20 @@ acpi_ps_parse_aml (
* If the method return value is not used by the parent,
* The object is deleted
*/
- status = acpi_ds_restart_control_method (walk_state,
- previous_walk_state->return_desc);
+ if (!previous_walk_state->return_desc) {
+ status = acpi_ds_restart_control_method (walk_state,
+ previous_walk_state->implicit_return_obj);
+ }
+ else {
+ /*
+ * We have a valid return value, delete any implicit
+ * return value.
+ */
+ acpi_ds_clear_implicit_return (previous_walk_state);
+
+ status = acpi_ds_restart_control_method (walk_state,
+ previous_walk_state->return_desc);
+ }
if (ACPI_SUCCESS (status)) {
walk_state->walk_type |= ACPI_WALK_METHOD_RESTART;
}
@@ -1218,12 +1230,26 @@ acpi_ps_parse_aml (
* value (if any)
*/
else if (previous_walk_state->caller_return_desc) {
- *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; /* NULL if no return value */
+ if (previous_walk_state->implicit_return_obj) {
+ *(previous_walk_state->caller_return_desc) = previous_walk_state->implicit_return_obj;
+ }
+ else {
+ /* NULL if no return value */
+
+ *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc;
+ }
}
- else if (previous_walk_state->return_desc) {
- /* Caller doesn't want it, must delete it */
+ else {
+ if (previous_walk_state->return_desc) {
+ /* Caller doesn't want it, must delete it */
- acpi_ut_remove_reference (previous_walk_state->return_desc);
+ acpi_ut_remove_reference (previous_walk_state->return_desc);
+ }
+ if (previous_walk_state->implicit_return_obj) {
+ /* Caller doesn't want it, must delete it */
+
+ acpi_ut_remove_reference (previous_walk_state->implicit_return_obj);
+ }
}
acpi_ds_delete_walk_state (previous_walk_state);
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index e04b1b73606b95..110d2ce917b643 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -44,7 +44,6 @@
#include <acpi/acpi.h>
#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME ("pswalk")
@@ -52,256 +51,65 @@
/*******************************************************************************
*
- * FUNCTION: acpi_ps_get_next_walk_op
+ * FUNCTION: acpi_ps_delete_parse_tree
*
- * PARAMETERS: walk_state - Current state of the walk
- * Op - Current Op to be walked
- * ascending_callback - Procedure called when Op is complete
+ * PARAMETERS: subtree_root - Root of tree (or subtree) to delete
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: Get the next Op in a walk of the parse tree.
+ * DESCRIPTION: Delete a portion of or an entire parse tree.
*
******************************************************************************/
-acpi_status
-acpi_ps_get_next_walk_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_parse_upwards ascending_callback)
+void
+acpi_ps_delete_parse_tree (
+ union acpi_parse_object *subtree_root)
{
- union acpi_parse_object *next;
- union acpi_parse_object *parent;
- union acpi_parse_object *grand_parent;
- acpi_status status;
+ union acpi_parse_object *op = subtree_root;
+ union acpi_parse_object *next = NULL;
+ union acpi_parse_object *parent = NULL;
- ACPI_FUNCTION_TRACE_PTR ("ps_get_next_walk_op", op);
+ ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
- /* Check for a argument only if we are descending in the tree */
+ /* Visit all nodes in the subtree */
- if (walk_state->next_op_info != ACPI_NEXT_OP_UPWARD) {
- /* Look for an argument or child of the current op */
+ while (op) {
+ /* Check if we are not ascending */
- next = acpi_ps_get_arg (op, 0);
- if (next) {
- /* Still going downward in tree (Op is not completed yet) */
+ if (op != parent) {
+ /* Look for an argument or child of the current op */
- walk_state->prev_op = op;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
+ next = acpi_ps_get_arg (op, 0);
+ if (next) {
+ /* Still going downward in tree (Op is not completed yet) */
- return_ACPI_STATUS (AE_OK);
+ op = next;
+ continue;
+ }
}
/*
- * No more children, this Op is complete. Save Next and Parent
- * in case the Op object gets deleted by the callback routine
+ * No more children, this Op is complete.
*/
- next = op->common.next;
- parent = op->common.parent;
-
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
+ next = op->common.next;
+ parent = op->common.parent;
- status = ascending_callback (walk_state);
+ acpi_ps_free_op (op);
/*
* If we are back to the starting point, the walk is complete.
*/
- if (op == walk_state->origin) {
- /* Reached the point of origin, the walk is complete */
-
- walk_state->prev_op = op;
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (status);
+ if (op == subtree_root) {
+ return_VOID;
}
-
- /*
- * Check for a sibling to the current op. A sibling means
- * we are still going "downward" in the tree.
- */
if (next) {
- /* There is a sibling, it will be next */
-
- walk_state->prev_op = op;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- /* Continue downward */
-
- return_ACPI_STATUS (status);
+ op = next;
}
-
- /*
- * Drop into the loop below because we are moving upwards in
- * the tree
- */
- }
- else {
- /*
- * We are resuming a walk, and we were (are) going upward in the tree.
- * So, we want to drop into the parent loop below.
- */
- parent = op;
- }
-
- /*
- * Look for a sibling of the current Op's parent
- * Continue moving up the tree until we find a node that has not been
- * visited, or we get back to where we started.
- */
- while (parent) {
- /* We are moving up the tree, therefore this parent Op is complete */
-
- grand_parent = parent->common.parent;
- next = parent->common.next;
-
- walk_state->op = parent;
- walk_state->op_info = acpi_ps_get_opcode_info (parent->common.aml_opcode);
- walk_state->opcode = parent->common.aml_opcode;
-
- status = ascending_callback (walk_state);
-
- /*
- * If we are back to the starting point, the walk is complete.
- */
- if (parent == walk_state->origin) {
- /* Reached the point of origin, the walk is complete */
-
- walk_state->prev_op = parent;
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (status);
- }
-
- /*
- * If there is a sibling to this parent (it is not the starting point
- * Op), then we will visit it.
- */
- if (next) {
- /* found sibling of parent */
-
- walk_state->prev_op = parent;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- return_ACPI_STATUS (status);
+ else {
+ op = parent;
}
-
- /* No siblings, no errors, just move up one more level in the tree */
-
- op = parent;
- parent = grand_parent;
- walk_state->prev_op = op;
}
-
-
- /*
- * Got all the way to the top of the tree, we must be done!
- * However, the code should have terminated in the loop above
- */
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_completed_op
- *
- * PARAMETERS: State - Walk state
- * Op - Completed op
- *
- * RETURN: AE_OK
- *
- * DESCRIPTION: Callback function for acpi_ps_get_next_walk_op(). Used during
- * acpi_ps_delete_parse tree to delete Op objects when all sub-objects
- * have been visited (and deleted.)
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ps_delete_completed_op (
- struct acpi_walk_state *walk_state)
-{
-
- acpi_ps_free_op (walk_state->op);
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_parse_tree
- *
- * PARAMETERS: subtree_root - Root of tree (or subtree) to delete
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete a portion of or an entire parse tree.
- *
- ******************************************************************************/
-
-void
-acpi_ps_delete_parse_tree (
- union acpi_parse_object *subtree_root)
-{
- struct acpi_walk_state *walk_state;
- struct acpi_thread_state *thread;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
-
-
- if (!subtree_root) {
- return_VOID;
- }
-
- /* Create and initialize a new walk list */
-
- thread = acpi_ut_create_thread_state ();
- if (!thread) {
- return_VOID;
- }
-
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, thread);
- if (!walk_state) {
- return_VOID;
- }
-
- walk_state->parse_flags = 0;
- walk_state->descending_callback = NULL;
- walk_state->ascending_callback = NULL;
-
- walk_state->origin = subtree_root;
- walk_state->next_op = subtree_root;
-
- /* Head downward in the tree */
-
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- /* Visit all nodes in the subtree */
-
- while (walk_state->next_op) {
- status = acpi_ps_get_next_walk_op (walk_state, walk_state->next_op,
- acpi_ps_delete_completed_op);
- if (ACPI_FAILURE (status)) {
- break;
- }
- }
-
- /* We are done with this walk */
-
- acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread));
- acpi_ds_delete_walk_state (walk_state);
-
return_VOID;
}
-
-
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index a4750192a31995..12b0eea6340733 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -42,8 +42,8 @@
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME ("pci_irq")
-struct acpi_prt_list acpi_prt;
-DEFINE_SPINLOCK(acpi_prt_lock);
+static struct acpi_prt_list acpi_prt;
+static DEFINE_SPINLOCK(acpi_prt_lock);
/* --------------------------------------------------------------------------
PCI IRQ Routing Table (PRT) Support
@@ -281,7 +281,8 @@ acpi_pci_irq_lookup (
int device,
int pin,
int *edge_level,
- int *active_high_low)
+ int *active_high_low,
+ char **link)
{
struct acpi_prt_entry *entry = NULL;
int segment = pci_domain_nr(bus);
@@ -301,7 +302,8 @@ acpi_pci_irq_lookup (
}
if (entry->link.handle) {
- irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low);
+ irq = acpi_pci_link_get_irq(entry->link.handle,
+ entry->link.index, edge_level, active_high_low, link);
if (irq < 0) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
return_VALUE(-1);
@@ -327,7 +329,8 @@ acpi_pci_irq_derive (
struct pci_dev *dev,
int pin,
int *edge_level,
- int *active_high_low)
+ int *active_high_low,
+ char **link)
{
struct pci_dev *bridge = dev;
int irq = -1;
@@ -360,7 +363,7 @@ acpi_pci_irq_derive (
}
irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
- pin, edge_level, active_high_low);
+ pin, edge_level, active_high_low, link);
}
if (irq < 0) {
@@ -389,6 +392,7 @@ acpi_pci_irq_enable (
int edge_level = ACPI_LEVEL_SENSITIVE;
int active_high_low = ACPI_ACTIVE_LOW;
extern int via_interrupt_line_quirk;
+ char *link = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
@@ -411,21 +415,23 @@ acpi_pci_irq_enable (
* First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
* values override any BIOS-assigned IRQs set during boot.
*/
- irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low);
+ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
+ &edge_level, &active_high_low, &link);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (irq < 0)
- irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low);
+ irq = acpi_pci_irq_derive(dev, pin, &edge_level,
+ &active_high_low, &link);
/*
* No IRQ known to the ACPI subsystem - maybe the BIOS /
* driver reported one, then use it. Exit in any case.
*/
if (irq < 0) {
- printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI",
+ printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI",
pci_name(dev), ('A' + pin));
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq >= 0 && (dev->irq <= 0xF)) {
@@ -443,9 +449,13 @@ acpi_pci_irq_enable (
dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
- printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI %u "
- "(%s, %s) -> IRQ %d\n",
- pci_name(dev), 'A' + pin, irq,
+ printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
+ pci_name(dev), 'A' + pin);
+
+ if (link)
+ printk("Link [%s] -> ", link);
+
+ printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
(edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high",
dev->irq);
@@ -482,14 +492,14 @@ acpi_pci_irq_disable (
* First we check the PCI IRQ routing table (PRT) for an IRQ.
*/
gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low);
+ &edge_level, &active_high_low, NULL);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (gsi < 0)
gsi = acpi_pci_irq_derive(dev, pin,
- &edge_level, &active_high_low);
+ &edge_level, &active_high_low, NULL);
if (gsi < 0)
return_VOID;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 3191b5ff105e1a..520b28ad0740e6 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -522,9 +522,11 @@ acpi_irq_penalty_init(void)
static int acpi_irq_balance; /* 0: static, 1: balance */
-static int acpi_pci_link_allocate(struct acpi_pci_link* link) {
- int irq;
- int i;
+static int acpi_pci_link_allocate(
+ struct acpi_pci_link *link)
+{
+ int irq;
+ int i;
ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
@@ -597,8 +599,9 @@ int
acpi_pci_link_get_irq (
acpi_handle handle,
int index,
- int* edge_level,
- int* active_high_low)
+ int *edge_level,
+ int *active_high_low,
+ char **name)
{
int result = 0;
struct acpi_device *device = NULL;
@@ -634,6 +637,7 @@ acpi_pci_link_get_irq (
if (edge_level) *edge_level = link->irq.edge_level;
if (active_high_low) *active_high_low = link->irq.active_high_low;
+ if (name) *name = acpi_device_bid(link->device);
return_VALUE(link->irq.active);
}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 2adaba68b85b7f..7e6b8e3b2ed418 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -258,7 +258,7 @@ acpi_pci_root_add (
/* TBD: Locking */
list_add_tail(&root->node, &acpi_pci_roots);
- printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x)\n",
+ printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
acpi_device_name(device), acpi_device_bid(device),
root->id.segment, root->id.bus);
@@ -272,7 +272,7 @@ acpi_pci_root_add (
root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
if (!root->bus) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Bus %02x:%02x not present in PCI namespace\n",
+ "Bus %04x:%02x not present in PCI namespace\n",
root->id.segment, root->id.bus));
result = -ENODEV;
goto end;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 419b371d95ad83..373a3a95bb4e1b 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -58,8 +58,8 @@ ACPI_MODULE_NAME ("acpi_power")
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
-int acpi_power_add (struct acpi_device *device);
-int acpi_power_remove (struct acpi_device *device, int type);
+static int acpi_power_add (struct acpi_device *device);
+static int acpi_power_remove (struct acpi_device *device, int type);
static int acpi_power_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_power_driver = {
@@ -479,7 +479,7 @@ end:
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_power_dir;
+static struct proc_dir_entry *acpi_power_dir;
static int acpi_power_seq_show(struct seq_file *seq, void *offset)
{
@@ -576,7 +576,7 @@ acpi_power_remove_fs (
Driver Interface
-------------------------------------------------------------------------- */
-int
+static int
acpi_power_add (
struct acpi_device *device)
{
@@ -642,7 +642,7 @@ end:
}
-int
+static int
acpi_power_remove (
struct acpi_device *device,
int type)
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index e517a11dc9c688..f4778747e889bd 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -105,7 +105,7 @@ static struct acpi_driver acpi_processor_driver = {
#define UNINSTALL_NOTIFY_HANDLER 2
-struct file_operations acpi_processor_info_fops = {
+static struct file_operations acpi_processor_info_fops = {
.open = acpi_processor_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
@@ -121,7 +121,7 @@ struct acpi_processor_errata errata;
Errata Handling
-------------------------------------------------------------------------- */
-int
+static int
acpi_processor_errata_piix4 (
struct pci_dev *dev)
{
@@ -259,7 +259,7 @@ acpi_processor_errata (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_processor_dir = NULL;
+static struct proc_dir_entry *acpi_processor_dir = NULL;
static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
{
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 8711236d28b665..12bd980a12e940 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -345,7 +345,7 @@ end:
return_VALUE(0);
}
-int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
+static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_limit_seq_show,
PDE(inode)->data);
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index db0b31d2b3eb3b..be9f569d39d33f 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -308,7 +308,7 @@ end:
return_VALUE(0);
}
-int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
+static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_throttling_seq_show,
PDE(inode)->data);
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
index ec4ae9a15cb0c5..4788c079735d8a 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/resources/rsaddr.c
@@ -110,13 +110,13 @@ acpi_rs_address16_resource (
buffer += 2;
temp8 = *buffer;
- /* Values 0-2 are valid */
+ /* Values 0-2 and 0xC0-0xFF are valid */
- if (temp8 > 2) {
+ if ((temp8 > 2) && (temp8 < 0xC0)) {
return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
}
- output_struct->data.address16.resource_type = temp8 & 0x03;
+ output_struct->data.address16.resource_type = temp8;
/*
* Get the General Flags (Byte4)
@@ -496,12 +496,13 @@ acpi_rs_address32_resource (
buffer += 2;
temp8 = *buffer;
- /* Values 0-2 are valid */
- if(temp8 > 2) {
+ /* Values 0-2 and 0xC0-0xFF are valid */
+
+ if ((temp8 > 2) && (temp8 < 0xC0)) {
return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
}
- output_struct->data.address32.resource_type = temp8 & 0x03;
+ output_struct->data.address32.resource_type = temp8;
/*
* Get the General Flags (Byte4)
@@ -850,6 +851,7 @@ acpi_rs_address64_resource (
struct acpi_resource *output_struct = (void *) *output_buffer;
u16 temp16;
u8 temp8;
+ u8 resource_type;
u8 *temp_ptr;
acpi_size struct_size;
u32 index;
@@ -860,6 +862,7 @@ acpi_rs_address64_resource (
buffer = byte_stream_buffer;
struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
+ resource_type = *buffer;
/*
* Point past the Descriptor to get the number of bytes consumed
@@ -882,13 +885,13 @@ acpi_rs_address64_resource (
buffer += 2;
temp8 = *buffer;
- /* Values 0-2 are valid */
+ /* Values 0-2 and 0xC0-0xFF are valid */
- if(temp8 > 2) {
+ if ((temp8 > 2) && (temp8 < 0xC0)) {
return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
}
- output_struct->data.address64.resource_type = temp8 & 0x03;
+ output_struct->data.address64.resource_type = temp8;
/*
* Get the General Flags (Byte4)
@@ -942,98 +945,113 @@ acpi_rs_address64_resource (
}
}
+ if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
+ /* Move past revision_id and Reserved byte */
+
+ buffer += 2;
+ }
+
/*
- * Get Granularity (Bytes 6-13)
+ * Get Granularity (Bytes 6-13) or (Bytes 8-15)
*/
buffer += 1;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer);
/*
- * Get min_address_range (Bytes 14-21)
+ * Get min_address_range (Bytes 14-21) or (Bytes 16-23)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer);
/*
- * Get max_address_range (Bytes 22-29)
+ * Get max_address_range (Bytes 22-29) or (Bytes 24-31)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer);
/*
- * Get address_translation_offset (Bytes 30-37)
+ * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer);
/*
- * Get address_length (Bytes 38-45)
+ * Get address_length (Bytes 38-45) or (Bytes 40-47)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer);
- /*
- * Resource Source Index (if present)
- */
- buffer += 8;
+ output_struct->data.address64.resource_source.index = 0x00;
+ output_struct->data.address64.resource_source.string_length = 0;
+ output_struct->data.address64.resource_source.string_ptr = NULL;
- /*
- * This will leave us pointing to the Resource Source Index
- * If it is present, then save it off and calculate the
- * pointer to where the null terminated string goes:
- * Each Interrupt takes 32-bits + the 5 bytes of the
- * stream that are default.
- *
- * Note: Some resource descriptors will have an additional null, so
- * we add 1 to the length.
- */
- if (*bytes_consumed > (46 + 1)) {
- /* Dereference the Index */
+ if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
+ /* Get type_specific_attribute (Bytes 48-55) */
- temp8 = *buffer;
- output_struct->data.address64.resource_source.index =
- (u32) temp8;
+ buffer += 8;
+ ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer);
+ }
+ else {
+ output_struct->data.address64.type_specific_attributes = 0;
- /* Point to the String */
+ /*
+ * Resource Source Index (if present)
+ */
+ buffer += 8;
- buffer += 1;
+ /*
+ * This will leave us pointing to the Resource Source Index
+ * If it is present, then save it off and calculate the
+ * pointer to where the null terminated string goes:
+ * Each Interrupt takes 32-bits + the 5 bytes of the
+ * stream that are default.
+ *
+ * Note: Some resource descriptors will have an additional null, so
+ * we add 1 to the length.
+ */
+ if (*bytes_consumed > (46 + 1)) {
+ /* Dereference the Index */
- /* Point the String pointer to the end of this structure */
+ temp8 = *buffer;
+ output_struct->data.address64.resource_source.index =
+ (u32) temp8;
- output_struct->data.address64.resource_source.string_ptr =
- (char *)((u8 *)output_struct + struct_size);
+ /* Point to the String */
- temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr;
+ buffer += 1;
- /* Copy the string into the buffer */
+ /* Point the String pointer to the end of this structure */
- index = 0;
- while (0x00 != *buffer) {
- *temp_ptr = *buffer;
+ output_struct->data.address64.resource_source.string_ptr =
+ (char *)((u8 *)output_struct + struct_size);
- temp_ptr += 1;
- buffer += 1;
- index += 1;
- }
+ temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr;
- /*
- * Add the terminating null
- */
- *temp_ptr = 0x00;
- output_struct->data.address64.resource_source.string_length = index + 1;
+ /* Copy the string into the buffer */
- /*
- * In order for the struct_size to fall on a 32-bit boundary,
- * calculate the length of the string and expand the
- * struct_size to the next 32-bit boundary.
- */
- temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.address64.resource_source.index = 0x00;
- output_struct->data.address64.resource_source.string_length = 0;
- output_struct->data.address64.resource_source.string_ptr = NULL;
+ index = 0;
+ while (0x00 != *buffer) {
+ *temp_ptr = *buffer;
+
+ temp_ptr += 1;
+ buffer += 1;
+ index += 1;
+ }
+
+ /*
+ * Add the terminating null
+ */
+ *temp_ptr = 0x00;
+ output_struct->data.address64.resource_source.string_length = index + 1;
+
+ /*
+ * In order for the struct_size to fall on a 32-bit boundary,
+ * calculate the length of the string and expand the
+ * struct_size to the next 32-bit boundary.
+ */
+ temp8 = (u8) (index + 1);
+ struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
+ }
}
/*
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 1113af74693954..8a5f0a52371d49 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -376,6 +376,20 @@ acpi_rs_get_list_length (
break;
+ case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
+ /*
+ * 64-Bit Address Resource
+ */
+ buffer = byte_stream_buffer;
+
+ ++buffer;
+ ACPI_MOVE_16_TO_16 (&temp16, buffer);
+
+ bytes_consumed = temp16 + 3;
+ structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
+ break;
+
+
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index a869980f7fe454..eef1b1f2c68596 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -571,7 +571,7 @@ acpi_rs_dump_address16 (
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
+ acpi_os_printf (" Type Specific: %s Translation\n",
ACPI_SPARSE_TRANSLATION ==
address16_data->attribute.io.translation_attribute ?
"Sparse" : "Dense");
@@ -584,8 +584,8 @@ acpi_rs_dump_address16 (
default:
- acpi_os_printf ("Invalid resource type. Exiting.\n");
- return;
+ acpi_os_printf ("0x%2.2X\n", address16_data->resource_type);
+ break;
}
acpi_os_printf (" Resource %s\n",
@@ -718,7 +718,7 @@ acpi_rs_dump_address32 (
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
+ acpi_os_printf (" Type Specific: %s Translation\n",
ACPI_SPARSE_TRANSLATION ==
address32_data->attribute.io.translation_attribute ?
"Sparse" : "Dense");
@@ -731,8 +731,8 @@ acpi_rs_dump_address32 (
default:
- acpi_os_printf (" Invalid Resource Type..exiting.\n");
- return;
+ acpi_os_printf (" Resource Type: 0x%2.2X\n", address32_data->resource_type);
+ break;
}
acpi_os_printf (" Resource %s\n",
@@ -865,7 +865,7 @@ acpi_rs_dump_address64 (
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
+ acpi_os_printf (" Type Specific: %s Translation\n",
ACPI_SPARSE_TRANSLATION ==
address64_data->attribute.io.translation_attribute ?
"Sparse" : "Dense");
@@ -878,8 +878,8 @@ acpi_rs_dump_address64 (
default:
- acpi_os_printf (" Invalid Resource Type..exiting.\n");
- return;
+ acpi_os_printf (" Resource Type: 0x%2.2X\n", address64_data->resource_type);
+ break;
}
acpi_os_printf (" Resource %s\n",
@@ -913,7 +913,10 @@ acpi_rs_dump_address64 (
acpi_os_printf (" Address Length: %8.8X%8.8X\n",
ACPI_FORMAT_UINT64 (address64_data->address_length));
- if(0xFF != address64_data->resource_source.index) {
+ acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes));
+
+ if (0xFF != address64_data->resource_source.index) {
acpi_os_printf (" Resource Source Index: %X\n",
address64_data->resource_source.index);
acpi_os_printf (" Resource Source: %s\n",
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index 1297589d792f53..e49c1e030f99f7 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -178,6 +178,7 @@ acpi_rs_byte_stream_to_list (
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
+ case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
*/
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f20d88d3c554bb..e7ca06626566e5 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -27,6 +27,10 @@ static LIST_HEAD(acpi_device_list);
DEFINE_SPINLOCK(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
+static int
+acpi_bus_trim(struct acpi_device *start,
+ int rmdevice);
+
static void acpi_device_release(struct kobject * kobj)
{
struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
@@ -81,12 +85,37 @@ static struct kobj_type ktype_acpi_ns = {
.release = acpi_device_release,
};
+static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
+ char **envp, int num_envp, char *buffer,
+ int buffer_size)
+{
+ struct acpi_device *dev = to_acpi_device(kobj);
+ int i = 0;
+ int len = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "PHYSDEVDRIVER=%s", dev->driver->name))
+ return -ENOMEM;
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
+static struct kset_hotplug_ops namespace_hotplug_ops = {
+ .hotplug = &namespace_hotplug,
+};
+
static struct kset acpi_namespace_kset = {
.kobj = {
.name = "namespace",
},
.subsys = &acpi_subsys,
.ktype = &ktype_acpi_ns,
+ .hotplug_ops = &namespace_hotplug_ops,
};
@@ -358,7 +387,15 @@ setup_sys_fs_device_files (
struct acpi_device *dev,
acpi_device_sysfs_files *func)
{
- if (dev->flags.ejectable == 1)
+ acpi_status status;
+ acpi_handle temp = NULL;
+
+ /*
+ * If device has _EJ0, 'eject' file is created that is used to trigger
+ * hot-removal function from userland.
+ */
+ status = acpi_get_handle(dev->handle, "_EJ0", &temp);
+ if (ACPI_SUCCESS(status))
(*(func))(&dev->kobj,&acpi_device_attr_eject.attr);
}
@@ -857,7 +894,7 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device *
acpi_os_free(buffer.pointer);
}
-int acpi_device_set_context(struct acpi_device * device, int type)
+static int acpi_device_set_context(struct acpi_device * device, int type)
{
acpi_status status = AE_OK;
int result = 0;
@@ -882,7 +919,7 @@ int acpi_device_set_context(struct acpi_device * device, int type)
return result;
}
-void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type)
+static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type)
{
#ifdef CONFIG_ACPI_DEBUG_OUTPUT
char *type_string = NULL;
@@ -925,7 +962,7 @@ void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle,
}
-int
+static int
acpi_bus_remove (
struct acpi_device *dev,
int rmdevice)
@@ -1223,7 +1260,7 @@ int acpi_bus_scan (struct acpi_device *start)
EXPORT_SYMBOL(acpi_bus_scan);
-int
+static int
acpi_bus_trim(struct acpi_device *start,
int rmdevice)
{
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index be97f286957924..79c3a686bc4421 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -774,7 +774,7 @@ acpi_thermal_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_thermal_dir;
+static struct proc_dir_entry *acpi_thermal_dir;
static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
{
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index c0c9ea1084aa34..c84997c9f9640b 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -481,7 +481,7 @@ read_version(char* p)
#define PROC_TOSHIBA "toshiba"
-ProcItem proc_items[] =
+static ProcItem proc_items[] =
{
{ "lcd" , read_lcd , write_lcd },
{ "video" , read_video , write_video },
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 0b366d3b48667a..0fcd98bde0d105 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -659,15 +659,17 @@ acpi_ut_copy_simple_object (
/* Create an actual buffer only if length > 0 */
if (source_desc->buffer.length) {
- dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length);
+ dest_desc->buffer.pointer =
+ ACPI_MEM_ALLOCATE (source_desc->buffer.length);
if (!dest_desc->buffer.pointer) {
return (AE_NO_MEMORY);
}
/* Copy the actual buffer data */
- ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer,
- source_desc->buffer.length);
+ ACPI_MEMCPY (dest_desc->buffer.pointer,
+ source_desc->buffer.pointer,
+ source_desc->buffer.length);
}
}
break;
@@ -682,7 +684,8 @@ acpi_ut_copy_simple_object (
*/
if ((source_desc->string.pointer) &&
(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
- dest_desc->string.pointer = ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
+ dest_desc->string.pointer =
+ ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
if (!dest_desc->string.pointer) {
return (AE_NO_MEMORY);
}
@@ -692,6 +695,14 @@ acpi_ut_copy_simple_object (
}
break;
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ /*
+ * We copied the reference object, so we now must add a reference
+ * to the object pointed to by the reference
+ */
+ acpi_ut_add_reference (source_desc->reference.object);
+ break;
+
default:
/* Nothing to do for other simple objects */
break;
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index e8ee13280bbf16..9a52ad52a23aea 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -46,6 +46,7 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
+#include <acpi/amlcode.h>
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utdelete")
@@ -562,8 +563,23 @@ acpi_ut_update_object_reference (
break;
- case ACPI_TYPE_REGION:
case ACPI_TYPE_LOCAL_REFERENCE:
+
+ /*
+ * The target of an Index (a package, string, or buffer) must track
+ * changes to the ref count of the index.
+ */
+ if (object->reference.opcode == AML_INDEX_OP) {
+ status = acpi_ut_create_update_state_and_push (
+ object->reference.object, action, &state_list);
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
+ }
+ break;
+
+
+ case ACPI_TYPE_REGION:
default:
/* No subobjects */
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index d3eb4db38f75ce..25b0f8ae1bc6fc 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -194,6 +194,8 @@ const char *acpi_gbl_highest_dstate_names[4] =
*/
const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
{
+ /* Operating System Vendor Strings */
+
"Linux",
"Windows 2000",
"Windows 2001",
@@ -202,7 +204,11 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STR
"Windows 2001 SP1",
"Windows 2001 SP2",
"Windows 2001 SP3",
- "Windows 2001 SP4"
+ "Windows 2001 SP4",
+
+ /* Feature Group Strings */
+
+ "Extended Address Space Descriptor"
};
@@ -355,6 +361,7 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]
/* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS},
/* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS},
/* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS},
+ /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS},
/* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE},
/* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
@@ -362,6 +369,7 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]
/* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
/* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE},
/* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
+ /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
/* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE},
/* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD},
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 4d32f6d18f648f..f6598547389b87 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -372,7 +372,7 @@ acpi_ut_strtoul64 (
u32 base,
acpi_integer *ret_integer)
{
- u32 this_digit;
+ u32 this_digit = 0;
acpi_integer return_value = 0;
acpi_integer quotient;
@@ -380,6 +380,10 @@ acpi_ut_strtoul64 (
ACPI_FUNCTION_TRACE ("ut_stroul64");
+ if ((!string) || !(*string)) {
+ goto error_exit;
+ }
+
switch (base) {
case ACPI_ANY_BASE:
case 10:
@@ -394,7 +398,7 @@ acpi_ut_strtoul64 (
/* Skip over any white space in the buffer */
while (ACPI_IS_SPACE (*string) || *string == '\t') {
- ++string;
+ string++;
}
/*
@@ -403,9 +407,9 @@ acpi_ut_strtoul64 (
*/
if (base == 0) {
if ((*string == '0') &&
- (ACPI_TOLOWER (*(++string)) == 'x')) {
+ (ACPI_TOLOWER (*(string + 1)) == 'x')) {
base = 16;
- ++string;
+ string += 2;
}
else {
base = 10;
@@ -416,10 +420,10 @@ acpi_ut_strtoul64 (
* For hexadecimal base, skip over the leading
* 0 or 0x, if they are present.
*/
- if (base == 16 &&
- *string == '0' &&
- ACPI_TOLOWER (*(++string)) == 'x') {
- string++;
+ if ((base == 16) &&
+ (*string == '0') &&
+ (ACPI_TOLOWER (*(string + 1)) == 'x')) {
+ string += 2;
}
/* Any string left? */
@@ -437,23 +441,27 @@ acpi_ut_strtoul64 (
this_digit = ((u8) *string) - '0';
}
else {
+ if (base == 10) {
+ /* Digit is out of range */
+
+ goto error_exit;
+ }
+
this_digit = (u8) ACPI_TOUPPER (*string);
- if (ACPI_IS_UPPER ((char) this_digit)) {
+ if (ACPI_IS_XDIGIT ((char) this_digit)) {
/* Convert ASCII Hex char to value */
this_digit = this_digit - 'A' + 10;
}
else {
- goto error_exit;
+ /*
+ * We allow non-hex chars, just stop now, same as end-of-string.
+ * See ACPI spec, string-to-integer conversion.
+ */
+ break;
}
}
- /* Check to see if digit is out of range */
-
- if (this_digit >= base) {
- goto error_exit;
- }
-
/* Divide the digit into the correct position */
(void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit),
@@ -464,9 +472,11 @@ acpi_ut_strtoul64 (
return_value *= base;
return_value += this_digit;
- ++string;
+ string++;
}
+ /* All done, normal exit */
+
*ret_integer = return_value;
return_ACPI_STATUS (AE_OK);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index bd311c2076acc4..71fa1011715f36 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -683,7 +683,7 @@ acpi_video_bus_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_video_dir;
+static struct proc_dir_entry *acpi_video_dir;
/* video devices */
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 08b2d48494694e..02242e8ba99687 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -238,7 +238,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
q->make_request_fn = mfn;
q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
q->backing_dev_info.state = 0;
- q->backing_dev_info.memory_backed = 0;
+ q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
blk_queue_max_sectors(q, MAX_SECTORS);
blk_queue_hardsect_size(q, 512);
blk_queue_dma_alignment(q, 511);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 7c7ed041c28cee..efdf04450bf731 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -549,7 +549,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
file = fget(arg);
if (file) {
inode = file->f_dentry->d_inode;
- if (inode->i_sock) {
+ if (S_ISSOCK(inode->i_mode)) {
lo->file = file;
lo->sock = SOCKET_I(inode);
error = 0;
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 6a126ee370d602..145c1fbffe0135 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -325,7 +325,7 @@ static int rd_ioctl(struct inode *inode, struct file *file,
*/
static struct backing_dev_info rd_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK | BDI_CAP_MAP_COPY,
.unplug_io_fn = default_unplug_io_fn,
};
@@ -336,7 +336,7 @@ static struct backing_dev_info rd_backing_dev_info = {
*/
static struct backing_dev_info rd_file_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 0, /* Does contribute to dirty memory */
+ .capabilities = BDI_CAP_MAP_COPY, /* Does contribute to dirty memory */
.unplug_io_fn = default_unplug_io_fn,
};
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3dfcaffd37ccd9..096a1202ea077d 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -271,7 +271,7 @@ config SPECIALIX_RTSCTS
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+ depends on SERIAL_NONSTANDARD
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/sx.txt> for details.
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 4d159c610f7f37..947cb3cef81671 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,6 +23,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/ptrace.h>
#include <linux/device.h>
+#include <linux/backing-dev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -282,30 +283,30 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
unsigned long p = *ppos;
- ssize_t read, virtr, sz;
+ ssize_t low_count, read, sz;
char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
read = 0;
- virtr = 0;
if (p < (unsigned long) high_memory) {
- read = count;
+ low_count = count;
if (count > (unsigned long) high_memory - p)
- read = (unsigned long) high_memory - p;
+ low_count = (unsigned long) high_memory - p;
#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
/* we don't have page 0 mapped on sparc and m68k.. */
- if (p < PAGE_SIZE && read > 0) {
+ if (p < PAGE_SIZE && low_count > 0) {
size_t tmp = PAGE_SIZE - p;
- if (tmp > read) tmp = read;
+ if (tmp > low_count) tmp = low_count;
if (clear_user(buf, tmp))
return -EFAULT;
buf += tmp;
p += tmp;
- read -= tmp;
+ read += tmp;
+ low_count -= tmp;
count -= tmp;
}
#endif
- while (read > 0) {
+ while (low_count > 0) {
/*
* Handle first page in case it's not aligned
*/
@@ -314,7 +315,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
else
sz = PAGE_SIZE;
- sz = min_t(unsigned long, sz, count);
+ sz = min_t(unsigned long, sz, low_count);
/*
* On ia64 if a page has been mapped somewhere as
@@ -327,7 +328,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
return -EFAULT;
buf += sz;
p += sz;
- read -= sz;
+ read += sz;
+ low_count -= sz;
count -= sz;
}
}
@@ -350,13 +352,13 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
}
count -= len;
buf += len;
- virtr += len;
+ read += len;
p += len;
}
free_page((unsigned long)kbuf);
}
*ppos = p;
- return virtr + read;
+ return read;
}
@@ -758,6 +760,10 @@ static struct file_operations zero_fops = {
.mmap = mmap_zero,
};
+static struct backing_dev_info zero_bdi = {
+ .capabilities = BDI_CAP_MAP_COPY,
+};
+
static struct file_operations full_fops = {
.llseek = full_lseek,
.read = read_full,
@@ -804,6 +810,7 @@ static int memory_open(struct inode * inode, struct file * filp)
break;
#endif
case 5:
+ filp->f_mapping->backing_dev_info = &zero_bdi;
filp->f_op = &zero_fops;
break;
case 7:
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 8f70185f192afe..533085ec6f1bb3 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -84,9 +84,7 @@ static struct IdentifyRta IdRta;
static struct KillNeighbour KillUnit;
int
-RIOFoadRta(HostP, MapP)
-struct Host * HostP;
-struct Map * MapP;
+RIOFoadRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
@@ -117,9 +115,7 @@ struct Map * MapP;
}
int
-RIOZombieRta(HostP, MapP)
-struct Host * HostP;
-struct Map * MapP;
+RIOZombieRta(struct Host *HostP, struct Map *MapP)
{
struct CmdBlk *CmdBlkP;
@@ -150,10 +146,8 @@ struct Map * MapP;
}
int
-RIOCommandRta(p, RtaUnique, func)
-struct rio_info * p;
-uint RtaUnique;
-int (* func)( struct Host *HostP, struct Map *MapP );
+RIOCommandRta(struct rio_info *p, uint RtaUnique,
+ int (* func)(struct Host *HostP, struct Map *MapP))
{
uint Host;
@@ -195,9 +189,7 @@ int (* func)( struct Host *HostP, struct Map *MapP );
int
-RIOIdentifyRta(p, arg)
-struct rio_info * p;
-caddr_t arg;
+RIOIdentifyRta(struct rio_info *p, caddr_t arg)
{
uint Host;
@@ -263,9 +255,7 @@ caddr_t arg;
int
-RIOKillNeighbour(p, arg)
-struct rio_info * p;
-caddr_t arg;
+RIOKillNeighbour(struct rio_info *p, caddr_t arg)
{
uint Host;
uint ID;
@@ -329,10 +319,7 @@ caddr_t arg;
}
int
-RIOSuspendBootRta(HostP, ID, Link)
-struct Host *HostP;
-int ID;
-int Link;
+RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
{
struct CmdBlk *CmdBlkP;
@@ -363,8 +350,7 @@ int Link;
}
int
-RIOFoadWakeup(p)
-struct rio_info * p;
+RIOFoadWakeup(struct rio_info *p)
{
int port;
register struct Port *PortP;
@@ -398,11 +384,7 @@ struct rio_info * p;
** Incoming command on the COMMAND_RUP to be processed.
*/
static int
-RIOCommandRup(p, Rup, HostP, PacketP)
-struct rio_info * p;
-uint Rup;
-struct Host *HostP;
-PKT *PacketP;
+RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, PKT *PacketP)
{
struct PktCmd *PktCmdP = (struct PktCmd *)PacketP->data;
struct Port *PortP;
@@ -619,7 +601,7 @@ PKT *PacketP;
** Allocate an empty command block.
*/
struct CmdBlk *
-RIOGetCmdBlk()
+RIOGetCmdBlk(void)
{
struct CmdBlk *CmdBlkP;
@@ -634,8 +616,7 @@ RIOGetCmdBlk()
** Return a block to the head of the free list.
*/
void
-RIOFreeCmdBlk(CmdBlkP)
-struct CmdBlk *CmdBlkP;
+RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
{
sysfree((void *)CmdBlkP, sizeof(struct CmdBlk));
}
@@ -645,10 +626,7 @@ struct CmdBlk *CmdBlkP;
** a given rup.
*/
int
-RIOQueueCmdBlk(HostP, Rup, CmdBlkP)
-struct Host *HostP;
-uint Rup;
-struct CmdBlk *CmdBlkP;
+RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
{
struct CmdBlk **Base;
struct UnixRup *UnixRupP;
@@ -679,7 +657,6 @@ struct CmdBlk *CmdBlkP;
:TRUE)) {
rio_dprintk (RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n",
CmdBlkP->Packet.data[0]);
-
/*
** Whammy! blat that pack!
@@ -737,9 +714,7 @@ struct CmdBlk *CmdBlkP;
** must be called at splrio() or higher.
*/
void
-RIOPollHostCommands(p, HostP)
-struct rio_info * p;
-struct Host * HostP;
+RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
{
register struct CmdBlk *CmdBlkP;
register struct UnixRup *UnixRupP;
@@ -918,9 +893,7 @@ struct Host * HostP;
}
int
-RIOWFlushMark(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIOWFlushMark(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
unsigned long flags;
@@ -936,9 +909,7 @@ struct CmdBlk *CmdBlkP;
}
int
-RIORFlushEnable(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIORFlushEnable(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
PKT *PacketP;
@@ -965,9 +936,7 @@ struct CmdBlk *CmdBlkP;
}
int
-RIOUnUse(iPortP, CmdBlkP)
-int iPortP;
-struct CmdBlk *CmdBlkP;
+RIOUnUse(int iPortP, struct CmdBlk *CmdBlkP)
{
struct Port * PortP = (struct Port *)iPortP;
unsigned long flags;
@@ -1009,9 +978,7 @@ struct CmdBlk *CmdBlkP;
}
void
-ShowPacket(Flags, PacketP)
-uint Flags;
-struct PKT *PacketP;
+ShowPacket(uint Flags, struct PKT *PacketP)
{
}
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 5a250be53fa78f..3ad758a9a1dc10 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -4,7 +4,7 @@
* This driver will also support the older SI, and XIO cards.
*
*
- * (C) 1998 - 2000 R.E.Wolff@BitWizard.nl
+ * (C) 1998 - 2004 R.E.Wolff@BitWizard.nl
*
* Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
* version of this driver. Some fragments may have been copied. (none
@@ -354,13 +354,13 @@ static int si1_probe_addrs[]= { 0xd0000};
Some architectures may need more. */
static int sx_irqmask = -1;
-MODULE_PARM(sx_probe_addrs, "i");
-MODULE_PARM(si_probe_addrs, "i");
-MODULE_PARM(sx_poll, "i");
-MODULE_PARM(sx_slowpoll, "i");
-MODULE_PARM(sx_maxints, "i");
-MODULE_PARM(sx_debug, "i");
-MODULE_PARM(sx_irqmask, "i");
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+module_param(sx_poll, int, 0);
+module_param(sx_slowpoll, int, 0);
+module_param(sx_maxints, int, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_irqmask, int, 0);
MODULE_LICENSE("GPL");
@@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = {
-#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\b",__FUNCTION__)
+#define func_enter() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s\n",__FUNCTION__)
#define func_exit() sx_dprintk (SX_DEBUG_FLOW, "sx: exit %s\n", __FUNCTION__)
#define func_enter2() sx_dprintk (SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
@@ -1158,7 +1158,6 @@ static inline void sx_check_modem_signals (struct sx_port *port)
if (hi_state & ST_BREAK) {
hi_state &= ~ST_BREAK;
sx_dprintk (SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-
sx_write_channel_byte (port, hi_state, hi_state);
gs_got_break (&port->gs);
}
@@ -1206,7 +1205,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
struct sx_port *port;
int i;
- /* func_enter (); */
+ func_enter ();
sx_dprintk (SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq, board->irq);
/* AAargh! The order in which to do these things is essential and
@@ -1297,7 +1296,7 @@ static irqreturn_t sx_interrupt (int irq, void *ptr, struct pt_regs *regs)
clear_bit (SX_BOARD_INTR_LOCK, &board->locks);
sx_dprintk (SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq, board->irq);
- /* func_exit (); */
+ func_exit ();
return IRQ_HANDLED;
}
@@ -1428,6 +1427,7 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
{
struct sx_port *port;
int retval, line;
+ unsigned long flags;
func_enter();
@@ -1449,9 +1449,12 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
sx_dprintk (SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
+ spin_lock_irqsave(&port->gs.driver_lock, flags);
+
tty->driver_data = port;
port->gs.tty = tty;
port->gs.count++;
+ spin_unlock_irqrestore(&port->gs.driver_lock, flags);
sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
@@ -1466,7 +1469,8 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
}
port->gs.flags |= GS_ACTIVE;
- sx_setsignals (port, 1,1);
+ if (port->gs.count <= 1)
+ sx_setsignals (port, 1,1);
#if 0
if (sx_debug & SX_DEBUG_OPEN)
@@ -1476,10 +1480,14 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
my_hd_io (port->board->base + port->ch_base, sizeof (*port));
#endif
- if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
- printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
- port->gs.count--;
- return -EIO;
+ if (port->gs.count <= 1) {
+ if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
+ printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
+ spin_lock_irqsave(&port->gs.driver_lock, flags);
+ port->gs.count--;
+ spin_unlock_irqrestore(&port->gs.driver_lock, flags);
+ return -EIO;
+ }
}
retval = gs_block_til_ready(port, filp);
@@ -1497,6 +1505,7 @@ static int sx_open (struct tty_struct * tty, struct file * filp)
port->c_dcd = sx_get_CD (port);
sx_dprintk (SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+
func_exit();
return 0;
@@ -1531,7 +1540,8 @@ static void sx_close (void *ptr)
if(port->gs.count) {
sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
- port->gs.count = 0;
+ //printk ("%s SETTING port count to zero: %p count: %d\n", __FUNCTION__, port, port->gs.count);
+ //port->gs.count = 0;
}
func_exit ();
@@ -1747,12 +1757,16 @@ static void sx_break (struct tty_struct * tty, int flag)
struct sx_port *port = tty->driver_data;
int rv;
+ func_enter ();
+
if (flag)
rv = sx_send_command (port, HS_START, -1, HS_IDLE_BREAK);
else
rv = sx_send_command (port, HS_STOP, -1, HS_IDLE_OPEN);
if (rv != 1) printk (KERN_ERR "sx: couldn't send break (%x).\n",
read_sx_byte (port->board, CHAN_OFFSET (port, hi_hstat)));
+
+ func_exit ();
}
@@ -2101,7 +2115,7 @@ static int probe_sx (struct sx_board *board)
}
if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) == SX_ISA_UNIQUEID1) {
- if (board->hw_base & 0x8000) {
+ if (((unsigned long)board->hw_base) & 0x8000) {
printk (KERN_WARNING "sx: Warning: There may be hardware problems with the card at %lx.\n", board->hw_base);
printk (KERN_WARNING "sx: Read sx.txt for more info.\n");
}
@@ -2150,6 +2164,7 @@ static int probe_si (struct sx_board *board)
}
for (i=0;i<8;i++) {
if ((read_sx_byte (board, SI2_ISA_ID_BASE+7-i) & 7) != i) {
+ func_exit ();
return 0;
}
}
@@ -2164,11 +2179,13 @@ static int probe_si (struct sx_board *board)
/* This should be an SI1 board, which has this
location writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ func_exit ();
return 0;
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ func_exit ();
return 0;
}
@@ -2181,11 +2198,13 @@ static int probe_si (struct sx_board *board)
/* This should be an SI1 board, which has this
location writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
+ func_exit();
return 0;
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
+ func_exit ();
return 0;
}
@@ -2302,6 +2321,7 @@ static int sx_init_portstructs (int nboards, int nports)
#ifdef NEW_WRITE_LOCKING
port->gs.port_write_sem = MUTEX;
#endif
+ port->gs.driver_lock = SPIN_LOCK_UNLOCKED;
/*
* Initializing wait queue
*/
@@ -2473,7 +2493,7 @@ static int __init sx_init(void)
found++;
fix_sx_pci (pdev, board);
} else
- iounmap(board->base);
+ iounmap(board->base2);
}
#endif
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 8c385a3f7e64ad..f59f7cbd525bcd 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -31,9 +31,10 @@
#include <linux/suspend.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for fsync_bdev() */
-
+#include <linux/swap.h>
#include <linux/spinlock.h>
#include <linux/vt_kern.h>
+#include <linux/workqueue.h>
#include <asm/ptrace.h>
@@ -209,6 +210,24 @@ static struct sysrq_key_op sysrq_term_op = {
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
+static void moom_callback(void *ignored)
+{
+ out_of_memory(GFP_KERNEL);
+}
+
+static DECLARE_WORK(moom_work, moom_callback, NULL);
+
+static void sysrq_handle_moom(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ schedule_work(&moom_work);
+}
+static struct sysrq_key_op sysrq_moom_op = {
+ .handler = sysrq_handle_moom,
+ .help_msg = "Full",
+ .action_msg = "Manual OOM execution",
+};
+
static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
@@ -257,7 +276,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
/* c */ NULL,
/* d */ NULL,
/* e */ &sysrq_term_op,
-/* f */ NULL,
+/* f */ &sysrq_moom_op,
/* g */ NULL,
/* h */ NULL,
/* i */ &sysrq_kill_op,
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6229dd04ac314d..e5ef1dfc54826a 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2212,9 +2212,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
}
set_cursor(vc);
- if (!oops_in_progress)
- poke_blanked_console();
-
quit:
clear_bit(0, &printing);
}
@@ -2815,6 +2812,13 @@ void do_unblank_screen(int leaving_gfx)
{
struct vc_data *vc;
+ /* This should now always be called from a "sane" (read: can schedule)
+ * context for the sake of the low level drivers, except in the special
+ * case of oops_in_progress
+ */
+ if (!oops_in_progress)
+ might_sleep();
+
WARN_CONSOLE_UNLOCKED();
ignore_poke = 0;
@@ -2871,6 +2875,14 @@ void poke_blanked_console(void)
{
WARN_CONSOLE_UNLOCKED();
+ /* Add this so we quickly catch whoever might call us in a non
+ * safe context. Nowadays, unblank_screen() isn't to be called in
+ * atomic contexts and is allowed to schedule (with the special case
+ * of oops_in_progress, but that isn't of any concern for this
+ * function. --BenH.
+ */
+ might_sleep();
+
/* This isn't perfectly race free, but a race here would be mostly harmless,
* at worse, we'll do a spurrious blank and it's unlikely
*/
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index ffd87404b0a0eb..68e9e6832ca0c2 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -713,14 +713,11 @@ static u32 iic_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm iic_algo = {
- "ITE IIC algorithm",
- I2C_ALGO_IIC,
- iic_xfer, /* master_xfer */
- NULL, /* smbus_xfer */
- NULL, /* slave_xmit */
- NULL, /* slave_recv */
- algo_control, /* ioctl */
- iic_func, /* functionality */
+ .name = "ITE IIC algorithm",
+ .id = I2C_ALGO_IIC,
+ .master_xfer = iic_xfer,
+ .algo_control = algo_control, /* ioctl */
+ .functionality = iic_func,
};
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 66e681cb33d1ea..8d087dac32afc7 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -78,7 +78,6 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
set_pcf(adap, 1, I2C_PCF_STOP);
}
-
static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
int timeout = DEF_TIMEOUT;
@@ -109,6 +108,26 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
adap->waitforpin();
*status = get_pcf(adap, 1);
}
+ if (*status & I2C_PCF_LAB) {
+ DEB2(printk(KERN_INFO
+ "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
+ *status));
+ /* Cleanup from LAB-- reset and enable ESO.
+ * This resets the PCF8584; since we've lost the bus, no
+ * further attempts should be made by callers to clean up
+ * (no i2c_stop() etc.)
+ */
+ set_pcf(adap, 1, I2C_PCF_PIN);
+ set_pcf(adap, 1, I2C_PCF_ESO);
+ /* TODO: we should pause for a time period sufficient for any
+ * running I2C transaction to complete-- the arbitration
+ * logic won't work properly until the next START is seen.
+ */
+ DEB2(printk(KERN_INFO
+ "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
+ get_pcf(adap,1)));
+ return(-EINTR);
+ }
#endif
if (timeout <= 0)
return(-1);
@@ -188,16 +207,22 @@ static inline int try_address(struct i2c_algo_pcf_data *adap,
unsigned char addr, int retries)
{
int i, status, ret = -1;
+ int wfp;
for (i=0;i<retries;i++) {
i2c_outb(adap, addr);
i2c_start(adap);
status = get_pcf(adap, 1);
- if (wait_for_pin(adap, &status) >= 0) {
+ if ((wfp = wait_for_pin(adap, &status)) >= 0) {
if ((status & I2C_PCF_LRB) == 0) {
i2c_stop(adap);
break; /* success! */
}
}
+ if (wfp == -EINTR) {
+ /* arbitration lost */
+ udelay(adap->udelay);
+ return -EINTR;
+ }
i2c_stop(adap);
udelay(adap->udelay);
}
@@ -219,6 +244,10 @@ static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
i2c_outb(adap, buf[wrcount]);
timeout = wait_for_pin(adap, &status);
if (timeout) {
+ if (timeout == -EINTR) {
+ /* arbitration lost */
+ return -EINTR;
+ }
i2c_stop(adap);
dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n");
return -EREMOTEIO; /* got a better one ?? */
@@ -247,11 +276,16 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
{
int i, status;
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
+ int wfp;
/* increment number of bytes to read by one -- read dummy byte */
for (i = 0; i <= count; i++) {
- if (wait_for_pin(adap, &status)) {
+ if ((wfp = wait_for_pin(adap, &status))) {
+ if (wfp == -EINTR) {
+ /* arbitration lost */
+ return -EINTR;
+ }
i2c_stop(adap);
dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n");
return (-1);
@@ -366,6 +400,10 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
/* Wait for PIN (pending interrupt NOT) */
timeout = wait_for_pin(adap, &status);
if (timeout) {
+ if (timeout == -EINTR) {
+ /* arbitration lost */
+ return (-EINTR);
+ }
i2c_stop(adap);
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting "
"for PIN(1) in pcf_xfer\n");)
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index ea1a9047a3b25a..35789bb7126a3b 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -136,14 +136,11 @@ static u32 bit_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_sibyte_algo = {
- "SiByte algorithm",
- I2C_ALGO_SIBYTE,
- NULL, /* master_xfer */
- smbus_xfer, /* smbus_xfer */
- NULL, /* slave_xmit */
- NULL, /* slave_recv */
- algo_control, /* ioctl */
- bit_func, /* functionality */
+ .name = "SiByte algorithm",
+ .id = I2C_ALGO_SIBYTE,
+ .smbus_xfer = smbus_xfer,
+ .algo_control = algo_control, /* ioctl */
+ .functionality = bit_func,
};
/*
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 34ff2ecad216fb..edf8051da3b4ce 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -108,7 +108,7 @@ config I2C_HYDRA
will be called i2c-hydra.
config I2C_I801
- tristate "Intel 801"
+ tristate "Intel 82801 (ICH)"
depends on I2C && PCI && EXPERIMENTAL
help
If you say yes to this option, support will be included for the Intel
@@ -119,7 +119,7 @@ config I2C_I801
82801BA
82801CA/CAM
82801DB
- 82801EB
+ 82801EB/ER (ICH5/ICH5R)
6300ESB
ICH6
ICH7
@@ -143,6 +143,23 @@ config I2C_I810
This driver can also be built as a module. If so, the module
will be called i2c-i810.
+config I2C_PIIX4
+ tristate "Intel PIIX4"
+ depends on I2C && PCI
+ help
+ If you say yes to this option, support will be included for the Intel
+ PIIX4 family of mainboard I2C interfaces. Specifically, the following
+ versions of the chipset are supported:
+ Intel PIIX4
+ Intel 440MX
+ Serverworks OSB4
+ Serverworks CSB5
+ Serverworks CSB6
+ SMSC Victory66
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-piix4.
+
config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface"
depends on IBM_OCP && I2C
@@ -285,23 +302,6 @@ config I2C_PARPORT_LIGHT
This support is also available as a module. If so, the module
will be called i2c-parport-light.
-config I2C_PIIX4
- tristate "Intel PIIX4"
- depends on I2C && PCI && EXPERIMENTAL
- help
- If you say yes to this option, support will be included for the Intel
- PIIX4 family of mainboard I2C interfaces. Specifically, the following
- versions of the chipset are supported:
- Intel PIIX4
- Intel 440MX
- Serverworks OSB4
- Serverworks CSB5
- Serverworks CSB6
- SMSC Victory66
-
- This driver can also be built as a module. If so, the module
- will be called i2c-piix4.
-
config I2C_PROSAVAGE
tristate "S3/VIA (Pro)Savage"
depends on I2C && PCI && EXPERIMENTAL
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 96fc7d72904bcd..0a7720000a0c5d 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -110,22 +110,23 @@ static int pcf_isa_getclock(void *data)
}
static void pcf_isa_waitforpin(void) {
-
+ DEFINE_WAIT(wait);
int timeout = 2;
- long flags;
+ unsigned long flags;
if (irq > 0) {
spin_lock_irqsave(&lock, flags);
if (pcf_pending == 0) {
spin_unlock_irqrestore(&lock, flags);
- if (interruptible_sleep_on_timeout(&pcf_wait,
- timeout*HZ)) {
+ prepare_to_wait(&pcf_wait, &wait, TASK_INTERRUPTIBLE);
+ if (schedule_timeout(timeout*HZ)) {
spin_lock_irqsave(&lock, flags);
if (pcf_pending == 1) {
pcf_pending = 0;
}
spin_unlock_irqrestore(&lock, flags);
}
+ finish_wait(&pcf_wait, &wait);
} else {
pcf_pending = 0;
spin_unlock_irqrestore(&lock, flags);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 17326cdd68d745..bb885215c08d6c 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -630,10 +630,6 @@ static struct i2c_algorithm iic_algo = {
.name = "IBM IIC algorithm",
.id = I2C_ALGO_OCP,
.master_xfer = iic_xfer,
- .smbus_xfer = NULL,
- .slave_send = NULL,
- .slave_recv = NULL,
- .algo_control = NULL,
.functionality = iic_func
};
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 62638115cf1198..702e3def1b81f6 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -40,6 +40,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -107,7 +108,7 @@ static int iic_ite_getclock(void *data)
* IIC controller interrupts.
*/
static void iic_ite_waitforpin(void) {
-
+ DEFINE_WAIT(wait);
int timeout = 2;
long flags;
@@ -121,13 +122,15 @@ static void iic_ite_waitforpin(void) {
spin_lock_irqsave(&lock, flags);
if (iic_pending == 0) {
spin_unlock_irqrestore(&lock, flags);
- if (interruptible_sleep_on_timeout(&iic_wait, timeout*HZ)) {
+ prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE);
+ if (schedule_timeout(timeout*HZ)) {
spin_lock_irqsave(&lock, flags);
if (iic_pending == 1) {
iic_pending = 0;
}
spin_unlock_irqrestore(&lock, flags);
}
+ finish_wait(&iic_wait, &wait);
} else {
iic_pending = 0;
spin_unlock_irqrestore(&lock, flags);
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index db88a12439562b..5b852782d2f595 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -525,6 +525,8 @@ mv64xxx_i2c_probe(struct device *dev)
drv_data->irq = platform_get_irq(pd, 0);
drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
+ drv_data->adapter.owner = THIS_MODULE;
+ drv_data->adapter.class = I2C_CLASS_HWMON;
drv_data->adapter.timeout = pdata->timeout;
drv_data->adapter.retries = pdata->retries;
dev_set_drvdata(dev, drv_data);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 0ac72c935e752d..fcfa51c1436b56 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1,6 +1,6 @@
/* linux/drivers/i2c/busses/i2c-s3c2410.c
*
- * Copyright (C) 2004 Simtec Electronics
+ * Copyright (C) 2004,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 I2C Controller
@@ -188,6 +188,9 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
} else
stat |= S3C2410_IICSTAT_MASTER_TX;
+ if (msg->flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+
// todo - check for wether ack wanted or not
s3c24xx_i2c_enable_ack(i2c);
@@ -287,7 +290,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
/* ack was not received... */
- dev_err(i2c->dev, "ack was not received\n" );
+ dev_dbg(i2c->dev, "ack was not received\n");
s3c24xx_i2c_stop(i2c, -EREMOTEIO);
goto out_ack;
}
@@ -555,11 +558,18 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
return -EREMOTEIO;
}
+/* declare our i2c functionality */
+static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
+}
+
/* i2c bus registration info */
static struct i2c_algorithm s3c24xx_i2c_algorithm = {
.name = "S3C2410-I2C-Algorithm",
.master_xfer = s3c24xx_i2c_xfer,
+ .functionality = s3c24xx_i2c_func,
};
static struct s3c24xx_i2c s3c24xx_i2c = {
@@ -567,6 +577,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = {
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
.adap = {
.name = "s3c2410-i2c",
+ .owner = THIS_MODULE,
.algo = &s3c24xx_i2c_algorithm,
.retries = 2,
.class = I2C_CLASS_HWMON,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index c872c2849a0bf2..0bb60a636e166a 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -121,12 +121,12 @@ static int vt596_transaction(void)
inb_p(SMBHSTDAT1));
/* Make sure the SMBus host is ready to start transmitting */
- if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
"Resetting...\n", temp);
outb_p(temp, SMBHSTSTS);
- if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp);
return -1;
@@ -168,13 +168,14 @@ static int vt596_transaction(void)
dev_dbg(&vt596_adapter.dev, "Error: no response!\n");
}
- if (inb_p(SMBHSTSTS) != 0x00)
- outb_p(inb(SMBHSTSTS), SMBHSTSTS);
-
- if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
- dev_dbg(&vt596_adapter.dev, "Failed reset at end of "
- "transaction (%02x)\n", temp);
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
+ outb_p(temp, SMBHSTSTS);
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
+ dev_warn(&vt596_adapter.dev, "Failed reset at end "
+ "of transaction (%02x)\n", temp);
+ }
}
+
dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 824c62d3a66c5c..74d23cfce2a340 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -233,9 +233,23 @@ config SENSORS_LM90
LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
MAX6658 sensor chips.
+ The Analog Devices ADT7461 sensor chip is also supported, but only
+ if found in ADM1032 compatibility mode.
+
This driver can also be built as a module. If so, the module
will be called lm90.
+config SENSORS_LM92
+ tristate "National Semiconductor LM92 and compatibles"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for National Semiconductor LM92
+ and Maxim MAX6635 sensor chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called lm92.
+
config SENSORS_MAX1619
tristate "Maxim MAX1619 sensor chip"
depends on I2C && EXPERIMENTAL
@@ -351,6 +365,17 @@ endmenu
menu "Other I2C Chip support"
depends on I2C
+config SENSORS_DS1337
+ tristate "Dallas Semiconductor DS1337 Real Time Clock"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for Dallas Semiconductor
+ DS1337 real-time clock chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called ds1337.
+
config SENSORS_EEPROM
tristate "EEPROM reader"
depends on I2C && EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index a6db6f39476c20..65599161a172df 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
+obj-$(CONFIG_SENSORS_DS1337) += ds1337.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_SENSORS_LM83) += lm83.o
obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_LM87) += lm87.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
+obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
index 5dd7f64fdddd42..b4e3ee568265ff 100644
--- a/drivers/i2c/chips/adm1021.c
+++ b/drivers/i2c/chips/adm1021.c
@@ -28,18 +28,6 @@
#include <linux/i2c-sensor.h>
-/* Registers */
-#define ADM1021_SYSCTL_TEMP 1200
-#define ADM1021_SYSCTL_REMOTE_TEMP 1201
-#define ADM1021_SYSCTL_DIE_CODE 1202
-#define ADM1021_SYSCTL_ALARMS 1203
-
-#define ADM1021_ALARM_TEMP_HIGH 0x40
-#define ADM1021_ALARM_TEMP_LOW 0x20
-#define ADM1021_ALARM_RTEMP_HIGH 0x10
-#define ADM1021_ALARM_RTEMP_LOW 0x08
-#define ADM1021_ALARM_RTEMP_NA 0x04
-
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
@@ -380,7 +368,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
- data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
+ data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c;
if (data->type == adm1021)
data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
if (data->type == adm1023) {
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
new file mode 100644
index 00000000000000..07f16c3fb084df
--- /dev/null
+++ b/drivers/i2c/chips/ds1337.c
@@ -0,0 +1,402 @@
+/*
+ * linux/drivers/i2c/chips/ds1337.c
+ *
+ * Copyright (C) 2005 James Chapman <jchapman@katalix.com>
+ *
+ * based on linux/drivers/acron/char/pcf8583.c
+ * Copyright (C) 2000 Russell King
+ *
+ * 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.
+ *
+ * Driver for Dallas Semiconductor DS1337 real time clock chip
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/string.h>
+#include <linux/rtc.h> /* get the user-level API */
+#include <linux/bcd.h>
+#include <linux/list.h>
+
+/* Device registers */
+#define DS1337_REG_HOUR 2
+#define DS1337_REG_DAY 3
+#define DS1337_REG_DATE 4
+#define DS1337_REG_MONTH 5
+#define DS1337_REG_CONTROL 14
+#define DS1337_REG_STATUS 15
+
+/* FIXME - how do we export these interface constants? */
+#define DS1337_GET_DATE 0
+#define DS1337_SET_DATE 1
+
+/*
+ * Functions declaration
+ */
+static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+SENSORS_INSMOD_1(ds1337);
+
+static int ds1337_attach_adapter(struct i2c_adapter *adapter);
+static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
+static void ds1337_init_client(struct i2c_client *client);
+static int ds1337_detach_client(struct i2c_client *client);
+static int ds1337_command(struct i2c_client *client, unsigned int cmd,
+ void *arg);
+
+/*
+ * Driver data (common to all clients)
+ */
+static struct i2c_driver ds1337_driver = {
+ .owner = THIS_MODULE,
+ .name = "ds1337",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = ds1337_attach_adapter,
+ .detach_client = ds1337_detach_client,
+ .command = ds1337_command,
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+struct ds1337_data {
+ struct i2c_client client;
+ struct list_head list;
+ int id;
+};
+
+/*
+ * Internal variables
+ */
+static int ds1337_id;
+static LIST_HEAD(ds1337_clients);
+
+static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
+{
+ s32 tmp = i2c_smbus_read_byte_data(client, reg);
+
+ if (tmp < 0)
+ return -EIO;
+
+ *value = tmp;
+
+ return 0;
+}
+
+/*
+ * Chip access functions
+ */
+static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+ struct ds1337_data *data = i2c_get_clientdata(client);
+ int result;
+ u8 buf[7];
+ u8 val;
+ struct i2c_msg msg[2];
+ u8 offs = 0;
+
+ if (!dt) {
+ dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
+ __FUNCTION__);
+
+ return -EINVAL;
+ }
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &offs;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = sizeof(buf);
+ msg[1].buf = &buf[0];
+
+ result = client->adapter->algo->master_xfer(client->adapter,
+ &msg[0], 2);
+
+ dev_dbg(&client->adapter->dev,
+ "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
+ __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6]);
+
+ if (result >= 0) {
+ dt->tm_sec = BCD_TO_BIN(buf[0]);
+ dt->tm_min = BCD_TO_BIN(buf[1]);
+ val = buf[2] & 0x3f;
+ dt->tm_hour = BCD_TO_BIN(val);
+ dt->tm_wday = BCD_TO_BIN(buf[3]) - 1;
+ dt->tm_mday = BCD_TO_BIN(buf[4]);
+ val = buf[5] & 0x7f;
+ dt->tm_mon = BCD_TO_BIN(val);
+ dt->tm_year = 1900 + BCD_TO_BIN(buf[6]);
+ if (buf[5] & 0x80)
+ dt->tm_year += 100;
+
+ dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__, dt->tm_sec, dt->tm_min,
+ dt->tm_hour, dt->tm_mday,
+ dt->tm_mon, dt->tm_year, dt->tm_wday);
+ } else {
+ dev_err(&client->adapter->dev, "ds1337[%d]: error reading "
+ "data! %d\n", data->id, result);
+ result = -EIO;
+ }
+
+ return result;
+}
+
+static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+ struct ds1337_data *data = i2c_get_clientdata(client);
+ int result;
+ u8 buf[8];
+ u8 val;
+ struct i2c_msg msg[1];
+
+ if (!dt) {
+ dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
+ __FUNCTION__);
+
+ return -EINVAL;
+ }
+
+ dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
+ dt->tm_sec, dt->tm_min, dt->tm_hour,
+ dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
+
+ buf[0] = 0; /* reg offset */
+ buf[1] = BIN_TO_BCD(dt->tm_sec);
+ buf[2] = BIN_TO_BCD(dt->tm_min);
+ buf[3] = BIN_TO_BCD(dt->tm_hour) | (1 << 6);
+ buf[4] = BIN_TO_BCD(dt->tm_wday) + 1;
+ buf[5] = BIN_TO_BCD(dt->tm_mday);
+ buf[6] = BIN_TO_BCD(dt->tm_mon);
+ if (dt->tm_year >= 2000) {
+ val = dt->tm_year - 2000;
+ buf[6] |= (1 << 7);
+ } else {
+ val = dt->tm_year - 1900;
+ }
+ buf[7] = BIN_TO_BCD(val);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = sizeof(buf);
+ msg[0].buf = &buf[0];
+
+ result = client->adapter->algo->master_xfer(client->adapter,
+ &msg[0], 1);
+ if (result < 0) {
+ dev_err(&client->adapter->dev, "ds1337[%d]: error "
+ "writing data! %d\n", data->id, result);
+ result = -EIO;
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+static int ds1337_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ dev_dbg(&client->adapter->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+
+ switch (cmd) {
+ case DS1337_GET_DATE:
+ return ds1337_get_datetime(client, arg);
+
+ case DS1337_SET_DATE:
+ return ds1337_set_datetime(client, arg);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * Public API for access to specific device. Useful for low-level
+ * RTC access from kernel code.
+ */
+int ds1337_do_command(int id, int cmd, void *arg)
+{
+ struct list_head *walk;
+ struct list_head *tmp;
+ struct ds1337_data *data;
+
+ list_for_each_safe(walk, tmp, &ds1337_clients) {
+ data = list_entry(walk, struct ds1337_data, list);
+ if (data->id == id)
+ return ds1337_command(&data->client, cmd, arg);
+ }
+
+ return -ENODEV;
+}
+
+static int ds1337_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, ds1337_detect);
+}
+
+/*
+ * The following function does more than just detection. If detection
+ * succeeds, it also registers the new chip.
+ */
+static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct ds1337_data *data;
+ int err = 0;
+ const char *name = "";
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_I2C))
+ goto exit;
+
+ if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct ds1337_data));
+ INIT_LIST_HEAD(&data->list);
+
+ /* The common I2C client data is placed right before the
+ * DS1337-specific data.
+ */
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &ds1337_driver;
+ new_client->flags = 0;
+
+ /*
+ * Now we do the remaining detection. A negative kind means that
+ * the driver was loaded with no force parameter (default), so we
+ * must both detect and identify the chip. A zero kind means that
+ * the driver was loaded with the force parameter, the detection
+ * step shall be skipped. A positive kind means that the driver
+ * was loaded with the force parameter and a given kind of chip is
+ * requested, so both the detection and the identification steps
+ * are skipped.
+ *
+ * For detection, we read registers that are most likely to cause
+ * detection failure, i.e. those that have more bits with fixed
+ * or reserved values.
+ */
+
+ /* Default to an DS1337 if forced */
+ if (kind == 0)
+ kind = ds1337;
+
+ if (kind < 0) { /* detection and identification */
+ u8 data;
+
+ /* Check that status register bits 6-2 are zero */
+ if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) ||
+ (data & 0x7c))
+ goto exit_free;
+
+ /* Check for a valid day register value */
+ if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) ||
+ (data == 0) || (data & 0xf8))
+ goto exit_free;
+
+ /* Check for a valid date register value */
+ if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) ||
+ (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) ||
+ (data >= 0x32))
+ goto exit_free;
+
+ /* Check for a valid month register value */
+ if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) ||
+ (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) ||
+ ((data >= 0x13) && (data <= 0x19)))
+ goto exit_free;
+
+ /* Check that control register bits 6-5 are zero */
+ if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) ||
+ (data & 0x60))
+ goto exit_free;
+
+ kind = ds1337;
+ }
+
+ if (kind == ds1337)
+ name = "ds1337";
+
+ /* We can fill in the remaining client fields */
+ strlcpy(new_client->name, name, I2C_NAME_SIZE);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ /* Initialize the DS1337 chip */
+ ds1337_init_client(new_client);
+
+ /* Add client to local list */
+ data->id = ds1337_id++;
+ list_add(&data->list, &ds1337_clients);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static void ds1337_init_client(struct i2c_client *client)
+{
+ s32 val;
+
+ /* Ensure that device is set in 24-hour mode */
+ val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+ if ((val >= 0) && (val & (1 << 6)) == 0)
+ i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+ val | (1 << 6));
+}
+
+static int ds1337_detach_client(struct i2c_client *client)
+{
+ int err;
+ struct ds1337_data *data = i2c_get_clientdata(client);
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ list_del(&data->list);
+ kfree(data);
+ return 0;
+}
+
+static int __init ds1337_init(void)
+{
+ return i2c_add_driver(&ds1337_driver);
+}
+
+static void __exit ds1337_exit(void)
+{
+ i2c_del_driver(&ds1337_driver);
+}
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("DS1337 RTC driver");
+MODULE_LICENSE("GPL");
+
+module_init(ds1337_init);
+module_exit(ds1337_exit);
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index f126d011cfee26..cbdfa2db6f7c90 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -210,10 +210,11 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
&& i2c_smbus_read_byte(new_client) == 'C'
&& i2c_smbus_read_byte(new_client) == 'G'
- && i2c_smbus_read_byte(new_client) == '-')
+ && i2c_smbus_read_byte(new_client) == '-') {
dev_info(&new_client->dev, "Vaio EEPROM detected, "
"enabling password protection\n");
data->nature = VAIO;
+ }
}
/* create the sysfs eeprom file */
diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
index e62c2e390076bc..bf02ba555a8518 100644
--- a/drivers/i2c/chips/it87.c
+++ b/drivers/i2c/chips/it87.c
@@ -734,10 +734,9 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR0;
/* Probe whether there is anything available on this address. Already
- done for SMBus clients */
+ done for SMBus and Super-I/O clients */
if (kind < 0) {
- if (is_isa) {
-
+ if (is_isa && !chip_type) {
#define REALLY_SLOW_IO
/* We need the timeouts for at least some IT87-like chips. But only
if we read 'undefined' registers. */
@@ -890,9 +889,9 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (data->type == it8712) {
+ data->vrm = i2c_which_vrm();
device_create_file_vrm(new_client);
device_create_file_vid(new_client);
- data->vrm = i2c_which_vrm();
}
return 0;
@@ -1123,9 +1122,6 @@ static struct it87_data *it87_update_device(struct device *dev)
it87_read_value(client, IT87_REG_TEMP_LOW(i));
}
- /* The 8705 does not have VID capability */
- data->vid = 0x1f;
-
i = it87_read_value(client, IT87_REG_FAN_DIV);
data->fan_div[0] = i & 0x07;
data->fan_div[1] = (i >> 3) & 0x07;
diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
index d17aba4e42fcd9..e08000b948b2f6 100644
--- a/drivers/i2c/chips/lm85.c
+++ b/drivers/i2c/chips/lm85.c
@@ -37,7 +37,7 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
+SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
/* The LM85 registers */
@@ -74,8 +74,10 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
#define LM85_VERSTEP_LM85B 0x62
#define LM85_VERSTEP_ADM1027 0x60
#define LM85_VERSTEP_ADT7463 0x62
+#define LM85_VERSTEP_ADT7463C 0x6A
#define LM85_VERSTEP_EMC6D100_A0 0x60
#define LM85_VERSTEP_EMC6D100_A1 0x61
+#define LM85_VERSTEP_EMC6D102 0x65
#define LM85_REG_CONFIG 0x40
@@ -112,9 +114,13 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
#define EMC6D100_REG_ALARM3 0x7d
/* IN5, IN6 and IN7 */
-#define EMC6D100_REG_IN(nr) (0x70 + ((nr)-5))
-#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr)-5) * 2)
-#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr)-5) * 2)
+#define EMC6D100_REG_IN(nr) (0x70 + ((nr)-5))
+#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr)-5) * 2)
+#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr)-5) * 2)
+#define EMC6D102_REG_EXTEND_ADC1 0x85
+#define EMC6D102_REG_EXTEND_ADC2 0x86
+#define EMC6D102_REG_EXTEND_ADC3 0x87
+#define EMC6D102_REG_EXTEND_ADC4 0x88
#define LM85_ALARM_IN0 0x0001
#define LM85_ALARM_IN1 0x0002
@@ -139,35 +145,36 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
these macros are called: arguments may be evaluated more than once.
*/
-/* IN are scaled 1.000 == 0xc0, mag = 3 */
-#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255))
-#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0)
-#define IN_FROM_REG(val) (INEXT_FROM_REG(val,0))
-
/* IN are scaled acording to built-in resistors */
static int lm85_scaling[] = { /* .001 Volts */
2500, 2250, 3300, 5000, 12000,
3300, 1500, 1800 /*EMC6D100*/
};
#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
-#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
-#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
-#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
+
+#define INS_TO_REG(n,val) \
+ SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255)
+
+#define INSEXT_FROM_REG(n,val,ext,scale) \
+ SCALE((val)*(scale) + (ext),192*(scale),lm85_scaling[n])
+
+#define INS_FROM_REG(n,val) INSEXT_FROM_REG(n,val,0,1)
/* FAN speed is measured using 90kHz clock */
#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
#define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val))
/* Temperature is reported in .001 degC increments */
-#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+500)/1000,-127,127))
-#define TEMPEXT_FROM_REG(val,ext) ((val)*1000 + (ext)*250)
-#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0))
-#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/250,-127,127))
+#define TEMP_TO_REG(val) \
+ SENSORS_LIMIT(SCALE(val,1000,1),-127,127)
+#define TEMPEXT_FROM_REG(val,ext,scale) \
+ SCALE((val)*scale + (ext),scale,1000)
+#define TEMP_FROM_REG(val) \
+ TEMPEXT_FROM_REG(val,0,1)
#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
#define PWM_FROM_REG(val) (val)
-#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03)
/* ZONEs have the following parameters:
* Limit (low) temp, 1. degC
@@ -355,7 +362,9 @@ struct lm85_data {
u8 pwm[3]; /* Register value */
u8 spinup_ctl; /* Register encoding, combined */
u8 tach_mode; /* Register encoding, combined */
- u16 extend_adc; /* Register value */
+ u8 temp_ext[3]; /* Decoded values */
+ u8 in_ext[8]; /* Decoded values */
+ u8 adc_scale; /* ADC Extended bits scaling factor */
u8 fan_ppr; /* Register value */
u8 smooth[3]; /* Register encoding */
u8 vid; /* Register value */
@@ -536,7 +545,10 @@ show_pwm_reg(3);
static ssize_t show_in(struct device *dev, char *buf, int nr)
{
struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) );
+ return sprintf( buf, "%d\n", INSEXT_FROM_REG(nr,
+ data->in[nr],
+ data->in_ext[nr],
+ data->adc_scale) );
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
{
@@ -617,7 +629,9 @@ show_in_reg(4);
static ssize_t show_temp(struct device *dev, char *buf, int nr)
{
struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
+ return sprintf(buf,"%d\n", TEMPEXT_FROM_REG(data->temp[nr],
+ data->temp_ext[nr],
+ data->adc_scale) );
}
static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
{
@@ -1089,7 +1103,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
&& verstep == LM85_VERSTEP_ADM1027 ) {
kind = adm1027 ;
} else if( company == LM85_COMPANY_ANALOG_DEV
- && verstep == LM85_VERSTEP_ADT7463 ) {
+ && (verstep == LM85_VERSTEP_ADT7463
+ || verstep == LM85_VERSTEP_ADT7463C) ) {
kind = adt7463 ;
} else if( company == LM85_COMPANY_ANALOG_DEV
&& (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC ) {
@@ -1107,6 +1122,9 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
*/
kind = emc6d100 ;
} else if( company == LM85_COMPANY_SMSC
+ && verstep == LM85_VERSTEP_EMC6D102) {
+ kind = emc6d102 ;
+ } else if( company == LM85_COMPANY_SMSC
&& (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
dev_err(&adapter->dev, "lm85: Detected SMSC chip\n");
dev_err(&adapter->dev, "lm85: Unrecognized version/stepping 0x%02x"
@@ -1142,6 +1160,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
type_name = "adt7463";
} else if ( kind == emc6d100){
type_name = "emc6d100";
+ } else if ( kind == emc6d102 ) {
+ type_name = "emc6d102";
}
strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
@@ -1259,7 +1279,6 @@ int lm85_read_value(struct i2c_client *client, u8 reg)
case LM85_REG_FAN_MIN(2) :
case LM85_REG_FAN_MIN(3) :
case LM85_REG_ALARM1 : /* Read both bytes at once */
- case ADM1027_REG_EXTEND_ADC1 : /* Read two bytes at once */
res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ;
break ;
@@ -1363,10 +1382,25 @@ static struct lm85_data *lm85_update_device(struct device *dev)
* more significant bits that are read later.
*/
if ( (data->type == adm1027) || (data->type == adt7463) ) {
- data->extend_adc =
- lm85_read_value(client, ADM1027_REG_EXTEND_ADC1);
+ int ext1 = lm85_read_value(client,
+ ADM1027_REG_EXTEND_ADC1);
+ int ext2 = lm85_read_value(client,
+ ADM1027_REG_EXTEND_ADC2);
+ int val = (ext1 << 8) + ext2;
+
+ for(i = 0; i <= 4; i++)
+ data->in_ext[i] = (val>>(i * 2))&0x03;
+
+ for(i = 0; i <= 2; i++)
+ data->temp_ext[i] = (val>>((i + 5) * 2))&0x03;
}
+ /* adc_scale is 2^(number of LSBs). There are 4 extra bits in
+ the emc6d102 and 2 in the adt7463 and adm1027. In all
+ other chips ext is always 0 and the value of scale is
+ irrelevant. So it is left in 4*/
+ data->adc_scale = (data->type == emc6d102 ) ? 16 : 4;
+
for (i = 0; i <= 4; ++i) {
data->in[i] =
lm85_read_value(client, LM85_REG_IN(i));
@@ -1403,6 +1437,28 @@ static struct lm85_data *lm85_update_device(struct device *dev)
/* More alarm bits */
data->alarms |=
lm85_read_value(client, EMC6D100_REG_ALARM3) << 16;
+ } else if (data->type == emc6d102 ) {
+ /* Have to read LSB bits after the MSB ones because
+ the reading of the MSB bits has frozen the
+ LSBs (backward from the ADM1027).
+ */
+ int ext1 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC1);
+ int ext2 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC2);
+ int ext3 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC3);
+ int ext4 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC4);
+ data->in_ext[0] = ext3 & 0x0f;
+ data->in_ext[1] = ext4 & 0x0f;
+ data->in_ext[2] = (ext4 >> 4) & 0x0f;
+ data->in_ext[3] = (ext3 >> 4) & 0x0f;
+ data->in_ext[4] = (ext2 >> 4) & 0x0f;
+
+ data->temp_ext[0] = ext1 & 0x0f;
+ data->temp_ext[1] = ext2 & 0x0f;
+ data->temp_ext[2] = (ext1 >> 4) & 0x0f;
}
data->last_reading = jiffies ;
diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c
index 8b9e2de21bff74..49d92326faab5f 100644
--- a/drivers/i2c/chips/lm87.c
+++ b/drivers/i2c/chips/lm87.c
@@ -317,20 +317,20 @@ show_temp(3);
static void set_temp_low(struct device *dev, const char *buf, int nr)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm87_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
- data->temp_low[nr] = TEMP_TO_REG(val);
- lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm87_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ data->temp_low[nr] = TEMP_TO_REG(val);
+ lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]);
}
static void set_temp_high(struct device *dev, const char *buf, int nr)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm87_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
- data->temp_high[nr] = TEMP_TO_REG(val);
- lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm87_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ data->temp_high[nr] = TEMP_TO_REG(val);
+ lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]);
}
#define set_temp(offset) \
diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
index 7540b230173e8b..02e22b128b0453 100644
--- a/drivers/i2c/chips/lm90.c
+++ b/drivers/i2c/chips/lm90.c
@@ -43,6 +43,14 @@
* variants. The extra address and features of the MAX6659 are not
* supported by this driver.
*
+ * This driver also supports the ADT7461 chip from Analog Devices but
+ * only in its "compatability mode". If an ADT7461 chip is found but
+ * is configured in non-compatible mode (where its temperature
+ * register values are decoded differently) it is ignored by this
+ * driver. Complete datasheet can be obtained from Analog's website
+ * at:
+ * http://products.analog.com/products/info.asp?product=ADT7461
+ *
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
* concern all supported chipsets, unless mentioned otherwise.
@@ -77,6 +85,7 @@
* LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
* LM89-1, and LM99-1 have address 0x4d.
* MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
+ * ADT7461 always has address 0x4c.
*/
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
@@ -86,7 +95,7 @@ static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
* Insmod parameters
*/
-SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657);
+SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
/*
* The LM90 registers
@@ -148,6 +157,19 @@ SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657);
#define HYST_TO_REG(val) ((val) <= 0 ? 0 : (val) >= 30500 ? 31 : \
((val) + 500) / 1000)
+/*
+ * ADT7461 is almost identical to LM90 except that attempts to write
+ * values that are outside the range 0 < temp < 127 are treated as
+ * the boundary value.
+ */
+
+#define TEMP1_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \
+ (val) >= 127000 ? 127 : \
+ ((val) + 500) / 1000)
+#define TEMP2_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \
+ (val) >= 127750 ? 0x7FC0 : \
+ ((val) + 125) / 250 * 64)
+
/*
* Functions declaration
*/
@@ -181,6 +203,7 @@ struct lm90_data {
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
+ int kind;
/* registers values */
s8 temp_input1, temp_low1, temp_high1; /* local */
@@ -216,7 +239,10 @@ static ssize_t set_##value(struct device *dev, const char *buf, \
struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \
- data->value = TEMP1_TO_REG(val); \
+ if (data->kind == adt7461) \
+ data->value = TEMP1_TO_REG_ADT7461(val); \
+ else \
+ data->value = TEMP1_TO_REG(val); \
i2c_smbus_write_byte_data(client, reg, data->value); \
return count; \
}
@@ -227,7 +253,10 @@ static ssize_t set_##value(struct device *dev, const char *buf, \
struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \
- data->value = TEMP2_TO_REG(val); \
+ if (data->kind == adt7461) \
+ data->value = TEMP2_TO_REG_ADT7461(val); \
+ else \
+ data->value = TEMP2_TO_REG(val); \
i2c_smbus_write_byte_data(client, regh, data->value >> 8); \
i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \
return count; \
@@ -381,6 +410,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
&& (reg_config1 & 0x3F) == 0x00
&& reg_convrate <= 0x0A) {
kind = adm1032;
+ } else
+ if (address == 0x4c
+ && chip_id == 0x51 /* ADT7461 */
+ && (reg_config1 & 0x1F) == 0x00 /* check compat mode */
+ && reg_convrate <= 0x0A) {
+ kind = adt7461;
}
} else
if (man_id == 0x4D) { /* Maxim */
@@ -418,11 +453,14 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
name = "lm86";
} else if (kind == max6657) {
name = "max6657";
+ } else if (kind == adt7461) {
+ name = "adt7461";
}
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0;
+ data->kind = kind;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
diff --git a/drivers/i2c/chips/lm92.c b/drivers/i2c/chips/lm92.c
new file mode 100644
index 00000000000000..3c9d0ef8eca79e
--- /dev/null
+++ b/drivers/i2c/chips/lm92.c
@@ -0,0 +1,423 @@
+/*
+ * lm92 - Hardware monitoring driver
+ * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ *
+ * Based on the lm90 driver, with some ideas taken from the lm_sensors
+ * lm92 driver as well.
+ *
+ * The LM92 is a sensor chip made by National Semiconductor. It reports
+ * its own temperature with a 0.0625 deg resolution and a 0.33 deg
+ * accuracy. Complete datasheet can be obtained from National's website
+ * at:
+ * http://www.national.com/pf/LM/LM92.html
+ *
+ * This driver also supports the MAX6635 sensor chip made by Maxim.
+ * This chip is compatible with the LM92, but has a lesser accuracy
+ * (1.0 deg). Complete datasheet can be obtained from Maxim's website
+ * at:
+ * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
+ *
+ * Since the LM92 was the first chipset supported by this driver, most
+ * comments will refer to this chipset, but are actually general and
+ * concern all supported chipsets, unless mentioned otherwise.
+ *
+ * Support could easily be added for the National Semiconductor LM76
+ * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible
+ * with the LM92.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+
+/* The LM92 and MAX6635 have 2 two-state pins for address selection,
+ resulting in 4 possible addresses. */
+static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+ I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(lm92);
+
+/* The LM92 registers */
+#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */
+#define LM92_REG_TEMP 0x00 /* 16-bit, RO */
+#define LM92_REG_TEMP_HYST 0x02 /* 16-bit, RW */
+#define LM92_REG_TEMP_CRIT 0x03 /* 16-bit, RW */
+#define LM92_REG_TEMP_LOW 0x04 /* 16-bit, RW */
+#define LM92_REG_TEMP_HIGH 0x05 /* 16-bit, RW */
+#define LM92_REG_MAN_ID 0x07 /* 16-bit, RO, LM92 only */
+
+/* The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius,
+ left-justified in 16-bit registers. No rounding is done, with such
+ a resolution it's just not worth it. Note that the MAX6635 doesn't
+ make use of the 4 lower bits for limits (i.e. effective resolution
+ for limits is 1 degree Celsius). */
+static inline int TEMP_FROM_REG(s16 reg)
+{
+ return reg / 8 * 625 / 10;
+}
+
+static inline s16 TEMP_TO_REG(int val)
+{
+ if (val <= -60000)
+ return -60000 * 10 / 625 * 8;
+ if (val >= 160000)
+ return 160000 * 10 / 625 * 8;
+ return val * 10 / 625 * 8;
+}
+
+/* Alarm flags are stored in the 3 LSB of the temperature register */
+static inline u8 ALARMS_FROM_REG(s16 reg)
+{
+ return reg & 0x0007;
+}
+
+/* Driver data (common to all clients) */
+static struct i2c_driver lm92_driver;
+
+/* Client data (each client gets its own) */
+struct lm92_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ char valid; /* zero until following fields are valid */
+ unsigned long last_updated; /* in jiffies */
+
+ /* registers values */
+ s16 temp1_input, temp1_crit, temp1_min, temp1_max, temp1_hyst;
+};
+
+
+/*
+ * Sysfs attributes and callback functions
+ */
+
+static struct lm92_data *lm92_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm92_data *data = i2c_get_clientdata(client);
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ)
+ || !data->valid) {
+ dev_dbg(&client->dev, "Updating lm92 data\n");
+ data->temp1_input = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP));
+ data->temp1_hyst = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HYST));
+ data->temp1_crit = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_CRIT));
+ data->temp1_min = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_LOW));
+ data->temp1_max = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HIGH));
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+#define show_temp(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+ struct lm92_data *data = lm92_update_device(dev); \
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+}
+show_temp(temp1_input);
+show_temp(temp1_crit);
+show_temp(temp1_min);
+show_temp(temp1_max);
+
+#define set_temp(value, reg) \
+static ssize_t set_##value(struct device *dev, const char *buf, \
+ size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct lm92_data *data = i2c_get_clientdata(client); \
+ long val = simple_strtol(buf, NULL, 10); \
+ data->value = TEMP_TO_REG(val); \
+ i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
+ return count; \
+}
+set_temp(temp1_crit, LM92_REG_TEMP_CRIT);
+set_temp(temp1_min, LM92_REG_TEMP_LOW);
+set_temp(temp1_max, LM92_REG_TEMP_HIGH);
+
+static ssize_t show_temp1_crit_hyst(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit)
+ - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_max_hyst(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max)
+ - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_min_hyst(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min)
+ + TEMP_FROM_REG(data->temp1_hyst));
+}
+
+static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm92_data *data = i2c_get_clientdata(client);
+ data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) -
+ simple_strtol(buf, NULL, 10);
+ i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
+ swab16(TEMP_TO_REG(data->temp1_hyst)));
+ return count;
+}
+
+static ssize_t show_alarms(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input));
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL);
+static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp1_crit,
+ set_temp1_crit);
+static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp1_crit_hyst,
+ set_temp1_crit_hyst);
+static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp1_min,
+ set_temp1_min);
+static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp1_min_hyst, NULL);
+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_max,
+ set_temp1_max);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp1_max_hyst, NULL);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+
+/*
+ * Detection and registration
+ */
+
+static void lm92_init_client(struct i2c_client *client)
+{
+ u8 config;
+
+ /* Start the conversions if needed */
+ config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+ if (config & 0x01)
+ i2c_smbus_write_byte_data(client, LM92_REG_CONFIG,
+ config & 0xFE);
+}
+
+/* The MAX6635 has no identification register, so we have to use tricks
+ to identify it reliably. This is somewhat slow.
+ Note that we do NOT rely on the 2 MSB of the configuration register
+ always reading 0, as suggested by the datasheet, because it was once
+ reported not to be true. */
+static int max6635_check(struct i2c_client *client)
+{
+ u16 temp_low, temp_high, temp_hyst, temp_crit;
+ u8 conf;
+ int i;
+
+ /* No manufacturer ID register, so a read from this address will
+ always return the last read value. */
+ temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW);
+ if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low)
+ return 0;
+ temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH);
+ if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high)
+ return 0;
+
+ /* Limits are stored as integer values (signed, 9-bit). */
+ if ((temp_low & 0x7f00) || (temp_high & 0x7f00))
+ return 0;
+ temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST);
+ temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT);
+ if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00))
+ return 0;
+
+ /* Registers addresses were found to cycle over 16-byte boundaries.
+ We don't test all registers with all offsets so as to save some
+ reads and time, but this should still be sufficient to dismiss
+ non-MAX6635 chips. */
+ conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+ for (i=16; i<96; i*=2) {
+ if (temp_hyst != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HYST + i - 16)
+ || temp_crit != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_CRIT + i)
+ || temp_low != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_LOW + i + 16)
+ || temp_high != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HIGH + i + 32)
+ || conf != i2c_smbus_read_byte_data(client,
+ LM92_REG_CONFIG + i))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* The following function does more than just detection. If detection
+ succeeds, it also registers the new chip. */
+static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct lm92_data *data;
+ int err = 0;
+ char *name;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
+ | I2C_FUNC_SMBUS_WORD_DATA))
+ goto exit;
+
+ if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct lm92_data));
+
+ /* Fill in enough client fields so that we can read from the chip,
+ which is required for identication */
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &lm92_driver;
+ new_client->flags = 0;
+
+ /* A negative kind means that the driver was loaded with no force
+ parameter (default), so we must identify the chip. */
+ if (kind < 0) {
+ u8 config = i2c_smbus_read_byte_data(new_client,
+ LM92_REG_CONFIG);
+ u16 man_id = i2c_smbus_read_word_data(new_client,
+ LM92_REG_MAN_ID);
+
+ if ((config & 0xe0) == 0x00
+ && man_id == 0x0180) {
+ pr_info("lm92: Found National Semiconductor LM92 chip\n");
+ kind = lm92;
+ } else
+ if (max6635_check(new_client)) {
+ pr_info("lm92: Found Maxim MAX6635 chip\n");
+ kind = lm92; /* No separate prefix */
+ }
+ else
+ goto exit_free;
+ } else
+ if (kind == 0) /* Default to an LM92 if forced */
+ kind = lm92;
+
+ /* Give it the proper name */
+ if (kind == lm92) {
+ name = "lm92";
+ } else { /* Supposedly cannot happen */
+ dev_dbg(&new_client->dev, "Kind out of range?\n");
+ goto exit_free;
+ }
+
+ /* Fill in the remaining client fields */
+ strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the i2c subsystem a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ /* Initialize the chipset */
+ lm92_init_client(new_client);
+
+ /* Register sysfs hooks */
+ device_create_file(&new_client->dev, &dev_attr_temp1_input);
+ device_create_file(&new_client->dev, &dev_attr_temp1_crit);
+ device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
+ device_create_file(&new_client->dev, &dev_attr_temp1_min);
+ device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int lm92_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, lm92_detect);
+}
+
+static int lm92_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+
+/*
+ * Module and driver stuff
+ */
+
+static struct i2c_driver lm92_driver = {
+ .owner = THIS_MODULE,
+ .name = "lm92",
+ .id = I2C_DRIVERID_LM92,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = lm92_attach_adapter,
+ .detach_client = lm92_detach_client,
+};
+
+static int __init sensors_lm92_init(void)
+{
+ return i2c_add_driver(&lm92_driver);
+}
+
+static void __exit sensors_lm92_exit(void)
+{
+ i2c_del_driver(&lm92_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("LM92/MAX6635 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm92_init);
+module_exit(sensors_lm92_exit);
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index de270e920207a2..e771566dffa8d6 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -184,7 +184,6 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
memset(client, 0, sizeof(struct i2c_client));
strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
- client->id = m41t00_driver.id;
client->flags = I2C_DF_NOTIFY;
client->addr = addr;
client->adapter = adap;
diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
index 986dba3f0a7275..133e449dc14efa 100644
--- a/drivers/i2c/chips/w83627hf.c
+++ b/drivers/i2c/chips/w83627hf.c
@@ -304,7 +304,6 @@ struct w83627hf_data {
u32 beep_mask; /* Register encoding, combined */
u8 beep_enable; /* Boolean */
u8 pwm[3]; /* Register value */
- u8 pwmenable[3]; /* bool */
u16 sens[3]; /* 782D/783S only.
1 = pentium diode; 2 = 3904 diode;
3000-5000 = thermistor beta.
@@ -1317,10 +1316,6 @@ static void w83627hf_init_client(struct i2c_client *client)
break;
}
- data->pwmenable[0] = 1;
- data->pwmenable[1] = 1;
- data->pwmenable[2] = 1;
-
if(init) {
/* Enable temp2 */
tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG);
diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
index e893229239d072..628d769cf47516 100644
--- a/drivers/i2c/chips/w83781d.c
+++ b/drivers/i2c/chips/w83781d.c
@@ -46,9 +46,6 @@
#include <asm/io.h>
#include "lm75.h"
-/* RT Table support #defined so we can take it out if it gets bothersome */
-#define W83781D_RT 1
-
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
@@ -258,9 +255,6 @@ struct w83781d_data {
3000-5000 = thermistor beta.
Default = 3435.
Other Betas unimplemented */
-#ifdef W83781D_RT
- u8 rt[3][32]; /* Register value */
-#endif
u8 vrm;
};
@@ -834,66 +828,6 @@ do { \
device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
} while (0)
-#ifdef W83781D_RT
-static ssize_t
-show_rt_reg(struct device *dev, char *buf, int nr)
-{
- struct w83781d_data *data = w83781d_update_device(dev);
- int i, j = 0;
-
- for (i = 0; i < 32; i++) {
- if (i > 0)
- j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]);
- else
- j += sprintf(buf, "%ld", (long) data->rt[nr - 1][i]);
- }
- j += sprintf(buf, "\n");
-
- return j;
-}
-
-static ssize_t
-store_rt_reg(struct device *dev, const char *buf, size_t count, int nr)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83781d_data *data = i2c_get_clientdata(client);
- u32 val, i;
-
- for (i = 0; i < count; i++) {
- val = simple_strtoul(buf + count, NULL, 10);
-
- /* fixme: no bounds checking 0-255 */
- data->rt[nr - 1][i] = val & 0xff;
- w83781d_write_value(client, W83781D_REG_RT_IDX, i);
- w83781d_write_value(client, W83781D_REG_RT_VAL,
- data->rt[nr - 1][i]);
- }
-
- return count;
-}
-
-#define sysfs_rt(offset) \
-static ssize_t show_regs_rt_##offset (struct device *dev, char *buf) \
-{ \
- return show_rt_reg(dev, buf, offset); \
-} \
-static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size_t count) \
-{ \
- return store_rt_reg(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset);
-
-sysfs_rt(1);
-sysfs_rt(2);
-sysfs_rt(3);
-
-#define device_create_file_rt(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_rt##offset); \
-} while (0)
-
-#endif /* ifdef W83781D_RT */
-
/* This function is called when:
* w83781d_driver is inserted (when this module is loaded), for each
available adapter
@@ -1304,13 +1238,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind != w83783s && kind != w83697hf)
device_create_file_sensor(new_client, 3);
}
-#ifdef W83781D_RT
- if (kind == w83781d) {
- device_create_file_rt(new_client, 1);
- device_create_file_rt(new_client, 2);
- device_create_file_rt(new_client, 3);
- }
-#endif
return 0;
@@ -1535,33 +1462,6 @@ w83781d_init_client(struct i2c_client *client)
break;
}
}
-#ifdef W83781D_RT
-/*
- Fill up the RT Tables.
- We assume that they are 32 bytes long, in order for temp 1-3.
- Data sheet documentation is sparse.
- We also assume that it is only for the 781D although I suspect
- that the others support it as well....
-*/
-
- if (init && type == w83781d) {
- u16 k = 0;
-/*
- Auto-indexing doesn't seem to work...
- w83781d_write_value(client,W83781D_REG_RT_IDX,0);
-*/
- for (i = 0; i < 3; i++) {
- int j;
- for (j = 0; j < 32; j++) {
- w83781d_write_value(client,
- W83781D_REG_RT_IDX, k++);
- data->rt[i][j] =
- w83781d_read_value(client,
- W83781D_REG_RT_VAL);
- }
- }
- }
-#endif /* W83781D_RT */
if (init && type != as99127f) {
/* Enable temp2 */
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 56a67457341d4d..e62a91a45a291e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -587,7 +587,13 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
int ret;
if (adap->algo->master_xfer) {
- dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num);
+#ifdef DEBUG
+ for (ret = 0; ret < num; ret++) {
+ dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
+ "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
+ 'R' : 'W', msgs[ret].addr, msgs[ret].len);
+ }
+#endif
down(&adap->bus_lock);
ret = adap->algo->master_xfer(adap,msgs,num);
@@ -709,7 +715,7 @@ int i2c_probe(struct i2c_adapter *adapter,
at all */
found = 0;
- for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
+ for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
if (((adap_id == address_data->force[i]) ||
(address_data->force[i] == ANY_I2C_BUS)) &&
(addr == address_data->force[i+1])) {
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index e8d11a7c48a817..3c092117a8eae4 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -984,7 +984,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
BUG(); // we're called with the master device always
slot = lp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
lp->ppp_slot);
kfree_skb(skb);
@@ -1039,7 +1039,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
int slot;
slot = lp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
lp->ppp_slot);
goto drop_packet;
@@ -1234,7 +1234,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
nd = mlp->netdev; /* get master lp */
slot = mlp->ppp_slot;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
mlp->ppp_slot);
kfree_skb(skb);
@@ -1882,7 +1882,7 @@ void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
struct sk_buff * skb;
unsigned int tot_len;
- if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+ if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
__FUNCTION__, lp->ppp_slot);
return;
@@ -2831,7 +2831,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
if(!skb || skb->len < 3)
return;
- if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+ if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
__FUNCTION__, slot);
return;
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index 6147e580a15364..ae16112a06535b 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -385,6 +385,30 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
+static int cx24110_diseqc_send_burst(struct dvb_frontend* fe,
+ fe_sec_mini_cmd_t burst)
+{
+ int rv, bit, i;
+ struct cx24110_state *state = fe->demodulator_priv;
+
+ if (burst == SEC_MINI_A)
+ bit = 0x00;
+ else if (burst == SEC_MINI_B)
+ bit = 0x08;
+ else
+ return -EINVAL;
+
+ rv = cx24110_readreg(state, 0x77);
+ cx24110_writereg(state, 0x77, rv|0x04);
+
+ rv = cx24110_readreg(state, 0x76);
+ cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
+ for (i = 500; i-- > 0 && !(cx24110_readreg(state,0x76)&0x40) ; )
+ ; /* wait for LNB ready */
+
+ return 0;
+}
+
static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *cmd)
{
@@ -394,6 +418,9 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
for (i = 0; i < cmd->msg_len; i++)
cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
+ rv = cx24110_readreg(state, 0x77);
+ cx24110_writereg(state, 0x77, rv|0x04);
+
rv = cx24110_readreg(state, 0x76);
cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
@@ -616,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = {
.diseqc_send_master_cmd = cx24110_send_diseqc_msg,
.set_tone = cx24110_set_tone,
.set_voltage = cx24110_set_voltage,
+ .diseqc_send_burst = cx24110_diseqc_send_burst,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
index 1e1bec697a5607..13b1e7b6fd6eb6 100644
--- a/drivers/media/video/zr36050.c
+++ b/drivers/media/video/zr36050.c
@@ -419,7 +419,7 @@ zr36050_set_dri (struct zr36050 *ptr)
dri_data[2] = 0x00;
dri_data[3] = 0x04;
dri_data[4] = ptr->dri >> 8;
- dri_data[5] = ptr->dri * 0xff;
+ dri_data[5] = ptr->dri & 0xff;
return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 96a870866ace7a..770e28f98fd532 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -793,29 +793,20 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
* @skb: hw accel VLAN tagged skb to transmit
* @slave_dev: slave that is supposed to xmit this skbuff
*
- * When the bond gets an skb to tarnsmit that is
+ * When the bond gets an skb to transmit that is
* already hardware accelerated VLAN tagged, and it
* needs to relay this skb to a slave that is not
* hw accel capable, the skb needs to be "unaccelerated",
* i.e. strip the hwaccel tag and re-insert it as part
* of the payload.
- *
- * Assumption - once a VLAN device is created over the bond device, all
- * packets are going to be hardware accelerated VLAN tagged since the IP
- * binding is done over the VLAN device
*/
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev)
{
unsigned short vlan_id;
- int res;
if (!list_empty(&bond->vlan_list) &&
- !(slave_dev->features & NETIF_F_HW_VLAN_TX)) {
- res = vlan_get_tag(skb, &vlan_id);
- if (res) {
- return -EINVAL;
- }
-
+ !(slave_dev->features & NETIF_F_HW_VLAN_TX) &&
+ vlan_get_tag(skb, &vlan_id) == 0) {
skb->dev = slave_dev;
skb = vlan_put_tag(skb, vlan_id);
if (!skb) {
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index d597a051bc7dfc..ce1a9bf7b9a76e 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -480,6 +480,12 @@ static struct packet_type pppoed_ptype = {
.func = pppoe_disc_rcv,
};
+static struct proto pppoe_sk_proto = {
+ .name = "PPPOE",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct pppox_sock),
+};
+
/***********************************************************************
*
* Initialize a new struct sock.
@@ -490,12 +496,12 @@ static int pppoe_create(struct socket *sock)
int error = -ENOMEM;
struct sock *sk;
- sk = sk_alloc(PF_PPPOX, GFP_KERNEL, sizeof(struct pppox_sock), NULL);
+ sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1);
if (!sk)
goto out;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
+
sock->state = SS_UNCONNECTED;
sock->ops = &pppoe_ops;
@@ -1103,22 +1109,29 @@ static struct pppox_proto pppoe_proto = {
static int __init pppoe_init(void)
{
- int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
+ int err = proto_register(&pppoe_sk_proto, 0);
if (err)
goto out;
+ err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto);
+ if (err)
+ goto out_unregister_pppoe_proto;
+
err = pppoe_proc_init();
- if (err) {
- unregister_pppox_proto(PX_PROTO_OE);
- goto out;
- }
+ if (err)
+ goto out_unregister_pppox_proto;
dev_add_pack(&pppoes_ptype);
dev_add_pack(&pppoed_ptype);
register_netdevice_notifier(&pppoe_notifier);
out:
return err;
+out_unregister_pppox_proto:
+ unregister_pppox_proto(PX_PROTO_OE);
+out_unregister_pppoe_proto:
+ proto_unregister(&pppoe_sk_proto);
+ goto out;
}
static void __exit pppoe_exit(void)
@@ -1128,6 +1141,7 @@ static void __exit pppoe_exit(void)
dev_remove_pack(&pppoed_ptype);
unregister_netdevice_notifier(&pppoe_notifier);
remove_proc_entry("pppoe", proc_net);
+ proto_unregister(&pppoe_sk_proto);
}
module_init(pppoe_init);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 2951b9084bfd2b..c5774e7855d036 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2976,10 +2976,12 @@ static void __devexit parport_pc_pci_remove(struct pci_dev *dev)
pci_set_drvdata(dev, NULL);
- for (i = data->num - 1; i >= 0; i--)
- parport_pc_unregister_port(data->ports[i]);
+ if (data) {
+ for (i = data->num - 1; i >= 0; i--)
+ parport_pc_unregister_port(data->ports[i]);
- kfree(data);
+ kfree(data);
+ }
}
static struct pci_driver parport_pc_pci_driver = {
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 3f70e4926cb613..5425e0f77d8608 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -67,7 +67,7 @@ static void msi_set_mask_bit(unsigned int vector, int flag)
int pos;
u32 mask_bits;
- pos = (int)entry->mask_base;
+ pos = (long)entry->mask_base;
pci_read_config_dword(entry->dev, pos, &mask_bits);
mask_bits &= ~(1);
mask_bits |= flag;
@@ -555,7 +555,7 @@ static int msi_capability_init(struct pci_dev *dev)
dev->irq = vector;
entry->dev = dev;
if (is_mask_bit_support(control)) {
- entry->mask_base = (void __iomem *)msi_mask_bits_reg(pos,
+ entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control));
}
/* Replace with MSI handler */
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index df102f9301e71e..c0ddb1eb8c4d68 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -219,9 +219,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
res->data.address64.min_address_range,
res->data.address64.address_length);
break;
+ case ACPI_RSTYPE_VENDOR:
+ break;
default:
- pnp_warn("PnPACPI: Alloc type : %d not handle",
- res->id);
+ pnp_warn("PnPACPI: unknown resource type %d", res->id);
return AE_ERROR;
}
@@ -508,7 +509,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
case ACPI_RSTYPE_END_DPF:
return AE_CTRL_TERMINATE;
default:
- pnp_warn("PnPACPI:Option type: %d not handle", res->id);
+ pnp_warn("PnPACPI: unknown resource type %d", res->id);
return AE_ERROR;
}
@@ -810,7 +811,7 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
mem ++;
break;
default: /* other type */
- pnp_warn("Invalid type");
+ pnp_warn("unknown resource type %d", resource->id);
return -EINVAL;
}
resource ++;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index fbfe5d35de3300..cdf110fd635181 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -615,7 +615,7 @@ config SERIAL_68360
config SERIAL_PMACZILOG
tristate "PowerMac z85c30 ESCC support"
- depends on PPC_OF
+ depends on PPC_OF && PPC_PMAC
select SERIAL_CORE
help
This driver supports the Zilog z85C30 serial ports found on
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 47945745291d2f..2a5cf174ca30d9 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -18,7 +18,7 @@
* Some of the code has been inspired/copied from the 2.4 code written
* by Dale Farnsworth <dfarnsworth@mvista.com>.
*
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
@@ -26,33 +26,26 @@
* kind, whether express or implied.
*/
-/* OCP Usage :
+/* Platform device Usage :
*
- * This drivers uses the OCP model. To load the serial driver for one of the
- * PSCs, just add this to the core_ocp table :
+ * Since PSCs can have multiple function, the correct driver for each one
+ * is selected by calling mpc52xx_match_psc_function(...). The function
+ * handled by this driver is "uart".
*
- * {
- * .vendor = OCP_VENDOR_FREESCALE,
- * .function = OCP_FUNC_PSC_UART,
- * .index = 0,
- * .paddr = MPC52xx_PSC1,
- * .irq = MPC52xx_PSC1_IRQ,
- * .pm = OCP_CPM_NA,
- * },
- *
- * This is for PSC1, replace the paddr and irq according to the PSC you want to
- * use. The driver all necessary registers to place the PSC in uart mode without
+ * The driver init all necessary registers to place the PSC in uart mode without
* DCD. However, the pin multiplexing aren't changed and should be set either
* by the bootloader or in the platform init code.
- * The index field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
+ *
+ * The idx field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2,
* and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so
* on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for
* the console code : without this 1:1 mapping, at early boot time, when we are
* parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be
- * mapped to because OCP stuff is not yet initialized.
+ * mapped to.
*/
#include <linux/config.h>
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/serial.h>
@@ -61,7 +54,6 @@
#include <asm/delay.h>
#include <asm/io.h>
-#include <asm/ocp.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
@@ -191,6 +183,13 @@ static int
mpc52xx_uart_startup(struct uart_port *port)
{
struct mpc52xx_psc __iomem *psc = PSC(port);
+ int ret;
+
+ /* Request IRQ */
+ ret = request_irq(port->irq, mpc52xx_uart_int,
+ SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
+ if (ret)
+ return ret;
/* Reset/activate the port, clear and enable interrupts */
out_8(&psc->command,MPC52xx_PSC_RST_RX);
@@ -225,6 +224,9 @@ mpc52xx_uart_shutdown(struct uart_port *port)
port->read_status_mask = 0;
out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
+
+ /* Release interrupt */
+ free_irq(port->irq, port);
}
static void
@@ -326,15 +328,21 @@ mpc52xx_uart_release_port(struct uart_port *port)
iounmap(port->membase);
port->membase = NULL;
}
+
+ release_mem_region(port->mapbase, MPC52xx_PSC_SIZE);
}
static int
mpc52xx_uart_request_port(struct uart_port *port)
{
if (port->flags & UPF_IOREMAP) /* Need to remap ? */
- port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
-
- return port->membase != NULL ? 0 : -EBUSY;
+ port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
+
+ if (!port->membase)
+ return -EINVAL;
+
+ return request_mem_region(port->mapbase, MPC52xx_PSC_SIZE,
+ "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
}
static void
@@ -354,7 +362,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
if ( (ser->irq != port->irq) ||
(ser->io_type != SERIAL_IO_MEM) ||
(ser->baud_base != port->uartclk) ||
- // FIXME Should check addresses/irq as well ?
+ (ser->iomem_base != (void*)port->mapbase) ||
(ser->hub6 != 0 ) )
return -EINVAL;
@@ -630,7 +638,7 @@ mpc52xx_console_setup(struct console *co, char *options)
{
struct uart_port *port = &mpc52xx_uart_ports[co->index];
- int baud = 9600;
+ int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
int bits = 8;
int parity = 'n';
int flow = 'n';
@@ -643,14 +651,12 @@ mpc52xx_console_setup(struct console *co, char *options)
spin_lock_init(&port->lock);
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
port->ops = &mpc52xx_uart_ops;
- port->mapbase = MPC52xx_PSCx(co->index);
+ port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
- /* We ioremap ourself */
- port->membase = ioremap(port->mapbase, sizeof(struct mpc52xx_psc));
- if (port->membase == NULL) {
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
- return -EBUSY;
- }
+ /* We ioremap ourself */
+ port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
+ if (port->membase == NULL)
+ return -EINVAL;
/* Setup the port parameters accoding to options */
if (options)
@@ -707,26 +713,32 @@ static struct uart_driver mpc52xx_uart_driver = {
/* ======================================================================== */
-/* OCP Driver */
+/* Platform Driver */
/* ======================================================================== */
static int __devinit
-mpc52xx_uart_probe(struct ocp_device *ocp)
+mpc52xx_uart_probe(struct device *dev)
{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res = pdev->resource;
+
struct uart_port *port = NULL;
- int idx, ret;
+ int i, idx, ret;
- /* Get the corresponding port struct */
- idx = ocp->def->index;
+ /* Check validity & presence */
+ idx = pdev->id;
if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
return -EINVAL;
-
- port = &mpc52xx_uart_ports[idx];
+
+ if (!mpc52xx_match_psc_function(idx,"uart"))
+ return -ENODEV;
/* Init the port structure */
+ port = &mpc52xx_uart_ports[idx];
+
+ memset(port, 0x00, sizeof(struct uart_port));
+
spin_lock_init(&port->lock);
- port->mapbase = ocp->def->paddr;
- port->irq = ocp->def->irq;
port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
port->fifosize = 255; /* Should be 512 ! But it can't be */
/* stored in a unsigned char */
@@ -735,95 +747,65 @@ mpc52xx_uart_probe(struct ocp_device *ocp)
( uart_console(port) ? 0 : UPF_IOREMAP );
port->line = idx;
port->ops = &mpc52xx_uart_ops;
- port->read_status_mask = 0;
-
- /* Requests the mem & irqs */
- /* Unlike other serial drivers, we reserve the resources here, so we
- * can detect early if multiple drivers uses the same PSC. Special
- * care must be taken with the console PSC
- */
- ret = request_irq(
- port->irq, mpc52xx_uart_int,
- SA_INTERRUPT | SA_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
- if (ret)
- goto error;
- ret = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
- "mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
- if (ret)
- goto free_irq;
+ /* Search for IRQ and mapbase */
+ for (i=0 ; i<pdev->num_resources ; i++, res++) {
+ if (res->flags & IORESOURCE_MEM)
+ port->mapbase = res->start;
+ else if (res->flags & IORESOURCE_IRQ)
+ port->irq = res->start;
+ }
+ if (!port->irq || !port->mapbase)
+ return -EINVAL;
/* Add the port to the uart sub-system */
ret = uart_add_one_port(&mpc52xx_uart_driver, port);
- if (ret)
- goto release_mem;
-
- ocp_set_drvdata(ocp, (void*)port);
-
- return 0;
-
-
-free_irq:
- free_irq(port->irq, mpc52xx_uart_int);
-
-release_mem:
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
-
-error:
- if (uart_console(port))
- printk( "mpc52xx_uart.c: Error during resource alloction for "
- "the console port !!! Check that the console PSC is "
- "not used by another OCP driver !!!\n" );
+ if (!ret)
+ dev_set_drvdata(dev, (void*)port);
return ret;
}
-static void
-mpc52xx_uart_remove(struct ocp_device *ocp)
+static int
+mpc52xx_uart_remove(struct device *dev)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- ocp_set_drvdata(ocp, NULL);
+ dev_set_drvdata(dev, NULL);
- if (port) {
+ if (port)
uart_remove_one_port(&mpc52xx_uart_driver, port);
- release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
- free_irq(port->irq, mpc52xx_uart_int);
- }
+
+ return 0;
}
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct ocp_device *ocp, u32 state)
+mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- uart_suspend_port(&mpc52xx_uart_driver, port);
+ if (sport && level == SUSPEND_DISABLE)
+ uart_suspend_port(&mpc52xx_uart_driver, port);
return 0;
}
static int
-mpc52xx_uart_resume(struct ocp_device *ocp)
+mpc52xx_uart_resume(struct device *dev, u32 level)
{
- struct uart_port *port = (struct uart_port *) ocp_get_drvdata(ocp);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
- uart_resume_port(&mpc52xx_uart_driver, port);
+ if (port && level == RESUME_ENABLE)
+ uart_resume_port(&mpc52xx_uart_driver, port);
return 0;
}
#endif
-static struct ocp_device_id mpc52xx_uart_ids[] __devinitdata = {
- { .vendor = OCP_VENDOR_FREESCALE, .function = OCP_FUNC_PSC_UART },
- { .vendor = OCP_VENDOR_INVALID /* Terminating entry */ }
-};
-
-MODULE_DEVICE_TABLE(ocp, mpc52xx_uart_ids);
-
-static struct ocp_driver mpc52xx_uart_ocp_driver = {
- .name = "mpc52xx_psc_uart",
- .id_table = mpc52xx_uart_ids,
+static struct device_driver mpc52xx_uart_platform_driver = {
+ .name = "mpc52xx-psc",
+ .bus = &platform_bus_type,
.probe = mpc52xx_uart_probe,
.remove = mpc52xx_uart_remove,
#ifdef CONFIG_PM
@@ -845,10 +827,11 @@ mpc52xx_uart_init(void)
printk(KERN_INFO "Serial: MPC52xx PSC driver\n");
ret = uart_register_driver(&mpc52xx_uart_driver);
- if (ret)
- return ret;
-
- ret = ocp_register_driver(&mpc52xx_uart_ocp_driver);
+ if (ret == 0) {
+ ret = driver_register(&mpc52xx_uart_platform_driver);
+ if (ret)
+ uart_unregister_driver(&mpc52xx_uart_driver);
+ }
return ret;
}
@@ -856,7 +839,7 @@ mpc52xx_uart_init(void)
static void __exit
mpc52xx_uart_exit(void)
{
- ocp_unregister_driver(&mpc52xx_uart_ocp_driver);
+ driver_unregister(&mpc52xx_uart_platform_driver);
uart_unregister_driver(&mpc52xx_uart_driver);
}
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f6821e39e2bda5..2a1c5965de2229 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -74,6 +74,11 @@ config FB_SOFT_CURSOR
This is used by drivers that don't provide their own (accelerated)
version.
+config FB_MACMODES
+ tristate
+ depends on FB
+ default n
+
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
depends on FB
@@ -323,6 +328,7 @@ config FB_OF
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
Say Y if you want support with Open Firmware for your graphics
board.
@@ -334,6 +340,7 @@ config FB_CONTROL
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the graphics adapter in the
Power Macintosh 7300 and others.
@@ -345,6 +352,7 @@ config FB_PLATINUM
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the "platinum" graphics
adapter in some Power Macintoshes.
@@ -356,6 +364,7 @@ config FB_VALKYRIE
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
help
This driver supports a frame buffer for the "valkyrie" graphics
adapter in some Power Macintoshes.
@@ -384,6 +393,7 @@ config FB_IMSTT
depends on (FB = y) && PCI
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
The IMS Twin Turbo is a PCI-based frame buffer card bundled with
many Macintosh and compatible computers.
@@ -436,6 +446,7 @@ config FB_MAC
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES
# bool ' Apple DAFB display support' CONFIG_FB_DAFB
config FB_HP300
@@ -619,12 +630,11 @@ config FB_NVIDIA
help
This driver supports graphics boards with the nVidia chips, TNT
and newer. For very old chipsets, such as the RIVA128, then use
- the the rivafb.
+ the rivafb.
Say Y if you have such a graphics board.
To compile this driver as a module, choose M here: the
module will be called nvidiafb.
- none yet
config FB_NVIDIA_I2C
bool "Enable DDC Support"
@@ -754,6 +764,7 @@ config FB_MATROX
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
select FB_TILEBLITTING
+ select FB_MACMODES if PPC_PMAC
---help---
Say Y here if you have a Matrox Millennium, Matrox Millennium II,
Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
@@ -893,6 +904,7 @@ config FB_RADEON_OLD
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
Choose this option if you want to use an ATI Radeon graphics card as
a framebuffer device. There are both PCI and AGP versions. You
@@ -910,6 +922,7 @@ config FB_RADEON
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC_OF
help
Choose this option if you want to use an ATI Radeon graphics card as
a framebuffer device. There are both PCI and AGP versions. You
@@ -948,6 +961,7 @@ config FB_ATY128
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC_PMAC
help
This driver supports graphics boards with the ATI Rage128 chips.
Say Y if you have such a graphics board and read
@@ -963,6 +977,7 @@ config FB_ATY
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_SOFT_CURSOR
+ select FB_MACMODES if PPC
help
This driver supports graphics boards with the ATI Mach64 chips.
Say Y if you have such a graphics board.
@@ -1433,6 +1448,18 @@ config FB_PXA_PARAMETERS
<file:Documentation/fb/pxafb.txt> describes the available parameters.
+config FB_S1D13XXX
+ tristate "Epson S1D13XXX framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ help
+ Support for S1D13XXX framebuffer device family (currently only
+ working with S1D13806). Product specs at
+ <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
+
config FB_VIRTUAL
tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
depends on FB
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bf04cfb000bda5..92265b741dc3a4 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
obj-$(CONFIG_FB_SOFT_CURSOR) += softcursor.o
+obj-$(CONFIG_FB_MACMODES) += macmodes.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
@@ -29,8 +30,8 @@ obj-$(CONFIG_FB_PM3) += pm3fb.o
obj-$(CONFIG_FB_MATROX) += matrox/
obj-$(CONFIG_FB_RIVA) += riva/ vgastate.o
obj-$(CONFIG_FB_NVIDIA) += nvidia/
-obj-$(CONFIG_FB_ATY) += aty/
-obj-$(CONFIG_FB_ATY128) += aty/
+obj-$(CONFIG_FB_ATY) += aty/ macmodes.o
+obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o
obj-$(CONFIG_FB_RADEON) += aty/
obj-$(CONFIG_FB_SIS) += sis/
obj-$(CONFIG_FB_KYRO) += kyro/
@@ -41,9 +42,9 @@ obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o vgastate.o
obj-$(CONFIG_FB_VIRGE) += virgefb.o
obj-$(CONFIG_FB_3DFX) += tdfxfb.o
-obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o
-obj-$(CONFIG_FB_PLATINUM) += platinumfb.o macmodes.o
-obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o macmodes.o
+obj-$(CONFIG_FB_CONTROL) += controlfb.o
+obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
+obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
obj-$(CONFIG_FB_CT65550) += chipsfb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
@@ -61,7 +62,7 @@ obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o
obj-$(CONFIG_FB_SGIVW) += sgivwfb.o
obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_ATARI) += atafb.o
-obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o
+obj-$(CONFIG_FB_MAC) += macfb.o
obj-$(CONFIG_FB_HGA) += hgafb.o
obj-$(CONFIG_FB_IGA) += igafb.o
obj-$(CONFIG_FB_APOLLO) += dnfb.o
@@ -88,6 +89,7 @@ obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o
+obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_VESA) += vesafb.o
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index ed87832d789c4f..f4729f4df8cec0 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -604,7 +604,7 @@ static int __init asiliantfb_init(void)
if (fb_get_options("asiliantfb", NULL))
return -ENODEV;
- return pci_module_init(&asiliantfb_driver);
+ return pci_register_driver(&asiliantfb_driver);
}
module_init(asiliantfb_init);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 7b090b23bfffd1..8a4ba3bb987284 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -2461,7 +2461,7 @@ static int __init aty128fb_init(void)
aty128fb_setup(option);
#endif
- return pci_module_init(&aty128fb_driver);
+ return pci_register_driver(&aty128fb_driver);
}
static void __exit aty128fb_exit(void)
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 4d37dffe3bf640..8c42538dc8c12d 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -100,8 +100,8 @@
/*
* Debug flags.
*/
-/*#undef DEBUG*/
-#define DEBUG
+#undef DEBUG
+/*#define DEBUG*/
/* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
/* - must be large enough to catch all GUI-Regs */
@@ -307,6 +307,7 @@ static int vram;
static int pll;
static int mclk;
static int xclk;
+static int comp_sync __initdata = -1;
static char *mode;
#ifdef CONFIG_PPC
@@ -2527,6 +2528,13 @@ static int __init aty_init(struct fb_info *info, const char *name)
else
var.accel_flags |= FB_ACCELF_TEXT;
+ if (comp_sync != -1) {
+ if (!comp_sync)
+ var.sync &= ~FB_SYNC_COMP_HIGH_ACT;
+ else
+ var.sync |= FB_SYNC_COMP_HIGH_ACT;
+ }
+
if (var.yres == var.yres_virtual) {
u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));
var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;
@@ -3427,8 +3435,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
err_release_io:
#ifdef __sparc__
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
#else
if (par->ati_regbase)
iounmap(par->ati_regbase);
@@ -3436,7 +3443,7 @@ err_release_io:
iounmap(info->screen_base);
#endif
err_release_mem:
- if(par->aux_start)
+ if (par->aux_start)
release_mem_region(par->aux_start, par->aux_size);
release_mem_region(par->res_start, par->res_size);
@@ -3543,8 +3550,7 @@ static void __devexit atyfb_remove(struct fb_info *info)
#endif
#endif
#ifdef __sparc__
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
#endif
if (par->aux_start)
release_mem_region(par->aux_start, par->aux_size);
@@ -3612,6 +3618,8 @@ static int __init atyfb_setup(char *options)
mclk = simple_strtoul(this_opt + 5, NULL, 0);
else if (!strncmp(this_opt, "xclk:", 5))
xclk = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "comp_sync:", 10))
+ comp_sync = simple_strtoul(this_opt+10, NULL, 0);
#ifdef CONFIG_PPC
else if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode =
@@ -3671,7 +3679,7 @@ static int __init atyfb_init(void)
#endif
#ifdef CONFIG_PCI
- pci_module_init(&atyfb_driver);
+ pci_register_driver(&atyfb_driver);
#endif
#ifdef CONFIG_ATARI
atyfb_atari_probe();
@@ -3701,6 +3709,9 @@ module_param(mclk, int, 0);
MODULE_PARM_DESC(mclk, "int: override memory clock");
module_param(xclk, int, 0);
MODULE_PARM_DESC(xclk, "int: override accelerated engine clock");
+module_param(comp_sync, int, 0);
+MODULE_PARM_DESC(comp_sync,
+ "Set composite sync signal to low (0) or high (1)");
module_param(mode, charp, 0);
MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c
index dc8598dacbcb2d..3ca27cb13caa0d 100644
--- a/drivers/video/aty/radeon_accel.c
+++ b/drivers/video/aty/radeon_accel.c
@@ -189,32 +189,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
radeon_engine_flush (rinfo);
- /* Some ASICs have bugs with dynamic-on feature, which are
- * ASIC-version dependent, so we force all blocks on for now
- * -- from XFree86
- * We don't do that on macs, things just work here with dynamic
- * clocking... --BenH
- */
-#ifdef CONFIG_ALL_PPC
- if (_machine != _MACH_Pmac && rinfo->hasCRTC2)
-#else
- if (rinfo->has_CRTC2)
-#endif
- {
- u32 tmp;
-
- tmp = INPLL(SCLK_CNTL);
- OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) |
- CP_MAX_DYN_STOP_LAT |
- SCLK_FORCEON_MASK));
-
- if (rinfo->family == CHIP_FAMILY_RV200)
- {
- tmp = INPLL(SCLK_MORE_CNTL);
- OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON);
- }
- }
-
clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
mclk_cntl = INPLL(MCLK_CNTL);
@@ -274,8 +248,6 @@ void radeonfb_engine_reset(struct radeonfb_info *rinfo)
OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
OUTPLL(MCLK_CNTL, mclk_cntl);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
}
void radeonfb_engine_init (struct radeonfb_info *rinfo)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 7d1688a8900ec2..e8eb124754b136 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -1,4 +1,3 @@
-
/*
* drivers/video/aty/radeon_base.c
*
@@ -530,11 +529,8 @@ static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo)
break;
}
- radeon_pll_workaround_before(rinfo);
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
m = (INPLL(PPLL_REF_DIV) & 0x3ff);
@@ -1173,11 +1169,8 @@ static void radeon_save_state (struct radeonfb_info *rinfo,
save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
/* PLL regs */
- radeon_pll_workaround_before(rinfo);
save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
save->ppll_div_3 = INPLL(PPLL_DIV_3);
save->ppll_ref_div = INPLL(PPLL_REF_DIV);
}
@@ -1204,13 +1197,11 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
/* We still have to force a switch to selected PPLL div thanks to
* an XFree86 driver bug which will switch it away in some cases
* even when using UseFDev */
- radeon_pll_workaround_before(rinfo);
OUTREGP(CLOCK_CNTL_INDEX,
mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
~PPLL_DIV_SEL_MASK);
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
return;
}
}
@@ -1224,13 +1215,11 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
/* Switch to selected PPLL divider */
- radeon_pll_workaround_before(rinfo);
OUTREGP(CLOCK_CNTL_INDEX,
mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
~PPLL_DIV_SEL_MASK);
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Set PPLL ref. div */
if (rinfo->family == CHIP_FAMILY_R300 ||
@@ -1754,8 +1743,7 @@ static int radeonfb_set_par(struct fb_info *info)
} else {
/* DFP */
newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
- newmode->tmds_transmitter_cntl = (TMDS_RAN_PAT_RST | TMDS_ICHCSEL) &
- ~(TMDS_PLLRST);
+ newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST);
/* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */
if (IS_R300_VARIANT(rinfo) ||
(rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2)
@@ -2248,7 +2236,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;
rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;
rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;
-
+
/* Set base addrs */
rinfo->fb_base_phys = pci_resource_start (pdev, 0);
rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
@@ -2271,6 +2259,24 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+ /*
+ * Check for errata
+ */
+ rinfo->errata = 0;
+ if (rinfo->family == CHIP_FAMILY_R300 &&
+ (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
+ == CFG_ATI_REV_A11)
+ rinfo->errata |= CHIP_ERRATA_R300_CG;
+
+ if (rinfo->family == CHIP_FAMILY_RV200 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS;
+
+ if (rinfo->family == CHIP_FAMILY_RV100 ||
+ rinfo->family == CHIP_FAMILY_RS100 ||
+ rinfo->family == CHIP_FAMILY_RS200)
+ rinfo->errata |= CHIP_ERRATA_PLL_DELAY;
+
#ifdef CONFIG_PPC_OF
/* On PPC, we obtain the OF device-node pointer to the firmware
* data for this chip
@@ -2310,13 +2316,6 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
rinfo->mapped_vram/1024);
/*
- * Check for required workaround for PLL accesses
- */
- rinfo->R300_cg_workaround = (rinfo->family == CHIP_FAMILY_R300 &&
- (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK)
- == CFG_ATI_REV_A11);
-
- /*
* Map the BIOS ROM if any and retreive PLL parameters from
* the BIOS. We skip that on mobility chips as the real panel
* values we need aren't in the ROM but in the BIOS image in
@@ -2420,10 +2419,8 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
err_unmap_fb:
iounmap(rinfo->fb_base);
err_unmap_rom:
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon2_EDID);
if (rinfo->mon1_modedb)
fb_destroy_modedb(rinfo->mon1_modedb);
fb_dealloc_cmap(&info->cmap);
@@ -2479,10 +2476,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
pci_release_regions(pdev);
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon2_EDID);
if (rinfo->mon1_modedb)
fb_destroy_modedb(rinfo->mon1_modedb);
#ifdef CONFIG_FB_RADEON_I2C
@@ -2551,7 +2546,7 @@ static int __init radeonfb_init (void)
return -ENODEV;
radeonfb_setup(option);
#endif
- return pci_module_init (&radeonfb_driver);
+ return pci_register_driver (&radeonfb_driver);
}
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c
index e87ef153d87bb4..762244164c81a9 100644
--- a/drivers/video/aty/radeon_i2c.c
+++ b/drivers/video/aty/radeon_i2c.c
@@ -236,6 +236,12 @@ int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_e
if (edid)
break;
}
+ /* Release the DDC lines when done or the Apple Cinema HD display
+ * will switch off
+ */
+ OUTREG(reg, INREG(reg) & ~(VGA_DDC_CLK_OUT_EN | VGA_DDC_DATA_OUT_EN));
+ (void)INREG(reg);
+
if (out_edid)
*out_edid = edid;
if (!edid) {
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 2918d5ec36c891..ea7c8630691845 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -618,11 +618,9 @@ void __devinit radeon_probe_screens(struct radeonfb_info *rinfo,
}
}
if (ignore_edid) {
- if (rinfo->mon1_EDID)
- kfree(rinfo->mon1_EDID);
+ kfree(rinfo->mon1_EDID);
rinfo->mon1_EDID = NULL;
- if (rinfo->mon2_EDID)
- kfree(rinfo->mon2_EDID);
+ kfree(rinfo->mon2_EDID);
rinfo->mon2_EDID = NULL;
}
@@ -657,11 +655,8 @@ static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
&& rinfo->is_mobility) {
int ppll_div_sel;
u32 ppll_divn;
- radeon_pll_workaround_before(rinfo);
ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff;
@@ -906,7 +901,7 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
*/
/*
- * This is used when looking for modes. We assign a "goodness" value
+ * This is used when looking for modes. We assign a "distance" value
* to a mode in the modedb depending how "close" it is from what we
* are looking for.
* Currently, we don't compare that much, we could do better but
@@ -915,13 +910,11 @@ void __devinit radeon_check_modes(struct radeonfb_info *rinfo, const char *mode_
static int radeon_compare_modes(const struct fb_var_screeninfo *var,
const struct fb_videomode *mode)
{
- int goodness = 0;
+ int distance = 0;
- if (var->yres == mode->yres)
- goodness += 10;
- if (var->xres == mode->xres)
- goodness += 9;
- return goodness;
+ distance = mode->yres - var->yres;
+ distance += (mode->xres - var->xres)/2;
+ return distance;
}
/*
@@ -943,7 +936,7 @@ int radeon_match_mode(struct radeonfb_info *rinfo,
const struct fb_videomode *db = vesa_modes;
int i, dbsize = 34;
int has_rmx, native_db = 0;
- int goodness = 0;
+ int distance = INT_MAX;
const struct fb_videomode *candidate = NULL;
/* Start with a copy of the requested mode */
@@ -979,19 +972,19 @@ int radeon_match_mode(struct radeonfb_info *rinfo,
/* Now look for a mode in the database */
while (db) {
for (i = 0; i < dbsize; i++) {
- int g;
+ int d;
if (db[i].yres < src->yres)
continue;
if (db[i].xres < src->xres)
continue;
- g = radeon_compare_modes(src, &db[i]);
+ d = radeon_compare_modes(src, &db[i]);
/* If the new mode is at least as good as the previous one,
* then it's our new candidate
*/
- if (g >= goodness) {
+ if (d < distance) {
candidate = &db[i];
- goodness = g;
+ distance = d;
}
}
db = NULL;
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index 365c049877b23c..23c677e5093fdd 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -1372,12 +1372,10 @@ static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
/* Reconfigure SPLL charge pump, VCO gain, duty cycle */
tmp = INPLL(pllSPLL_CNTL);
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Set SPLL feedback divider */
tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1409,12 +1407,10 @@ static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo)
/* Reconfigure MPLL charge pump, VCO gain, duty cycle */
tmp = INPLL(pllMPLL_CNTL);
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Set MPLL feedback divider */
tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1532,12 +1528,10 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
{
u32 tmp;
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA, 0);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(pllVCLK_ECP_CNTL);
OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80);
@@ -1552,12 +1546,10 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
* probably useless since we already did it ...
*/
tmp = INPLL(pllPPLL_CNTL);
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
/* Restore our "reference" PPLL divider set by firmware
* according to proper spread spectrum calculations
@@ -1581,11 +1573,9 @@ static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo)
mdelay(5);
/* Switch pixel clock to firmware default div 0 */
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX+1, 0);
- radeon_pll_workaround_after(rinfo);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
}
static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo)
@@ -2173,7 +2163,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
tmp = INPLL(MPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, MPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(M_SPLL_REF_FB_DIV);
OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x5900);
@@ -2194,7 +2186,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
tmp = INPLL(SPLL_CNTL);
OUTREG8(CLOCK_CNTL_INDEX, SPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+ radeon_pll_errata_after_data(rinfo);
tmp = INPLL(M_SPLL_REF_FB_DIV);
OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x780000);
@@ -2322,7 +2316,9 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
OUTREG(CRTC_H_SYNC_STRT_WID, 0x008e0580);
OUTREG(CRTC_H_TOTAL_DISP, 0x009f00d2);
OUTREG8(CLOCK_CNTL_INDEX, HTOTAL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA, 0);
+ radeon_pll_errata_after_data(rinfo);
OUTREG(CRTC_V_SYNC_STRT_WID, 0x00830403);
OUTREG(CRTC_V_TOTAL_DISP, 0x03ff0429);
OUTREG(FP_CRTC_H_TOTAL_DISP, 0x009f0033);
@@ -2344,10 +2340,15 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo)
INPLL(PPLL_REF_DIV);
OUTREG8(CLOCK_CNTL_INDEX, PPLL_CNTL + PLL_WR_EN);
+ radeon_pll_errata_after_index(rinfo);
OUTREG8(CLOCK_CNTL_DATA + 1, 0xbc);
+ radeon_pll_errata_after_data(rinfo);
tmp = INREG(CLOCK_CNTL_INDEX);
+ radeon_pll_errata_after_index(rinfo);
OUTREG(CLOCK_CNTL_INDEX, tmp & 0xff);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
OUTPLL(PPLL_DIV_0, 0x48090);
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index a1e9d39f0e8545..659bc9f62244aa 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -77,6 +77,15 @@ enum radeon_chip_flags {
CHIP_HAS_CRTC2 = 0x00040000UL,
};
+/*
+ * Errata workarounds
+ */
+enum radeon_errata {
+ CHIP_ERRATA_R300_CG = 0x00000001,
+ CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002,
+ CHIP_ERRATA_PLL_DELAY = 0x00000004,
+};
+
/*
* Monitor types
@@ -295,6 +304,7 @@ struct radeonfb_info {
int chipset;
u8 family;
u8 rev;
+ unsigned int errata;
unsigned long video_ram;
unsigned long mapped_vram;
int vram_width;
@@ -305,7 +315,6 @@ struct radeonfb_info {
int has_CRTC2;
int is_mobility;
int is_IGP;
- int R300_cg_workaround;
int reversed_DAC;
int reversed_TMDS;
struct panel_info panel_info;
@@ -369,6 +378,21 @@ struct radeonfb_info {
* IO macros
*/
+/* Note about this function: we have some rare cases where we must not schedule,
+ * this typically happen with our special "wake up early" hook which allows us to
+ * wake up the graphic chip (and thus get the console back) before everything else
+ * on some machines that support that mecanism. At this point, interrupts are off
+ * and scheduling is not permitted
+ */
+static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
+{
+ if (rinfo->no_schedule || oops_in_progress)
+ mdelay(ms);
+ else
+ msleep(ms);
+}
+
+
#define INREG8(addr) readb((rinfo->mmio_base)+addr)
#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
#define INREG(addr) readl((rinfo->mmio_base)+addr)
@@ -390,107 +414,85 @@ static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
#define OUTREGP(addr,val,mask) _OUTREGP(rinfo, addr, val,mask)
-/* This function is required to workaround a hardware bug in some (all?)
- * revisions of the R300. This workaround should be called after every
- * CLOCK_CNTL_INDEX register access. If not, register reads afterward
- * may not be correct.
- */
-static inline void R300_cg_workardound(struct radeonfb_info *rinfo)
-{
- u32 save, tmp;
- save = INREG(CLOCK_CNTL_INDEX);
- tmp = save & ~(0x3f | PLL_WR_EN);
- OUTREG(CLOCK_CNTL_INDEX, tmp);
- tmp = INREG(CLOCK_CNTL_DATA);
- OUTREG(CLOCK_CNTL_INDEX, save);
-}
-
/*
- * PLL accesses suffer from various HW issues on the different chip
- * families. Some R300's need the above workaround, rv200 & friends
- * need a couple of dummy reads after any write of CLOCK_CNTL_INDEX,
- * and some RS100/200 need a dummy read before writing to
- * CLOCK_CNTL_INDEX as well. Instead of testing every chip revision,
- * we just unconditionally do the workarounds at once since PLL
- * accesses are far from beeing performance critical. Except for R300
- * one which stays separate for now
+ * Note about PLL register accesses:
+ *
+ * I have removed the spinlock on them on purpose. The driver now
+ * expects that it will only manipulate the PLL registers in normal
+ * task environment, where radeon_msleep() will be called, protected
+ * by a semaphore (currently the console semaphore) so that no conflict
+ * will happen on the PLL register index.
+ *
+ * With the latest changes to the VT layer, this is guaranteed for all
+ * calls except the actual drawing/blits which aren't supposed to use
+ * the PLL registers anyway
+ *
+ * This is very important for the workarounds to work properly. The only
+ * possible exception to this rule is the call to unblank(), which may
+ * be done at irq time if an oops is in progress.
*/
-
-static inline void radeon_pll_workaround_before(struct radeonfb_info *rinfo)
+static inline void radeon_pll_errata_after_index(struct radeonfb_info *rinfo)
{
+ if (!(rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS))
+ return;
+
+ (void)INREG(CLOCK_CNTL_DATA);
(void)INREG(CRTC_GEN_CNTL);
}
-static inline void radeon_pll_workaround_after(struct radeonfb_info *rinfo)
+static inline void radeon_pll_errata_after_data(struct radeonfb_info *rinfo)
{
- (void)INREG(CLOCK_CNTL_DATA);
- (void)INREG(CRTC_GEN_CNTL);
+ if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) {
+ /* we can't deal with posted writes here ... */
+ _radeon_msleep(rinfo, 5);
+ }
+ if (rinfo->errata & CHIP_ERRATA_R300_CG) {
+ u32 save, tmp;
+ save = INREG(CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | PLL_WR_EN);
+ OUTREG(CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(CLOCK_CNTL_DATA);
+ OUTREG(CLOCK_CNTL_INDEX, save);
+ }
}
static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
{
u32 data;
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
data = INREG(CLOCK_CNTL_DATA);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
return data;
}
-static inline u32 _INPLL(struct radeonfb_info *rinfo, u32 addr)
-{
- unsigned long flags;
- u32 data;
-
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- data = __INPLL(rinfo, addr);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
- return data;
-}
-
-#define INPLL(addr) _INPLL(rinfo, addr)
-
-
static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
u32 val)
{
- radeon_pll_workaround_before(rinfo);
OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
- radeon_pll_workaround_after(rinfo);
+ radeon_pll_errata_after_index(rinfo);
OUTREG(CLOCK_CNTL_DATA, val);
- if (rinfo->R300_cg_workaround)
- R300_cg_workardound(rinfo);
+ radeon_pll_errata_after_data(rinfo);
}
-static inline void _OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
-{
- unsigned long flags;
- spin_lock_irqsave(&rinfo->reg_lock, flags);
- __OUTPLL(rinfo, index, val);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
-}
-static inline void _OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
- u32 val, u32 mask)
+static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask)
{
- unsigned long flags;
unsigned int tmp;
- spin_lock_irqsave(&rinfo->reg_lock, flags);
tmp = __INPLL(rinfo, index);
tmp &= (mask);
tmp |= (val);
__OUTPLL(rinfo, index, tmp);
- spin_unlock_irqrestore(&rinfo->reg_lock, flags);
}
-#define OUTPLL(index, val) _OUTPLL(rinfo, index, val)
-#define OUTPLLP(index, val, mask) _OUTPLLP(rinfo, index, val, mask)
+#define INPLL(addr) __INPLL(rinfo, addr)
+#define OUTPLL(index, val) __OUTPLL(rinfo, index, val)
+#define OUTPLLP(index, val, mask) __OUTPLLP(rinfo, index, val, mask)
#define BIOS_IN8(v) (readb(rinfo->bios_seg + (v)))
@@ -582,20 +584,6 @@ static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
printk(KERN_ERR "radeonfb: Idle Timeout !\n");
}
-/* Note about this function: we have some rare cases where we must not schedule,
- * this typically happen with our special "wake up early" hook which allows us to
- * wake up the graphic chip (and thus get the console back) before everything else
- * on some machines that support that mecanism. At this point, interrupts are off
- * and scheduling is not permitted
- */
-static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms)
-{
- if (rinfo->no_schedule)
- mdelay(ms);
- else
- msleep(ms);
-}
-
#define radeon_engine_idle() _radeon_engine_idle(rinfo)
#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index a51f4d2b69d8b7..ab98f225fe3ee5 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -465,7 +465,7 @@ int __init chips_init(void)
if (fb_get_options("chipsfb", NULL))
return -ENODEV;
- return pci_module_init(&chipsfb_driver);
+ return pci_register_driver(&chipsfb_driver);
}
module_init(chips_init);
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 0255c61df6207b..a3040429c27b7e 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -2623,7 +2623,7 @@ static int __init cirrusfb_init(void)
error |= zorro_module_init(&cirrusfb_zorro_driver);
#endif
#ifdef CONFIG_PCI
- error |= pci_module_init(&cirrusfb_pci_driver);
+ error |= pci_register_driver(&cirrusfb_pci_driver);
#endif
return error;
}
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index b1d435940eb120..b28a4b0e395e6e 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -199,7 +199,10 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
count -= cnt;
}
- if (buf)
+ /* buf is always NULL except when in monochrome mode, so in this case
+ it's a gain to check buf against NULL even though kfree() handles
+ NULL pointers just fine */
+ if (unlikely(buf))
kfree(buf);
}
@@ -273,8 +276,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
- if (ops->cursor_data)
- kfree(ops->cursor_data);
+ kfree(ops->cursor_data);
ops->cursor_data = dst;
update_attr(dst, src, attribute, vc);
src = dst;
@@ -321,8 +323,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
if (!mask)
return;
- if (ops->cursor_state.mask)
- kfree(ops->cursor_state.mask);
+ kfree(ops->cursor_state.mask);
ops->cursor_state.mask = mask;
p->cursor_shape = vc->vc_cursor_type;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index de92afb5eecf4d..59e3b4b4e7e3e2 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -107,15 +107,15 @@ enum {
};
struct display fb_display[MAX_NR_CONSOLES];
-signed char con2fb_map[MAX_NR_CONSOLES];
-signed char con2fb_map_boot[MAX_NR_CONSOLES];
+static signed char con2fb_map[MAX_NR_CONSOLES];
+static signed char con2fb_map_boot[MAX_NR_CONSOLES];
static int logo_height;
static int logo_lines;
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
enums. */
static int logo_shown = FBCON_LOGO_CANSHOW;
/* Software scrollback */
-int fbcon_softback_size = 32768;
+static int fbcon_softback_size = 32768;
static unsigned long softback_buf, softback_curr;
static unsigned long softback_in;
static unsigned long softback_top, softback_end;
@@ -130,6 +130,8 @@ static char fontname[40];
/* current fb_info */
static int info_idx = -1;
+static const struct consw fb_con;
+
#define CM_SOFTBACK (8)
#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
@@ -204,8 +206,10 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
{
+ struct fbcon_ops *ops = info->fbcon_par;
+
return (info->state != FBINFO_STATE_RUNNING ||
- vc->vc_mode != KD_TEXT);
+ vc->vc_mode != KD_TEXT || ops->graphics);
}
static inline int get_color(struct vc_data *vc, struct fb_info *info,
@@ -307,7 +311,8 @@ static void cursor_timer_handler(unsigned long dev_addr)
mod_timer(&ops->cursor_timer, jiffies + HZ/5);
}
-int __init fb_console_setup(char *this_opt)
+#ifndef MODULE
+static int __init fb_console_setup(char *this_opt)
{
char *options;
int i, j;
@@ -361,6 +366,7 @@ int __init fb_console_setup(char *this_opt)
}
__setup("fbcon=", fb_console_setup);
+#endif
static int search_fb_in_map(int idx)
{
@@ -593,9 +599,12 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
ops->currcon = fg_console;
- if (info->fbops->fb_set_par)
+ if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT))
info->fbops->fb_set_par(info);
+ ops->flags |= FBCON_FLAGS_INIT;
+ ops->graphics = 0;
+
if (vc)
fbcon_set_disp(info, &info->var, vc);
else
@@ -695,6 +704,7 @@ static int var_to_display(struct display *disp,
disp->green = var->green;
disp->blue = var->blue;
disp->transp = var->transp;
+ disp->rotate = var->rotate;
disp->mode = fb_match_mode(var, &info->modelist);
if (disp->mode == NULL)
/* This should not happen */
@@ -718,6 +728,7 @@ static void display_to_var(struct fb_var_screeninfo *var,
var->green = disp->green;
var->blue = disp->blue;
var->transp = disp->transp;
+ var->rotate = disp->rotate;
}
static const char *fbcon_startup(void)
@@ -763,6 +774,7 @@ static const char *fbcon_startup(void)
memset(ops, 0, sizeof(struct fbcon_ops));
ops->currcon = -1;
+ ops->graphics = 1;
info->fbcon_par = ops;
set_blitting_type(vc, info, NULL);
@@ -889,6 +901,7 @@ static const char *fbcon_startup(void)
static void fbcon_init(struct vc_data *vc, int init)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
+ struct fbcon_ops *ops;
struct vc_data **default_mode = vc->vc_display_fg;
struct vc_data *svc = *default_mode;
struct display *t, *p = &fb_display[vc->vc_num];
@@ -939,6 +952,8 @@ static void fbcon_init(struct vc_data *vc, int init)
new_cols = info->var.xres / vc->vc_font.width;
new_rows = info->var.yres / vc->vc_font.height;
vc_resize(vc, new_cols, new_rows);
+
+ ops = info->fbcon_par;
/*
* We must always set the mode. The mode of the previous console
* driver could be in the same resolution but we are using different
@@ -946,9 +961,14 @@ static void fbcon_init(struct vc_data *vc, int init)
*
* We need to do it in fbcon_init() to prevent screen corruption.
*/
- if (CON_IS_VISIBLE(vc) && info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
+ if (CON_IS_VISIBLE(vc)) {
+ if (info->fbops->fb_set_par &&
+ !(ops->flags & FBCON_FLAGS_INIT))
+ info->fbops->fb_set_par(info);
+ ops->flags |= FBCON_FLAGS_INIT;
+ }
+ ops->graphics = 0;
if ((cap & FBINFO_HWACCEL_COPYAREA) &&
!(cap & FBINFO_HWACCEL_DISABLED))
@@ -1111,7 +1131,7 @@ static int scrollback_phys_max = 0;
static int scrollback_max = 0;
static int scrollback_current = 0;
-int update_var(int con, struct fb_info *info)
+static int update_var(int con, struct fb_info *info)
{
if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon)
return fb_pan_display(info, &info->var);
@@ -1871,7 +1891,6 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
var.activate = FB_ACTIVATE_NOW |
FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
- info->flags &= ~FBINFO_MISC_MODESWITCH;
}
var_to_display(p, &info->var, info);
}
@@ -1884,7 +1903,7 @@ static int fbcon_switch(struct vc_data *vc)
struct fb_info *info;
struct display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var;
- int i, prev_console, do_set_par = 0;
+ int i, prev_console;
info = registered_fb[con2fb_map[vc->vc_num]];
@@ -1943,14 +1962,9 @@ static int fbcon_switch(struct vc_data *vc)
fb_set_var(info, &var);
if (prev_console != -1 &&
- registered_fb[con2fb_map[prev_console]] != info)
- do_set_par = 1;
-
- if (do_set_par || info->flags & FBINFO_MISC_MODESWITCH) {
- if (info->fbops->fb_set_par)
- info->fbops->fb_set_par(info);
- info->flags &= ~FBINFO_MISC_MODESWITCH;
- }
+ registered_fb[con2fb_map[prev_console]] != info &&
+ info->fbops->fb_set_par)
+ info->fbops->fb_set_par(info);
set_blitting_type(vc, info, p);
((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
@@ -2013,29 +2027,20 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
struct fbcon_ops *ops = info->fbcon_par;
- int active = !fbcon_is_inactive(vc, info);
if (mode_switch) {
struct fb_var_screeninfo var = info->var;
-/*
- * HACK ALERT: Some hardware will require reinitializion at this stage,
- * others will require it to be done as late as possible.
- * For now, we differentiate this with the
- * FBINFO_MISC_MODESWITCHLATE bitflag. Worst case will be
- * hardware that requires it here and another one later.
- * A definitive solution may require fixing X or the VT
- * system.
- */
- if (info->flags & FBINFO_MISC_MODESWITCHLATE)
- info->flags |= FBINFO_MISC_MODESWITCH;
- if (!blank && !(info->flags & FBINFO_MISC_MODESWITCHLATE)) {
+ ops->graphics = 1;
+
+ if (!blank) {
var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
fb_set_var(info, &var);
+ ops->graphics = 0;
}
}
- if (active) {
+ if (!fbcon_is_inactive(vc, info)) {
if (ops->blank_state != blank) {
ops->blank_state = blank;
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
@@ -2326,6 +2331,9 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
if (fbcon_is_inactive(vc, info))
return -EINVAL;
+ if (!CON_IS_VISIBLE(vc))
+ return 0;
+
depth = fb_get_color_depth(&info->var);
if (depth > 3) {
for (i = j = 0; i < 16; i++) {
@@ -2733,7 +2741,7 @@ static int fbcon_event_notify(struct notifier_block *self,
* The console `switch' structure for the frame buffer based console
*/
-const struct consw fb_con = {
+static const struct consw fb_con = {
.owner = THIS_MODULE,
.con_startup = fbcon_startup,
.con_init = fbcon_init,
@@ -2763,7 +2771,7 @@ static struct notifier_block fbcon_event_notifier = {
.notifier_call = fbcon_event_notify,
};
-int __init fb_console_init(void)
+static int __init fb_console_init(void)
{
int i;
@@ -2791,7 +2799,7 @@ module_init(fb_console_init);
#ifdef MODULE
-void __exit fb_console_exit(void)
+static void __exit fb_console_exit(void)
{
acquire_console_sem();
fb_unregister_client(&fbcon_event_notifier);
@@ -2803,10 +2811,4 @@ module_exit(fb_console_exit);
#endif
-/*
- * Visible symbols for modules
- */
-
-EXPORT_SYMBOL(fb_con);
-
MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 30e641160bf674..5d377860bce283 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -18,6 +18,8 @@
#include <asm/io.h>
+#define FBCON_FLAGS_INIT 1
+
/*
* This is the interface between the low-level console driver and the
* low-level frame buffer device
@@ -41,6 +43,7 @@ struct display {
u32 grayscale;
u32 nonstd;
u32 accel_flags;
+ u32 rotate;
struct fb_bitfield red;
struct fb_bitfield green;
struct fb_bitfield blue;
@@ -67,6 +70,8 @@ struct fbcon_ops {
int cursor_flash;
int cursor_reset;
int blank_state;
+ int graphics;
+ int flags;
char *cursor_data;
};
/*
@@ -156,13 +161,10 @@ struct fbcon_ops {
#define SCROLL_REDRAW 0x004
#define SCROLL_PAN_REDRAW 0x005
-extern int fb_console_init(void);
#ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info,
struct display *p, struct fbcon_ops *ops);
#endif
extern void fbcon_set_bitops(struct fbcon_ops *ops);
-extern const struct consw fb_con;
-
#endif /* _VIDEO_FBCON_H */
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 4a26c828b798f3..989e4d49e5bbea 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -564,7 +564,7 @@ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
* The console `switch' structure for the MDA based console
*/
-const struct consw mda_con = {
+static const struct consw mda_con = {
.owner = THIS_MODULE,
.con_startup = mdacon_startup,
.con_init = mdacon_init,
@@ -591,7 +591,7 @@ int __init mda_console_init(void)
return take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0);
}
-void __exit mda_console_exit(void)
+static void __exit mda_console_exit(void)
{
give_up_console(&mda_con);
}
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 1c5961ce00517b..d940f605acb684 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -798,11 +798,8 @@ sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
return 1;
out_err:
- if(raw)
- kfree(raw);
- if(cooked)
- kfree(cooked);
-
+ kfree(raw);
+ kfree(cooked);
return 0;
}
@@ -1058,7 +1055,7 @@ static void __init sti_init_roms(void)
/* Register drivers for native & PCI cards */
register_parisc_driver(&pa_sti_driver);
- pci_module_init(&pci_sti_driver);
+ pci_register_driver(&pci_sti_driver);
/* if we didn't find the given default sti, take the first one */
if (!default_sti)
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index de51017107179c..8b1b7c687a991a 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1740,7 +1740,7 @@ static int __init cyber2000fb_init(void)
}
#endif
#ifdef CONFIG_PCI
- err = pci_module_init(&cyberpro_driver);
+ err = pci_register_driver(&cyberpro_driver);
if (!err)
ret = 0;
#endif
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 4a45e287ba4591..25f460ca0daf10 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -446,8 +446,7 @@ int fb_show_logo(struct fb_info *info)
logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height,
GFP_KERNEL);
if (logo_new == NULL) {
- if (palette)
- kfree(palette);
+ kfree(palette);
if (saved_pseudo_palette)
info->pseudo_palette = saved_pseudo_palette;
return 0;
@@ -466,12 +465,10 @@ int fb_show_logo(struct fb_info *info)
info->fbops->fb_imageblit(info, &image);
}
- if (palette != NULL)
- kfree(palette);
+ kfree(palette);
if (saved_pseudo_palette != NULL)
info->pseudo_palette = saved_pseudo_palette;
- if (logo_new != NULL)
- kfree(logo_new);
+ kfree(logo_new);
return fb_logo.logo->height;
}
#else
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 905f2e132f43da..978def01358798 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -74,10 +74,9 @@ static struct broken_edid brokendb[] = {
},
};
-const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00
};
-const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
static void copy_string(unsigned char *c, unsigned char *s)
{
@@ -589,8 +588,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
*/
void fb_destroy_modedb(struct fb_videomode *modedb)
{
- if (modedb)
- kfree(modedb);
+ kfree(modedb);
}
static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
@@ -872,18 +870,6 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
DPRINTK("========================================\n");
}
-char *get_EDID_from_firmware(struct device *dev)
-{
- unsigned char *pedid = NULL;
-
-#if defined(CONFIG_EDID_FIRMWARE) && defined(CONFIG_X86)
- pedid = edid_info.dummy;
- if (!pedid)
- return NULL;
-#endif
- return pedid;
-}
-
/*
* VESA Generalized Timing Formula (GTF)
*/
@@ -1193,10 +1179,6 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
{
specs = NULL;
}
-char *get_EDID_from_firmware(struct device *dev)
-{
- return NULL;
-}
void fb_destroy_modedb(struct fb_videomode *modedb)
{
}
@@ -1270,7 +1252,6 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
EXPORT_SYMBOL(fb_parse_edid);
EXPORT_SYMBOL(fb_edid_to_monspecs);
-EXPORT_SYMBOL(get_EDID_from_firmware);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 2da19ea040d0f4..e326f44f652d74 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -536,8 +536,7 @@ int __init igafb_init(void)
if (!iga_init(info, par)) {
iounmap((void *)par->io_base);
iounmap(info->screen_base);
- if (par->mmap_map)
- kfree(par->mmap_map);
+ kfree(par->mmap_map);
kfree(info);
}
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index c1c9e073a12fdb..5a72ca3c01385b 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1611,7 +1611,7 @@ static int __init imsttfb_init(void)
imsttfb_setup(option);
#endif
- return pci_module_init(&imsttfb_pci_driver);
+ return pci_register_driver(&imsttfb_pci_driver);
}
static void __exit imsttfb_exit(void)
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 75a874ce37b185..6a05b70008301f 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -360,7 +360,7 @@ intelfb_init(void)
intelfb_setup(option);
#endif
- return pci_module_init(&intelfb_driver);
+ return pci_register_driver(&intelfb_driver);
}
static void __exit
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index 67f4deaa6a4547..d8bac9e978421b 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -802,7 +802,7 @@ static int __init kyrofb_init(void)
return -ENODEV;
kyrofb_setup(option);
#endif
- return pci_module_init(&kyrofb_pci_driver);
+ return pci_register_driver(&kyrofb_pci_driver);
}
static void __exit kyrofb_exit(void)
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 3cd1145a6c6625..de5a0f38360083 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/string.h>
+#include <linux/module.h>
#include "macmodes.h"
@@ -281,7 +282,7 @@ int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
var->vmode = mode->vmode;
return 0;
}
-
+EXPORT_SYMBOL(mac_vmode_to_var);
/**
* mac_var_to_vmode - convert var structure to MacOS vmode/cmode pair
@@ -326,7 +327,7 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
}
return -EINVAL;
}
-
+EXPORT_SYMBOL(mac_var_to_vmode);
/**
* mac_map_monitor_sense - Convert monitor sense to vmode
@@ -348,7 +349,7 @@ int mac_map_monitor_sense(int sense)
break;
return map->vmode;
}
-
+EXPORT_SYMBOL(mac_map_monitor_sense);
/**
* mac_find_mode - find a video mode
@@ -384,3 +385,5 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
return fb_find_mode(var, info, mode_option, db, dbsize,
&mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp);
}
+EXPORT_SYMBOL(mac_find_mode);
+
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index 8f14c9b300c286..c7f3e1321224d3 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -438,13 +438,21 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
} else if (step == 1) {
/* Special case for 1..8bit widths */
while (height--) {
- mga_writel(mmio, 0, *chardata);
+#if defined(__BIG_ENDIAN)
+ fb_writel((*chardata) << 24, mmio.vaddr);
+#else
+ fb_writel(*chardata, mmio.vaddr);
+#endif
chardata++;
}
} else if (step == 2) {
/* Special case for 9..15bit widths */
while (height--) {
- mga_writel(mmio, 0, *(u_int16_t*)chardata);
+#if defined(__BIG_ENDIAN)
+ fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr);
+#else
+ fb_writel(*(u_int16_t*)chardata, mmio.vaddr);
+#endif
chardata += 2;
}
} else {
@@ -454,7 +462,7 @@ static void matroxfb_1bpp_imageblit(WPMINFO u_int32_t fgx, u_int32_t bgx,
for (i = 0; i < step; i += 4) {
/* Hope that there are at least three readable bytes beyond the end of bitmap */
- mga_writel(mmio, 0, get_unaligned((u_int32_t*)(chardata + i)));
+ fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
}
chardata += step;
}
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 942ec768abd970..85a0b255845279 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -170,14 +170,14 @@ static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
if ((unsigned long)src & 3) {
while (len >= 4) {
- writel(get_unaligned((u32 *)src), addr);
+ fb_writel(get_unaligned((u32 *)src), addr);
addr++;
len -= 4;
src += 4;
}
} else {
while (len >= 4) {
- writel(*(u32 *)src, addr);
+ fb_writel(*(u32 *)src, addr);
addr++;
len -= 4;
src += 4;
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 805f6831af0bc5..fbf659b6dab01e 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -404,8 +404,8 @@ static int my_atoi(const char *name)
*
*/
-int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
- const struct fb_videomode *mode, unsigned int bpp)
+static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
+ const struct fb_videomode *mode, unsigned int bpp)
{
int err = 0;
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 085b4704a46ef8..5d424a30270acd 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1691,7 +1691,27 @@ static int __devinit neo_map_mmio(struct fb_info *info,
DBG("neo_map_mmio");
- info->fix.mmio_start = pci_resource_start(dev, 1);
+ switch (info->fix.accel) {
+ case FB_ACCEL_NEOMAGIC_NM2070:
+ info->fix.mmio_start = pci_resource_start(dev, 0)+
+ 0x100000;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2090:
+ case FB_ACCEL_NEOMAGIC_NM2093:
+ info->fix.mmio_start = pci_resource_start(dev, 0)+
+ 0x200000;
+ break;
+ case FB_ACCEL_NEOMAGIC_NM2160:
+ case FB_ACCEL_NEOMAGIC_NM2097:
+ case FB_ACCEL_NEOMAGIC_NM2200:
+ case FB_ACCEL_NEOMAGIC_NM2230:
+ case FB_ACCEL_NEOMAGIC_NM2360:
+ case FB_ACCEL_NEOMAGIC_NM2380:
+ info->fix.mmio_start = pci_resource_start(dev, 1);
+ break;
+ default:
+ info->fix.mmio_start = pci_resource_start(dev, 0);
+ }
info->fix.mmio_len = MMIO_SIZE;
if (!request_mem_region
@@ -2010,6 +2030,7 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
par->internal_display = internal;
par->external_display = external;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
switch (info->fix.accel) {
case FB_ACCEL_NEOMAGIC_NM2070:
@@ -2029,15 +2050,27 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
break;
case FB_ACCEL_NEOMAGIC_NM2200:
sprintf(info->fix.id, "MagicGraph 256AV");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2230:
sprintf(info->fix.id, "MagicGraph 256AV+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2360:
sprintf(info->fix.id, "MagicGraph 256ZX");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
case FB_ACCEL_NEOMAGIC_NM2380:
sprintf(info->fix.id, "MagicGraph 256XL+");
+ info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
+ FBINFO_HWACCEL_COPYAREA |
+ FBINFO_HWACCEL_FILLRECT;
break;
}
@@ -2049,9 +2082,6 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
info->fix.accel = id->driver_data;
info->fbops = &neofb_ops;
- info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA |
- FBINFO_HWACCEL_COPYAREA;
info->pseudo_palette = (void *) (par + 1);
return info;
}
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
index 8050ff979f9d73..f377a29ec97a6c 100644
--- a/drivers/video/nvidia/nv_accel.c
+++ b/drivers/video/nvidia/nv_accel.c
@@ -1,12 +1,50 @@
+ /***************************************************************************\
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NOTICE TO USER: The source code is copyrighted under U.S. and *|
+|* international laws. Users and possessors of this source code are *|
+|* hereby granted a nonexclusive, royalty-free copyright license to *|
+|* use this code in individual and commercial software. *|
+|* *|
+|* Any use of this source code must include, in the user documenta- *|
+|* tion and internal comments to the code, notices to the end user *|
+|* as follows: *|
+|* *|
+|* Copyright 1993-2003 NVIDIA, Corporation. All rights reserved. *|
+|* *|
+|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
+|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
+|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
+|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
+|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
+|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
+|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
+|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
+|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
+|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
+|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
+|* *|
+|* U.S. Government End Users. This source code is a "commercial *|
+|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
+|* consisting of "commercial computer software" and "commercial *|
+|* computer software documentation," as such terms are used in *|
+|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
+|* ment only as a commercial end item. Consistent with 48 C.F.R. *|
+|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
+|* all U.S. Government End Users acquire the source code with only *|
+|* those rights set forth herein. *|
+|* *|
+ \***************************************************************************/
+
/*
- * linux/drivers/video/nvidia/nv_accel.c - nVidia Hardware Acceleration
- *
- * Copyright 2004 Antonino Daplas <adaplas@pol.net>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
*
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
*/
#include <linux/fb.h>
@@ -321,10 +359,10 @@ static void nvidiafb_mono_color_expand(struct fb_info *info,
struct nvidia_par *par = info->par;
u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
u32 dsize, width, *data = (u32 *) image->data, tmp;
- int i, j, k = 0;
+ int j, k = 0;
width = (image->width + 31) & ~31;
- dsize = width >> 5;
+ dsize = (width * image->height) >> 5;
if (info->var.bits_per_pixel == 8) {
fg = image->fg_color | mask;
@@ -344,8 +382,22 @@ static void nvidiafb_mono_color_expand(struct fb_info *info,
NVDmaNext(par, (image->height << 16) | width);
NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
- for (i = image->height; i--;) {
+ while (dsize >= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS) {
+ NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0),
+ RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS);
+
+ for (j = RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS; j--;) {
+ tmp = data[k++];
+ reverse_order(&tmp);
+ NVDmaNext(par, tmp);
+ }
+
+ dsize -= RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS;
+ }
+
+ if (dsize) {
NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
+
for (j = dsize; j--;) {
tmp = data[k++];
reverse_order(&tmp);
diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h
index 5cc42537d006f0..a7ed1c0acbbbd5 100644
--- a/drivers/video/nvidia/nv_dma.h
+++ b/drivers/video/nvidia/nv_dma.h
@@ -38,6 +38,16 @@
|* *|
\***************************************************************************/
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
#define SURFACE_FORMAT 0x00000300
#define SURFACE_FORMAT_DEPTH8 0x00000001
#define SURFACE_FORMAT_DEPTH15 0x00000002
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index ffecb23bca210a..b989358437b372 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -36,6 +36,17 @@
|* those rights set forth herein. *|
|* *|
\***************************************************************************/
+
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */
#include <linux/pci.h>
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index 9e49e9ee44190e..3757c1407c1901 100644
--- a/drivers/video/nvidia/nv_i2c.c
+++ b/drivers/video/nvidia/nv_i2c.c
@@ -146,7 +146,6 @@ void nvidia_create_i2c_busses(struct nvidia_par *par)
nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
}
-#if 0
void nvidia_delete_i2c_busses(struct nvidia_par *par)
{
if (par->chan[0].par)
@@ -162,7 +161,6 @@ void nvidia_delete_i2c_busses(struct nvidia_par *par)
par->chan[2].par = NULL;
}
-#endif /* 0 */
static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
{
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
index 89a0ae89ea4473..9da320986f4c92 100644
--- a/drivers/video/nvidia/nv_local.h
+++ b/drivers/video/nvidia/nv_local.h
@@ -37,6 +37,16 @@
|* *|
\***************************************************************************/
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
#ifndef __NV_LOCAL_H__
#define __NV_LOCAL_H__
@@ -77,9 +87,8 @@
#endif
#define WRITE_PUT(par, data) { \
- volatile u8 scratch; \
_NV_FENCE() \
- scratch = NV_RD08((par)->FbStart, 0); \
+ NV_RD08((par)->FbStart, 0); \
NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \
mb(); \
}
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index 660ac29d723e1a..7d12eb85310de0 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -28,6 +28,7 @@
#include "nv_proto.h"
void nvidia_create_i2c_busses(struct nvidia_par *par) {}
+void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
{
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index 0c5dd425eb5d86..42847ce1b8dd76 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -33,10 +33,12 @@ void NVLockUnlock(struct nvidia_par *par, int);
/* in nvidia-i2c.c */
#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
void nvidia_create_i2c_busses(struct nvidia_par *par);
+void nvidia_delete_i2c_busses(struct nvidia_par *par);
int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
u8 ** out_edid);
#else
#define nvidia_create_i2c_busses(...)
+#define nvidia_delete_i2c_busses(...)
#define nvidia_probe_i2c_connector(p, c, edid) \
do { \
*(edid) = NULL; \
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index ed2566cbe8c726..0bbdca2e0f9118 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -37,6 +37,16 @@
|* *|
\***************************************************************************/
+/*
+ * GPL Licensing Note - According to Mark Vojkovich, author of the Xorg/
+ * XFree86 'nv' driver, this source code is provided under MIT-style licensing
+ * where the source code is provided "as is" without warranty of any kind.
+ * The only usage restriction is for the copyright notices to be retained
+ * whenever code is used.
+ *
+ * Antonino Daplas <adaplas@pol.net> 2005-03-11
+ */
+
#include <video/vga.h>
#include <linux/delay.h>
#include <linux/pci.h>
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 2dfecddc308e30..3a6555a8aaa252 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -402,25 +402,25 @@ static struct pci_device_id nvidiafb_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
/* command line data, set in nvidiafb_setup() */
-static int flatpanel __initdata = -1; /* Autodetect later */
-static int forceCRTC __initdata = -1;
-static int hwcur __initdata = 0;
-static int noaccel __initdata = 0;
-static int noscale __initdata = 0;
-static int paneltweak __initdata = 0;
+static int flatpanel __devinitdata = -1; /* Autodetect later */
+static int forceCRTC __devinitdata = -1;
+static int hwcur __devinitdata = 0;
+static int noaccel __devinitdata = 0;
+static int noscale __devinitdata = 0;
+static int paneltweak __devinitdata = 0;
#ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
+static int nomtrr __devinitdata = 0;
#endif
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
-static struct fb_fix_screeninfo __initdata nvidiafb_fix = {
+static struct fb_fix_screeninfo __devinitdata nvidiafb_fix = {
.type = FB_TYPE_PACKED_PIXELS,
.xpanstep = 8,
.ypanstep = 1,
};
-static struct fb_var_screeninfo __initdata nvidiafb_default_var = {
+static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
@@ -1191,6 +1191,7 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var,
var->yres_virtual = var->yres;
var->xres_virtual = vramlen / var->yres_virtual;
var->xres_virtual /= var->bits_per_pixel / 8;
+ var->xres_virtual &= ~63;
pitch = (var->xres_virtual *
var->bits_per_pixel + 7) / 8;
memlen = pitch * var->yres;
@@ -1301,7 +1302,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
| FBINFO_HWACCEL_IMAGEBLIT
| FBINFO_HWACCEL_FILLRECT
| FBINFO_HWACCEL_COPYAREA
- | FBINFO_HWACCEL_YPAN | FBINFO_MISC_MODESWITCHLATE;
+ | FBINFO_HWACCEL_YPAN;
fb_videomode_to_modelist(info->monspecs.modedb,
info->monspecs.modedb_len, &info->modelist);
@@ -1352,8 +1353,6 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
if (!hwcur)
info->fbops->fb_cursor = soft_cursor;
info->var.accel_flags = (!noaccel);
- par->FpScale = (!noscale);
- par->paneltweak = paneltweak;
switch (par->Architecture) {
case NV_ARCH_04:
@@ -1485,6 +1484,8 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
printk(KERN_INFO PFX "flatpanel support enabled\n");
par->CRTCnumber = forceCRTC;
+ par->FpScale = (!noscale);
+ par->paneltweak = paneltweak;
/* enable IO and mem if not already done */
pci_read_config_word(pd, PCI_COMMAND, &cmd);
@@ -1565,8 +1566,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
err_out_iounmap_fb:
iounmap(info->screen_base);
- err_out_free_base1:
fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
+ err_out_free_base1:
iounmap(par->REGS);
err_out_free_base0:
pci_release_regions(pd);
@@ -1596,9 +1598,10 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
info->fix.smem_len);
#endif /* CONFIG_MTRR */
+ iounmap(info->screen_base);
fb_destroy_modedb(info->monspecs.modedb);
+ nvidia_delete_i2c_busses(par);
iounmap(par->REGS);
- iounmap(info->screen_base);
pci_release_regions(pd);
pci_disable_device(pd);
kfree(info->pixmap.addr);
@@ -1614,7 +1617,7 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
* ------------------------------------------------------------------------- */
#ifndef MODULE
-static int __init nvidiafb_setup(char *options)
+static int __devinit nvidiafb_setup(char *options)
{
char *this_opt;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 496624c277c1b2..5dceddedf50752 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -747,7 +747,7 @@ static int pm2fb_set_par(struct fb_info *info)
}
if ((info->var.vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
video |= PM2F_LINE_DOUBLE;
- if (info->var.activate==FB_ACTIVATE_NOW)
+ if ((info->var.activate & FB_ACTIVATE_MASK)==FB_ACTIVATE_NOW)
video |= PM2F_VIDEO_ENABLE;
par->video = video;
@@ -1282,7 +1282,7 @@ static int __init pm2fb_init(void)
pm2fb_setup(option);
#endif
- return pci_module_init(&pm2fb_driver);
+ return pci_register_driver(&pm2fb_driver);
}
module_init(pm2fb_init);
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 6741b522c0d365..31c547fd383bf7 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -967,7 +967,7 @@ static struct pci_driver pvr2fb_pci_driver = {
static int __init pvr2fb_pci_init(void)
{
- return pci_module_init(&pvr2fb_pci_driver);
+ return pci_register_driver(&pvr2fb_pci_driver);
}
static void pvr2fb_pci_exit(void)
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 552a38e5f143fb..483ad9bab53904 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -1343,8 +1343,7 @@ int __init pxafb_probe(struct device *dev)
failed:
dev_set_drvdata(dev, NULL);
- if (fbi)
- kfree(fbi);
+ kfree(fbi);
return ret;
}
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 3fad3f70b9d3d5..d9a084e77a6323 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -3150,7 +3150,7 @@ static int __init radeonfb_old_init (void)
return -ENODEV;
radeonfb_old_setup(option);
#endif
- return pci_module_init (&radeonfb_driver);
+ return pci_register_driver (&radeonfb_driver);
}
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 7a6e82567ff897..b0c886de04043c 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1708,8 +1708,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
| FBINFO_HWACCEL_YPAN
| FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
- | FBINFO_HWACCEL_IMAGEBLIT
- | FBINFO_MISC_MODESWITCHLATE;
+ | FBINFO_HWACCEL_IMAGEBLIT;
/* Accel seems to not work properly on NV30 yet...*/
if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
@@ -2109,8 +2108,7 @@ static void __exit rivafb_remove(struct pci_dev *pd)
#ifdef CONFIG_FB_RIVA_I2C
riva_delete_i2c_busses(par);
- if (par->EDID)
- kfree(par->EDID);
+ kfree(par->EDID);
#endif
unregister_framebuffer(info);
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
new file mode 100644
index 00000000000000..b637c389e4f480
--- /dev/null
+++ b/drivers/video/s1d13xxxfb.c
@@ -0,0 +1,772 @@
+/* drivers/video/s1d13xxxfb.c
+ *
+ * (c) 2004 Simtec Electronics
+ * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * Driver for Epson S1D13xxx series framebuffer chips
+ *
+ * Adapted from
+ * linux/drivers/video/skeletonfb.c
+ * linux/drivers/video/epson1355fb.c
+ * linux/drivers/video/epson/s1d13xxxfb.c (2.4 driver by Epson)
+ *
+ * Note, currently only tested on S1D13806 with 16bit CRT.
+ * As such, this driver might still contain some hardcoded bits relating to
+ * S1D13806.
+ * Making it work on other S1D13XXX chips should merely be a matter of adding
+ * a few switch()s, some missing glue here and there maybe, and split header
+ * files.
+ *
+ * TODO: - handle dual screen display (CRT and LCD at the same time).
+ * - check_var(), mode change, etc.
+ * - PM untested.
+ * - Accelerated interfaces.
+ * - Probably not SMP safe :)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <video/s1d13xxxfb.h>
+
+#define PFX "s1d13xxxfb: "
+
+#if 0
+#define dbg(fmt, args...) do { printk(KERN_INFO fmt, ## args); } while(0)
+#else
+#define dbg(fmt, args...) do { } while (0)
+#endif
+
+/*
+ * Here we define the default struct fb_fix_screeninfo
+ */
+static struct fb_fix_screeninfo __devinitdata s1d13xxxfb_fix = {
+ .id = S1D_FBID,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_PSEUDOCOLOR,
+ .xpanstep = 0,
+ .ypanstep = 1,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+};
+
+static inline u8
+s1d13xxxfb_readreg(struct s1d13xxxfb_par *par, u16 regno)
+{
+ return readb(par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_writereg(struct s1d13xxxfb_par *par, u16 regno, u8 value)
+{
+ writeb(value, par->regs + regno);
+}
+
+static inline void
+s1d13xxxfb_runinit(struct s1d13xxxfb_par *par,
+ const struct s1d13xxxfb_regval *initregs,
+ const unsigned int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if ((initregs[i].addr == S1DREG_DELAYOFF) ||
+ (initregs[i].addr == S1DREG_DELAYON))
+ mdelay((int)initregs[i].value);
+ else {
+ s1d13xxxfb_writereg(par, initregs[i].addr, initregs[i].value);
+ }
+ }
+
+ /* make sure the hardware can cope with us */
+ mdelay(1);
+}
+
+static inline void
+lcd_enable(struct s1d13xxxfb_par *par, int enable)
+{
+ u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+ if (enable)
+ mode |= 0x01;
+ else
+ mode &= ~0x01;
+
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+static inline void
+crt_enable(struct s1d13xxxfb_par *par, int enable)
+{
+ u8 mode = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+
+ if (enable)
+ mode |= 0x02;
+ else
+ mode &= ~0x02;
+
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, mode);
+}
+
+/* framebuffer control routines */
+
+static inline void
+s1d13xxxfb_setup_pseudocolour(struct fb_info *info)
+{
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+
+ info->var.red.length = 4;
+ info->var.green.length = 4;
+ info->var.blue.length = 4;
+}
+
+static inline void
+s1d13xxxfb_setup_truecolour(struct fb_info *info)
+{
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ info->var.bits_per_pixel = 16;
+
+ info->var.red.length = 5;
+ info->var.red.offset = 11;
+
+ info->var.green.length = 6;
+ info->var.green.offset = 5;
+
+ info->var.blue.length = 5;
+ info->var.blue.offset = 0;
+}
+
+/**
+ * s1d13xxxfb_set_par - Alters the hardware state.
+ * @info: frame buffer structure
+ *
+ * Using the fb_var_screeninfo in fb_info we set the depth of the
+ * framebuffer. This function alters the par AND the
+ * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
+ * fb_info since we are using that data. This means we depend on the
+ * data in var inside fb_info to be supported by the hardware.
+ * xxxfb_check_var is always called before xxxfb_set_par to ensure this.
+ *
+ * XXX TODO: write proper s1d13xxxfb_check_var(), without which that
+ * function is quite useless.
+ */
+static int
+s1d13xxxfb_set_par(struct fb_info *info)
+{
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ unsigned int val;
+
+ dbg("s1d13xxxfb_set_par: bpp=%d\n", info->var.bits_per_pixel);
+
+ if ((s1dfb->display & 0x01)) /* LCD */
+ val = s1d13xxxfb_readreg(s1dfb, S1DREG_LCD_DISP_MODE); /* read colour control */
+ else /* CRT */
+ val = s1d13xxxfb_readreg(s1dfb, S1DREG_CRT_DISP_MODE); /* read colour control */
+
+ val &= ~0x07;
+
+ switch (info->var.bits_per_pixel) {
+ case 4:
+ dbg("pseudo colour 4\n");
+ s1d13xxxfb_setup_pseudocolour(info);
+ val |= 2;
+ break;
+ case 8:
+ dbg("pseudo colour 8\n");
+ s1d13xxxfb_setup_pseudocolour(info);
+ val |= 3;
+ break;
+ case 16:
+ dbg("true colour\n");
+ s1d13xxxfb_setup_truecolour(info);
+ val |= 5;
+ break;
+
+ default:
+ dbg("bpp not supported!\n");
+ return -EINVAL;
+ }
+
+ dbg("writing %02x to display mode register\n", val);
+
+ if ((s1dfb->display & 0x01)) /* LCD */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LCD_DISP_MODE, val);
+ else /* CRT */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_CRT_DISP_MODE, val);
+
+ info->fix.line_length = info->var.xres * info->var.bits_per_pixel;
+ info->fix.line_length /= 8;
+
+ dbg("setting line_length to %d\n", info->fix.line_length);
+
+ dbg("done setup\n");
+
+ return 0;
+}
+
+/**
+ * s1d13xxxfb_setcolreg - sets a color register.
+ * @regno: Which register in the CLUT we are programming
+ * @red: The red value which can be up to 16 bits wide
+ * @green: The green value which can be up to 16 bits wide
+ * @blue: The blue value which can be up to 16 bits wide.
+ * @transp: If supported the alpha value which can be up to 16 bits wide.
+ * @info: frame buffer info structure
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ unsigned int pseudo_val;
+
+ if (regno >= S1D_PALETTE_SIZE)
+ return -EINVAL;
+
+ dbg("s1d13xxxfb_setcolreg: %d: rgb=%d,%d,%d, tr=%d\n",
+ regno, red, green, blue, transp);
+
+ if (info->var.grayscale)
+ red = green = blue = (19595*red + 38470*green + 7471*blue) >> 16;
+
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ if (regno >= 16)
+ return -EINVAL;
+
+ /* deal with creating pseudo-palette entries */
+
+ pseudo_val = (red >> 11) << info->var.red.offset;
+ pseudo_val |= (green >> 10) << info->var.green.offset;
+ pseudo_val |= (blue >> 11) << info->var.blue.offset;
+
+ dbg("s1d13xxxfb_setcolreg: pseudo %d, val %08x\n",
+ regno, pseudo_val);
+
+ ((u32 *)info->pseudo_palette)[regno] = pseudo_val;
+
+ break;
+ case FB_VISUAL_PSEUDOCOLOR:
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_ADDR, regno);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, red);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, green);
+ s1d13xxxfb_writereg(s1dfb, S1DREG_LKUP_DATA, blue);
+
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ dbg("s1d13xxxfb_setcolreg: done\n");
+
+ return 0;
+}
+
+/**
+ * s1d13xxxfb_blank - blanks the display.
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ * video mode which doesn't support it. Implements VESA suspend
+ * and powerdown modes on hardware that supports disabling hsync/vsync:
+ * blank_mode == 2: suspend vsync
+ * blank_mode == 3: suspend hsync
+ * blank_mode == 4: powerdown
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_blank(int blank_mode, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *par = info->par;
+
+ dbg("s1d13xxxfb_blank: blank=%d, info=%p\n", blank_mode, info);
+
+ switch (blank_mode) {
+ case FB_BLANK_UNBLANK:
+ case FB_BLANK_NORMAL:
+ if ((par->display & 0x01) != 0)
+ lcd_enable(par, 1);
+ if ((par->display & 0x02) != 0)
+ crt_enable(par, 1);
+ break;
+ case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
+ break;
+ case FB_BLANK_POWERDOWN:
+ lcd_enable(par, 0);
+ crt_enable(par, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* let fbcon do a soft blank for us */
+ return ((blank_mode == FB_BLANK_NORMAL) ? 1 : 0);
+}
+
+/**
+ * s1d13xxxfb_pan_display - Pans the display.
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * `yoffset' field of the `var' structure (`xoffset' not yet supported).
+ * If the values don't fit, return -EINVAL.
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+static int
+s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct s1d13xxxfb_par *par = info->par;
+ u32 start;
+
+ if (var->xoffset != 0) /* not yet ... */
+ return -EINVAL;
+
+ if (var->yoffset + info->var.yres > info->var.yres_virtual)
+ return -EINVAL;
+
+ start = (info->fix.line_length >> 1) * var->yoffset;
+
+ if ((par->display & 0x01)) {
+ /* LCD */
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START0, (start & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START1, ((start >> 8) & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_LCD_DISP_START2, ((start >> 16) & 0x0f));
+ } else {
+ /* CRT */
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START0, (start & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START1, ((start >> 8) & 0xff));
+ s1d13xxxfb_writereg(par, S1DREG_CRT_DISP_START2, ((start >> 16) & 0x0f));
+ }
+
+ return 0;
+}
+
+
+/* framebuffer information structures */
+
+static struct fb_ops s1d13xxxfb_fbops = {
+ .owner = THIS_MODULE,
+ .fb_set_par = s1d13xxxfb_set_par,
+ .fb_setcolreg = s1d13xxxfb_setcolreg,
+ .fb_blank = s1d13xxxfb_blank,
+
+ .fb_pan_display = s1d13xxxfb_pan_display,
+
+ /* to be replaced by any acceleration we can */
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor
+};
+
+static int s1d13xxxfb_width_tab[2][4] __devinitdata = {
+ {4, 8, 16, -1},
+ {9, 12, 18, -1},
+};
+
+/**
+ * s1d13xxxfb_fetch_hw_state - Configure the framebuffer according to
+ * hardware setup.
+ * @info: frame buffer structure
+ *
+ * We setup the framebuffer structures according to the current
+ * hardware setup. On some machines, the BIOS will have filled
+ * the chip registers with such info, on others, these values will
+ * have been written in some init procedure. In any case, the
+ * software values needs to match the hardware ones. This is what
+ * this function ensures.
+ *
+ * Note: some of the hardcoded values here might need some love to
+ * work on various chips, and might need to no longer be hardcoded.
+ */
+static void __devinit
+s1d13xxxfb_fetch_hw_state(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct s1d13xxxfb_par *par = info->par;
+ u8 panel, display;
+ u16 offset;
+ u32 xres, yres;
+ u32 xres_virtual, yres_virtual;
+ int bpp, lcd_bpp;
+ int is_color, is_dual, is_tft;
+ int lcd_enabled, crt_enabled;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+
+ /* general info */
+ par->display = s1d13xxxfb_readreg(par, S1DREG_COM_DISP_MODE);
+ crt_enabled = (par->display & 0x02) != 0;
+ lcd_enabled = (par->display & 0x01) != 0;
+
+ if (lcd_enabled && crt_enabled)
+ printk(KERN_WARNING PFX "Warning: LCD and CRT detected, using LCD\n");
+
+ if (lcd_enabled)
+ display = s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_MODE);
+ else /* CRT */
+ display = s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_MODE);
+
+ bpp = display & 0x07;
+
+ switch (bpp) {
+ case 2: /* 4 bpp */
+ case 3: /* 8 bpp */
+ var->bits_per_pixel = 8;
+ var->red.offset = var->green.offset = var->blue.offset = 0;
+ var->red.length = var->green.length = var->blue.length = 8;
+ break;
+ case 5: /* 16 bpp */
+ s1d13xxxfb_setup_truecolour(info);
+ break;
+ default:
+ dbg("bpp: %i\n", bpp);
+ }
+ fb_alloc_cmap(&info->cmap, 256, 0);
+
+ /* LCD info */
+ panel = s1d13xxxfb_readreg(par, S1DREG_PANEL_TYPE);
+ is_color = (panel & 0x04) != 0;
+ is_dual = (panel & 0x02) != 0;
+ is_tft = (panel & 0x01) != 0;
+ lcd_bpp = s1d13xxxfb_width_tab[is_tft][(panel >> 4) & 3];
+
+ if (lcd_enabled) {
+ xres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_HWIDTH) + 1) * 8;
+ yres = (s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_LCD_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+ offset = (s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_LCD_MEM_OFF1) & 0x7) << 8));
+ } else { /* crt */
+ xres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_HWIDTH) + 1) * 8;
+ yres = (s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_CRT_DISP_VHEIGHT1) & 0x03) << 8) + 1);
+
+ offset = (s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF0) +
+ ((s1d13xxxfb_readreg(par, S1DREG_CRT_MEM_OFF1) & 0x7) << 8));
+ }
+ xres_virtual = offset * 16 / var->bits_per_pixel;
+ yres_virtual = fix->smem_len / (offset * 2);
+
+ var->xres = xres;
+ var->yres = yres;
+ var->xres_virtual = xres_virtual;
+ var->yres_virtual = yres_virtual;
+ var->xoffset = var->yoffset = 0;
+
+ fix->line_length = offset * 2;
+
+ var->grayscale = !is_color;
+
+ var->activate = FB_ACTIVATE_NOW;
+
+ dbg(PFX "bpp=%d, lcd_bpp=%d, "
+ "crt_enabled=%d, lcd_enabled=%d\n",
+ var->bits_per_pixel, lcd_bpp, crt_enabled, lcd_enabled);
+ dbg(PFX "xres=%d, yres=%d, vxres=%d, vyres=%d "
+ "is_color=%d, is_dual=%d, is_tft=%d\n",
+ xres, yres, xres_virtual, yres_virtual, is_color, is_dual, is_tft);
+}
+
+
+static int __devexit
+s1d13xxxfb_remove(struct device *dev)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s1d13xxxfb_par *par = NULL;
+
+ if (info) {
+ par = info->par;
+ if (par && par->regs) {
+ /* disable output & enable powersave */
+ s1d13xxxfb_writereg(par, S1DREG_COM_DISP_MODE, 0x00);
+ s1d13xxxfb_writereg(par, S1DREG_PS_CNF, 0x11);
+ iounmap(par->regs);
+ }
+
+ fb_dealloc_cmap(&info->cmap);
+
+ if (info->screen_base)
+ iounmap(info->screen_base);
+
+ framebuffer_release(info);
+ }
+
+ release_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1);
+ release_mem_region(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1);
+ return 0;
+}
+
+static int __devinit
+s1d13xxxfb_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct s1d13xxxfb_par *default_par;
+ struct fb_info *info;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+ int ret = 0;
+ u8 revision;
+
+ dbg("probe called: device is %p\n", dev);
+
+ printk(KERN_INFO "Epson S1D13XXX FB Driver\n");
+
+ /* enable platform-dependent hardware glue, if any */
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+ if (pdata && pdata->platform_init_video)
+ pdata->platform_init_video();
+
+
+ if (pdev->num_resources != 2) {
+ dev_err(&pdev->dev, "invalid num_resources: %i\n",
+ pdev->num_resources);
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ /* resource[0] is VRAM, resource[1] is registers */
+ if (pdev->resource[0].flags != IORESOURCE_MEM
+ || pdev->resource[1].flags != IORESOURCE_MEM) {
+ dev_err(&pdev->dev, "invalid resource type\n");
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (!request_mem_region(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1, "s1d13xxxfb mem")) {
+ dev_dbg(dev, "request_mem_region failed\n");
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ if (!request_mem_region(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1, "s1d13xxxfb regs")) {
+ dev_dbg(dev, "request_mem_region failed\n");
+ ret = -EBUSY;
+ goto bail;
+ }
+
+ info = framebuffer_alloc(sizeof(struct s1d13xxxfb_par) + sizeof(u32) * 256, &pdev->dev);
+ if (!info) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ default_par = info->par;
+ default_par->regs = ioremap_nocache(pdev->resource[1].start,
+ pdev->resource[1].end - pdev->resource[1].start +1);
+ if (!default_par->regs) {
+ printk(KERN_ERR PFX "unable to map registers\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+ info->pseudo_palette = default_par->pseudo_palette;
+
+ info->screen_base = ioremap_nocache(pdev->resource[0].start,
+ pdev->resource[0].end - pdev->resource[0].start +1);
+
+ if (!info->screen_base) {
+ printk(KERN_ERR PFX "unable to map framebuffer\n");
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE);
+ if ((revision >> 2) != S1D_CHIP_REV) {
+ printk(KERN_INFO PFX "chip not found: %i\n", (revision >> 2));
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ info->fix = s1d13xxxfb_fix;
+ info->fix.mmio_start = pdev->resource[1].start;
+ info->fix.mmio_len = pdev->resource[1].end - pdev->resource[1].start +1;
+ info->fix.smem_start = pdev->resource[0].start;
+ info->fix.smem_len = pdev->resource[0].end - pdev->resource[0].start +1;
+
+ printk(KERN_INFO PFX "regs mapped at 0x%p, fb %d KiB mapped at 0x%p\n",
+ default_par->regs, info->fix.smem_len / 1024, info->screen_base);
+
+ info->par = default_par;
+ info->fbops = &s1d13xxxfb_fbops;
+ info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+ /* perform "manual" chip initialization, if needed */
+ if (pdata && pdata->initregs)
+ s1d13xxxfb_runinit(info->par, pdata->initregs, pdata->initregssize);
+
+ s1d13xxxfb_fetch_hw_state(info);
+
+ if (register_framebuffer(info) < 0) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ dev_set_drvdata(&pdev->dev, info);
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n",
+ info->node, info->fix.id);
+
+ return 0;
+
+bail:
+ s1d13xxxfb_remove(dev);
+ return ret;
+
+}
+
+#ifdef CONFIG_PM
+static int s1d13xxxfb_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+
+ /* disable display */
+ lcd_enable(s1dfb, 0);
+ crt_enable(s1dfb, 0);
+
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+#if 0
+ if (!s1dfb->disp_save)
+ s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
+
+ if (!s1dfb->disp_save) {
+ printk(KERN_ERR PFX "no memory to save screen");
+ return -ENOMEM;
+ }
+
+ memcpy_fromio(s1dfb->disp_save, info->screen_base, info->fix.smem_len);
+#else
+ s1dfb->disp_save = NULL;
+#endif
+
+ if (!s1dfb->regs_save)
+ s1dfb->regs_save = kmalloc(info->fix.mmio_len, GFP_KERNEL);
+
+ if (!s1dfb->regs_save) {
+ printk(KERN_ERR PFX "no memory to save registers");
+ return -ENOMEM;
+ }
+
+ /* backup all registers */
+ memcpy_fromio(s1dfb->regs_save, s1dfb->regs, info->fix.mmio_len);
+
+ /* now activate power save mode */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x11);
+
+ if (pdata && pdata->platform_suspend_video)
+ return pdata->platform_suspend_video();
+ else
+ return 0;
+}
+
+static int s1d13xxxfb_resume(struct device *dev, u32 level)
+{
+ struct fb_info *info = dev_get_drvdata(dev);
+ struct s1d13xxxfb_par *s1dfb = info->par;
+ struct s1d13xxxfb_pdata *pdata = NULL;
+
+ if (level != RESUME_ENABLE)
+ return 0;
+
+ /* awaken the chip */
+ s1d13xxxfb_writereg(s1dfb, S1DREG_PS_CNF, 0x10);
+
+ /* do not let go until SDRAM "wakes up" */
+ while ((s1d13xxxfb_readreg(s1dfb, S1DREG_PS_STATUS) & 0x01))
+ udelay(10);
+
+ if (dev->platform_data)
+ pdata = dev->platform_data;
+
+ if (s1dfb->regs_save) {
+ /* will write RO regs, *should* get away with it :) */
+ memcpy_toio(s1dfb->regs, s1dfb->regs_save, info->fix.mmio_len);
+ kfree(s1dfb->regs_save);
+ }
+
+ if (s1dfb->disp_save) {
+ memcpy_toio(info->screen_base, s1dfb->disp_save,
+ info->fix.smem_len);
+ kfree(s1dfb->disp_save); /* XXX kmalloc()'d when? */
+ }
+
+ if ((s1dfb->display & 0x01) != 0)
+ lcd_enable(s1dfb, 1);
+ if ((s1dfb->display & 0x02) != 0)
+ crt_enable(s1dfb, 1);
+
+ if (pdata && pdata->platform_resume_video)
+ return pdata->platform_resume_video();
+ else
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct device_driver s1d13xxxfb_driver = {
+ .name = S1D_DEVICENAME,
+ .bus = &platform_bus_type,
+ .probe = s1d13xxxfb_probe,
+ .remove = s1d13xxxfb_remove,
+#ifdef CONFIG_PM
+ .suspend = s1d13xxxfb_suspend,
+ .resume = s1d13xxxfb_resume
+#endif
+};
+
+
+static int __init
+s1d13xxxfb_init(void)
+{
+ if (fb_get_options("s1d13xxxfb", NULL))
+ return -ENODEV;
+
+ return driver_register(&s1d13xxxfb_driver);
+}
+
+
+static void __exit
+s1d13xxxfb_exit(void)
+{
+ driver_unregister(&s1d13xxxfb_driver);
+}
+
+module_init(s1d13xxxfb_init);
+module_exit(s1d13xxxfb_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Framebuffer driver for S1D13xxx devices");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>, Thibaut VARENE <varenet@parisc-linux.org>");
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 33bedf94247ec3..4f8043a71f21d1 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1507,8 +1507,7 @@ static int __init sa1100fb_probe(struct device *dev)
failed:
dev_set_drvdata(dev, NULL);
- if (fbi)
- kfree(fbi);
+ kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
return ret;
}
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 301cef041a4e02..e1c9c946be2dc2 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1883,8 +1883,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
info->fbops = &savagefb_ops;
info->flags = FBINFO_DEFAULT |
FBINFO_HWACCEL_YPAN |
- FBINFO_HWACCEL_XPAN |
- FBINFO_MISC_MODESWITCHLATE;
+ FBINFO_HWACCEL_XPAN;
info->pseudo_palette = par->pseudo_palette;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 96a0d60e12ab8a..b773c98f6513d1 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -5640,7 +5640,7 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
/* Unmap */
iounmap(ivideo->video_vbase);
iounmap(ivideo->mmio_vbase);
- if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+ vfree(ivideo->bios_abase);
/* Release mem regions */
release_mem_region(ivideo->video_base, ivideo->video_size);
@@ -5695,7 +5695,7 @@ SISINITSTATIC int __init sisfb_init(void)
sisfb_setup(options);
#endif
#endif
- return(pci_module_init(&sisfb_driver));
+ return(pci_register_driver(&sisfb_driver));
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index aa455152235874..663d53657fa4cf 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1575,7 +1575,7 @@ static int __devinit sstfb_init(void)
return -ENODEV;
sstfb_setup(option);
#endif
- return pci_module_init(&sstfb_driver);
+ return pci_register_driver(&sstfb_driver);
}
#ifdef MODULE
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ded8cc87dfc431..c34ba39b6f7e7c 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1350,7 +1350,7 @@ static int __init tdfxfb_init(void)
tdfxfb_setup(option);
#endif
- return pci_module_init(&tdfxfb_driver);
+ return pci_register_driver(&tdfxfb_driver);
}
static void __exit tdfxfb_exit(void)
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 075c66de9af0e5..3099630d0c3d0b 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1540,7 +1540,7 @@ tgafb_init(void)
return -ENODEV;
tgafb_setup(option);
#endif
- return pci_module_init(&tgafb_driver);
+ return pci_register_driver(&tgafb_driver);
}
/*
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 2ad715a6cb2cab..da8004e5d03de6 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1163,7 +1163,7 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
fb_info.var = default_var;
fb_info.device = &dev->dev;
if (register_framebuffer(&fb_info) < 0) {
- output("Could not register Trident framebuffer\n");
+ printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
return -EINVAL;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
@@ -1264,7 +1264,7 @@ static int __init tridentfb_init(void)
tridentfb_setup(option);
#endif
output("Trident framebuffer %s initializing\n", VERSION);
- return pci_module_init(&tridentfb_pci_driver);
+ return pci_register_driver(&tridentfb_pci_driver);
}
static void __exit tridentfb_exit(void)
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 4e508df8212ebf..b46454c55c91b0 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -874,7 +874,7 @@ static int vga16fb_blank(int blank, struct fb_info *info)
return 0;
}
-void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
u32 dx = rect->dx, width = rect->width;
char oldindex = getindex();
@@ -928,7 +928,7 @@ void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
setindex(oldindex);
}
-void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
int x, x2, y2, vxres, vyres, width, height, line_ofs;
char __iomem *dst;
@@ -1003,7 +1003,7 @@ void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
}
}
-void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
char oldindex = getindex();
char oldmode = setmode(0x41);
@@ -1058,7 +1058,7 @@ void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
setindex(oldindex);
}
-void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
int x, x2, y2, old_dx, old_dy, vxres, vyres;
@@ -1166,7 +1166,7 @@ static unsigned int transl_l[] =
#endif
#endif
-void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
{
char oldindex = getindex();
char oldmode = setmode(0x40);
@@ -1197,7 +1197,7 @@ void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
setindex(oldindex);
}
-void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
+static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
{
char __iomem *where = info->screen_base + (image->dx/8) +
image->dy * info->fix.line_length;
@@ -1261,7 +1261,7 @@ void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
}
}
-void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
+static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
{
/*
* Draw logo
@@ -1306,7 +1306,7 @@ void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
}
}
-void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
+static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
if (image->depth == 1)
vga_imageblit_expand(info, image);
@@ -1329,7 +1329,8 @@ static struct fb_ops vga16fb_ops = {
.fb_cursor = soft_cursor,
};
-int vga16fb_setup(char *options)
+#ifndef MODULE
+static int vga16fb_setup(char *options)
{
char *this_opt;
@@ -1341,8 +1342,9 @@ int vga16fb_setup(char *options)
}
return 0;
}
+#endif
-int __init vga16fb_init(void)
+static int __init vga16fb_init(void)
{
int i;
int ret;
@@ -1427,9 +1429,7 @@ static void __exit vga16fb_exit(void)
/* XXX unshare VGA regions */
}
-#ifdef MODULE
MODULE_LICENSE("GPL");
-#endif
module_init(vga16fb_init);
module_exit(vga16fb_exit);
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 8c4de816297208..057e154c8858d2 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -537,10 +537,8 @@ static void w100fb_clear_buffer(void)
{
int i;
for (i = 0; i < W100_BUF_NUM; i++) {
- if (gSaveImagePtr[i] != NULL) {
- kfree(gSaveImagePtr[i]);
- gSaveImagePtr[i] = NULL;
- }
+ kfree(gSaveImagePtr[i]);
+ gSaveImagePtr[i] = NULL;
}
}
diff --git a/fs/buffer.c b/fs/buffer.c
index f847c686dcaa47..f961605a904b1c 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -878,7 +878,7 @@ int __set_page_dirty_buffers(struct page *page)
if (!TestSetPageDirty(page)) {
write_lock_irq(&mapping->tree_lock);
if (page->mapping) { /* Race with truncate? */
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
inc_page_state(nr_dirty);
radix_tree_tag_set(&mapping->page_tree,
page_index(page),
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 6d0e70efd39905..d6efb36cab2a7d 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -315,7 +315,7 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
struct backing_dev_info *bdi = mapping->backing_dev_info;
long pages_skipped;
- if (bdi->memory_backed) {
+ if (!bdi_cap_writeback_dirty(bdi)) {
list_move(&inode->i_list, &sb->s_dirty);
if (sb == blockdev_superblock) {
/*
@@ -566,7 +566,7 @@ int write_inode_now(struct inode *inode, int sync)
.sync_mode = WB_SYNC_ALL,
};
- if (inode->i_mapping->backing_dev_info->memory_backed)
+ if (!mapping_cap_writeback_dirty(inode->i_mapping))
return 0;
might_sleep();
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index cfb9801f6ccffb..a88ad292485110 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -806,15 +806,21 @@ int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd)
char *name;
int r = 0, w = 0, x = 0, err;
- if(desired & MAY_READ) r = 1;
- if(desired & MAY_WRITE) w = 1;
- if(desired & MAY_EXEC) x = 1;
+ if (desired & MAY_READ) r = 1;
+ if (desired & MAY_WRITE) w = 1;
+ if (desired & MAY_EXEC) x = 1;
name = inode_name(ino, 0);
- if(name == NULL) return(-ENOMEM);
- err = access_file(name, r, w, x);
+ if (name == NULL) return(-ENOMEM);
+
+ if (S_ISCHR(ino->i_mode) || S_ISBLK(ino->i_mode) ||
+ S_ISFIFO(ino->i_mode) || S_ISSOCK(ino->i_mode))
+ err = 0;
+ else
+ err = access_file(name, r, w, x);
kfree(name);
- if(!err) err = generic_permission(ino, desired, NULL);
- return(err);
+ if(!err)
+ err = generic_permission(ino, desired, NULL);
+ return err;
}
int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7a006cc6e1c242..2af3338f891bb1 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -40,7 +40,7 @@ static struct inode_operations hugetlbfs_inode_operations;
static struct backing_dev_info hugetlbfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
int sysctl_hugetlb_shm_group;
diff --git a/fs/inode.c b/fs/inode.c
index ff654a26833128..af8fd78d2099a0 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -118,7 +118,6 @@ static struct inode *alloc_inode(struct super_block *sb)
inode->i_blkbits = sb->s_blocksize_bits;
inode->i_flags = 0;
atomic_set(&inode->i_count, 1);
- inode->i_sock = 0;
inode->i_op = &empty_iops;
inode->i_fop = &empty_fops;
inode->i_nlink = 1;
@@ -1098,15 +1097,16 @@ static inline void iput_final(struct inode *inode)
* @inode: inode to put
*
* Puts an inode, dropping its usage count. If the inode use count hits
- * zero the inode is also then freed and may be destroyed.
+ * zero, the inode is then freed and may also be destroyed.
+ *
+ * Consequently, iput() can sleep.
*/
void iput(struct inode *inode)
{
if (inode) {
struct super_operations *op = inode->i_sb->s_op;
- if (inode->i_state == I_CLEAR)
- BUG();
+ BUG_ON(inode->i_state == I_CLEAR);
if (op && op->put_inode)
op->put_inode(inode);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index cb094d03287cf1..73f96acd5d378b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1472,8 +1472,8 @@ void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
if (cache->cred)
put_rpccred(cache->cred);
cache->cred = get_rpccred(set->cred);
- NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
}
+ NFS_FLAGS(inode) &= ~NFS_INO_INVALID_ACCESS;
cache->jiffies = set->jiffies;
cache->mask = set->mask;
}
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 172393942ac0c9..11ebf6c4aa54c5 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -49,12 +49,16 @@
/* mode bit translations: */
-#define NFS4_READ_MODE (NFS4_ACE_READ_DATA | NFS4_ACE_READ_NAMED_ATTRS)
-#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_WRITE_NAMED_ATTRS | NFS4_ACE_APPEND_DATA)
+#define NFS4_READ_MODE (NFS4_ACE_READ_DATA)
+#define NFS4_WRITE_MODE (NFS4_ACE_WRITE_DATA | NFS4_ACE_APPEND_DATA)
#define NFS4_EXECUTE_MODE NFS4_ACE_EXECUTE
#define NFS4_ANYONE_MODE (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL | NFS4_ACE_SYNCHRONIZE)
#define NFS4_OWNER_MODE (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)
+/* We don't support these bits; insist they be neither allowed nor denied */
+#define NFS4_MASK_UNSUPP (NFS4_ACE_DELETE | NFS4_ACE_WRITE_OWNER \
+ | NFS4_ACE_READ_NAMED_ATTRS | NFS4_ACE_WRITE_NAMED_ATTRS)
+
/* flags used to simulate posix default ACLs */
#define NFS4_INHERITANCE_FLAGS (NFS4_ACE_FILE_INHERIT_ACE \
| NFS4_ACE_DIRECTORY_INHERIT_ACE | NFS4_ACE_INHERIT_ONLY_ACE)
@@ -83,12 +87,15 @@ mask_from_posix(unsigned short perm, unsigned int flags)
static u32
deny_mask(u32 allow_mask, unsigned int flags)
{
- u32 ret = ~allow_mask & ~NFS4_ACE_DELETE;
+ u32 ret = ~allow_mask & ~NFS4_MASK_UNSUPP;
if (!(flags & NFS4_ACL_DIR))
ret &= ~NFS4_ACE_DELETE_CHILD;
return ret;
}
+/* XXX: modify functions to return NFS errors; they're only ever
+ * used by nfs code, after all.... */
+
static int
mode_from_nfs4(u32 perm, unsigned short *mode, unsigned int flags)
{
@@ -940,35 +947,8 @@ match_who(struct nfs4_ace *ace, uid_t owner, gid_t group, uid_t who)
}
}
-/* 0 = granted, -EACCES = denied; mask is an nfsv4 mask, not mode bits */
-int
-nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
- uid_t who, u32 mask)
-{
- struct nfs4_ace *ace;
- u32 allowed = 0;
-
- list_for_each_entry(ace, &acl->ace_head, l_ace) {
- if (!match_who(ace, group, owner, who))
- continue;
- switch (ace->type) {
- case NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE:
- allowed |= ace->access_mask;
- if ((allowed & mask) == mask)
- return 0;
- break;
- case NFS4_ACE_ACCESS_DENIED_ACE_TYPE:
- if (ace->access_mask & mask)
- return -EACCES;
- break;
- }
- }
- return -EACCES;
-}
-
EXPORT_SYMBOL(nfs4_acl_new);
EXPORT_SYMBOL(nfs4_acl_free);
EXPORT_SYMBOL(nfs4_acl_add_ace);
EXPORT_SYMBOL(nfs4_acl_get_whotype);
EXPORT_SYMBOL(nfs4_acl_write_who);
-EXPORT_SYMBOL(nfs4_acl_permission);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 271c231e7ba440..c70de9c2af7465 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -541,7 +541,7 @@ out:
atomic_set(&clp->cl_callback.cb_set, 0);
/* Success or failure, now we're either waiting for lease expiration
* or deleg_return. */
- nfs4_put_delegation(dp);
dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
+ nfs4_put_delegation(dp);
return;
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 6146c284da0f15..e8158741e8b5c0 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -197,30 +197,40 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
}
if (status)
goto out;
- if (open->op_claim_type == NFS4_OPEN_CLAIM_NULL) {
- /*
- * This block of code will (1) set CURRENT_FH to the file being opened,
- * creating it if necessary, (2) set open->op_cinfo,
- * (3) set open->op_truncate if the file is to be truncated
- * after opening, (4) do permission checking.
- */
- status = do_open_lookup(rqstp, current_fh, open);
- if (status)
+ switch (open->op_claim_type) {
+ case NFS4_OPEN_CLAIM_NULL:
+ /*
+ * (1) set CURRENT_FH to the file being opened,
+ * creating it if necessary, (2) set open->op_cinfo,
+ * (3) set open->op_truncate if the file is to be
+ * truncated after opening, (4) do permission checking.
+ */
+ status = do_open_lookup(rqstp, current_fh, open);
+ if (status)
+ goto out;
+ break;
+ case NFS4_OPEN_CLAIM_PREVIOUS:
+ /*
+ * The CURRENT_FH is already set to the file being
+ * opened. (1) set open->op_cinfo, (2) set
+ * open->op_truncate if the file is to be truncated
+ * after opening, (3) do permission checking.
+ */
+ status = do_open_fhandle(rqstp, current_fh, open);
+ if (status)
+ goto out;
+ break;
+ case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+ case NFS4_OPEN_CLAIM_DELEGATE_PREV:
+ printk("NFSD: unsupported OPEN claim type %d\n",
+ open->op_claim_type);
+ status = nfserr_notsupp;
goto out;
- } else if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) {
- /*
- * The CURRENT_FH is already set to the file being opened. This
- * block of code will (1) set open->op_cinfo, (2) set
- * open->op_truncate if the file is to be truncated after opening,
- * (3) do permission checking.
- */
- status = do_open_fhandle(rqstp, current_fh, open);
- if (status)
+ default:
+ printk("NFSD: Invalid OPEN claim type %d\n",
+ open->op_claim_type);
+ status = nfserr_inval;
goto out;
- } else {
- printk("NFSD: unsupported OPEN claim type\n");
- status = nfserr_inval;
- goto out;
}
/*
* nfsd4_process_open2() does the actual opening of the file. If
@@ -573,8 +583,8 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh,
- &setattr->sa_stateid,
+ if ((status = nfs4_preprocess_stateid_op(current_fh,
+ &setattr->sa_stateid,
CHECK_FH | WR_STATE, NULL))) {
dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
goto out_unlock;
@@ -609,7 +619,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
return nfserr_inval;
nfs4_lock_state();
- if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
+ if ((status = nfs4_preprocess_stateid_op(current_fh, stateid,
CHECK_FH | WR_STATE, &filp))) {
dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
goto out;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 945328d7c3a2a8..579f7fea796811 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -176,15 +176,11 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
}
}
-/* release_delegation:
- *
- * Remove the associated file_lock first, then remove the delegation.
+/* Remove the associated file_lock first, then remove the delegation.
* lease_modify() is called to remove the FS_LEASE file_lock from
* the i_flock list, eventually calling nfsd's lock_manager
* fl_release_callback.
- *
*/
-
static void
nfs4_close_delegation(struct nfs4_delegation *dp)
{
@@ -201,7 +197,7 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
/* Called under the state lock. */
static void
-release_delegation(struct nfs4_delegation *dp)
+unhash_delegation(struct nfs4_delegation *dp)
{
list_del_init(&dp->dl_del_perfile);
list_del_init(&dp->dl_del_perclnt);
@@ -345,7 +341,7 @@ expire_client(struct nfs4_client *clp)
while (!list_empty(&reaplist)) {
dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
- release_delegation(dp);
+ unhash_delegation(dp);
}
list_del(&clp->cl_idhash);
list_del(&clp->cl_strhash);
@@ -1123,7 +1119,8 @@ release_stateowner(struct nfs4_stateowner *sop)
}
static inline void
-init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open) {
+init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *open) {
+ struct nfs4_stateowner *sop = open->op_stateowner;
unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
INIT_LIST_HEAD(&stp->st_hash);
@@ -1529,20 +1526,19 @@ out:
}
static int
-nfs4_check_open(struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open, struct nfs4_stateid **stpp)
+nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
{
struct nfs4_stateid *local;
int status = nfserr_share_denied;
+ struct nfs4_stateowner *sop = open->op_stateowner;
list_for_each_entry(local, &fp->fi_perfile, st_perfile) {
- /* have we seen this open owner */
- if (local->st_stateowner == sop) {
- *stpp = local;
- continue;
- }
/* ignore lock owners */
if (local->st_stateowner->so_is_open_owner == 0)
continue;
+ /* remember if we have seen this open owner */
+ if (local->st_stateowner == sop)
+ *stpp = local;
/* check for conflicting share reservations */
if (!test_share(local, open))
goto out;
@@ -1575,6 +1571,21 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
return 0;
}
+static inline int
+nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh,
+ struct nfsd4_open *open)
+{
+ struct iattr iattr = {
+ .ia_valid = ATTR_SIZE,
+ .ia_size = 0,
+ };
+ if (!open->op_truncate)
+ return 0;
+ if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
+ return -EINVAL;
+ return nfsd_setattr(rqstp, fh, &iattr, 0, (time_t)0);
+}
+
static int
nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
{
@@ -1587,29 +1598,22 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta
share_access = ~share_access;
share_access &= open->op_share_access;
- /* update the struct file */
- if (share_access & NFS4_SHARE_ACCESS_WRITE) {
- status = get_write_access(inode);
- if (status)
- return nfserrno(status);
- if (open->op_truncate) {
- struct iattr iattr = {
- .ia_valid = ATTR_SIZE,
- .ia_size = 0,
- };
- status = nfsd_setattr(rqstp, cur_fh, &iattr, 0,
- (time_t)0);
- if (status) {
- put_write_access(inode);
- return status;
- }
- }
+ if (!(share_access & NFS4_SHARE_ACCESS_WRITE))
+ return nfsd4_truncate(rqstp, cur_fh, open);
- /* remember the open */
- filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
- set_bit(open->op_share_access, &stp->st_access_bmap);
- set_bit(open->op_share_deny, &stp->st_deny_bmap);
+ status = get_write_access(inode);
+ if (status)
+ return nfserrno(status);
+ status = nfsd4_truncate(rqstp, cur_fh, open);
+ if (status) {
+ put_write_access(inode);
+ return status;
}
+ /* remember the open */
+ filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
+ set_bit(open->op_share_access, &stp->st_access_bmap);
+ set_bit(open->op_share_deny, &stp->st_deny_bmap);
+
return nfs_ok;
}
@@ -1694,7 +1698,6 @@ out:
int
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
{
- struct nfs4_stateowner *sop = open->op_stateowner;
struct nfs4_file *fp = NULL;
struct inode *ino = current_fh->fh_dentry->d_inode;
struct nfs4_stateid *stp = NULL;
@@ -1710,7 +1713,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
*/
fp = find_file(ino);
if (fp) {
- if ((status = nfs4_check_open(fp, sop, open, &stp)))
+ if ((status = nfs4_check_open(fp, open, &stp)))
goto out;
} else {
status = nfserr_resource;
@@ -1737,18 +1740,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
flags = MAY_READ;
if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags)))
goto out;
- init_stateid(stp, fp, sop, open);
- if (open->op_truncate) {
- struct iattr iattr = {
- .ia_valid = ATTR_SIZE,
- .ia_size = 0,
- };
- status = nfsd_setattr(rqstp, current_fh, &iattr, 0,
- (time_t)0);
- if (status) {
- release_stateid(stp, OPEN_STATE);
- goto out;
- }
+ init_stateid(stp, fp, open);
+ status = nfsd4_truncate(rqstp, current_fh, open);
+ if (status) {
+ release_stateid(stp, OPEN_STATE);
+ goto out;
}
}
memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
@@ -1859,7 +1855,7 @@ nfs4_laundromat(void)
list_for_each_safe(pos, next, &reaplist) {
dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
- release_delegation(dp);
+ unhash_delegation(dp);
}
test_val = NFSD_LEASE_TIME;
list_for_each_safe(pos, next, &close_lru) {
@@ -1929,7 +1925,8 @@ static inline int
access_permit_read(unsigned long access_bmap)
{
return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
- test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
+ test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap) ||
+ test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap);
}
static inline int
@@ -2063,7 +2060,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
goto out;
renew_client(dp->dl_client);
if (flags & DELEG_RET)
- release_delegation(dp);
+ unhash_delegation(dp);
if (filpp)
*filpp = dp->dl_vfs_file;
}
@@ -3238,7 +3235,7 @@ __nfs4_state_shutdown(void)
list_for_each_safe(pos, next, &reaplist) {
dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
- release_delegation(dp);
+ unhash_delegation(dp);
}
release_all_files();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f5e1833094dbce..36a058a112d57e 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1331,7 +1331,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_ACL) {
if (status == -EOPNOTSUPP)
bmval0 &= ~FATTR4_WORD0_ACL;
- else if (status != 0)
+ else if (status == -EINVAL) {
+ status = nfserr_attrnotsupp;
+ goto out;
+ } else if (status != 0)
goto out_nfserr;
}
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 0fc725c3bd45c0..e3e9d217236e46 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -393,7 +393,7 @@ set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
}
out:
kfree(buf);
- return (error);
+ return error;
}
int
@@ -417,7 +417,10 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
flags = NFS4_ACL_DIR;
error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
- if (error < 0)
+ if (error == -EINVAL) {
+ error = nfserr_attrnotsupp;
+ goto out;
+ } else if (error < 0)
goto out_nfserr;
if (pacl) {
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 97a7a8f30eb4e8..0a88917605aee6 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -45,7 +45,9 @@ static struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK |
+ BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
+ BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
};
struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 97dc6db0870ca8..aff7b2dfa8eed3 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -23,7 +23,7 @@ static struct address_space_operations sysfs_aops = {
static struct backing_dev_info sysfs_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
struct inode * sysfs_new_inode(mode_t mode)
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 6701c11b406b3f..2b41e47b7d8094 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -64,7 +64,7 @@
/* Version string */
-#define ACPI_CA_VERSION 0x20050211
+#define ACPI_CA_VERSION 0x20050309
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
@@ -198,7 +198,7 @@
/* Number of strings associated with the _OSI reserved method */
-#define ACPI_NUM_OSI_STRINGS 9
+#define ACPI_NUM_OSI_STRINGS 10
/******************************************************************************
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index 6a5da01e46fcde..26d907eae6fe3b 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -75,6 +75,11 @@ extern const char *acpi_gbl_SHRdecode[2];
extern const char *acpi_gbl_TYPdecode[4];
extern const char *acpi_gbl_BMdecode[2];
extern const char *acpi_gbl_SIZdecode[4];
+extern const char *acpi_gbl_TTPdecode[2];
+extern const char *acpi_gbl_MTPdecode[4];
+extern const char *acpi_gbl_TRSdecode[2];
+
+
extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES];
extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES];
extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES];
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index 4efbb8d7e704b7..237d63433581cf 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -374,6 +374,16 @@ acpi_ds_create_node (
/* dsutils - Parser/Interpreter interface utility routines */
+void
+acpi_ds_clear_implicit_return (
+ struct acpi_walk_state *walk_state);
+
+u8
+acpi_ds_do_implicit_return (
+ union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference);
+
u8
acpi_ds_is_result_used (
union acpi_parse_object *op,
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index 78395916e4cfbf..c5301f5ffaf4fd 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -617,7 +617,6 @@ acpi_ex_store_object_to_object (
acpi_status
acpi_ex_store_buffer_to_buffer (
- acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index f2b96f6be45b5b..01d3b4bc0c857a 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -774,6 +774,7 @@ struct acpi_bit_register_info
#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200
#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_WAKE_STATUS 0x8000
#define ACPI_BITMASK_ALL_FIXED_STATUS (ACPI_BITMASK_TIMER_STATUS | \
@@ -789,6 +790,7 @@ struct acpi_bit_register_info
#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200
#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_SCI_ENABLE 0x0001
#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002
@@ -807,6 +809,7 @@ struct acpi_bit_register_info
#define ACPI_BITPOSITION_POWER_BUTTON_STATUS 0x08
#define ACPI_BITPOSITION_SLEEP_BUTTON_STATUS 0x09
#define ACPI_BITPOSITION_RT_CLOCK_STATUS 0x0A
+#define ACPI_BITPOSITION_PCIEXP_WAKE_STATUS 0x0E /* ACPI 3.0 */
#define ACPI_BITPOSITION_WAKE_STATUS 0x0F
#define ACPI_BITPOSITION_TIMER_ENABLE 0x00
@@ -814,6 +817,7 @@ struct acpi_bit_register_info
#define ACPI_BITPOSITION_POWER_BUTTON_ENABLE 0x08
#define ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE 0x09
#define ACPI_BITPOSITION_RT_CLOCK_ENABLE 0x0A
+#define ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE 0x0E /* ACPI 3.0 */
#define ACPI_BITPOSITION_SCI_ENABLE 0x00
#define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index b4479061b8f905..c627bc408a6b11 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -328,7 +328,6 @@ int acpi_bus_receive_event (struct acpi_bus_event *event);
int acpi_bus_register_driver (struct acpi_driver *driver);
int acpi_bus_unregister_driver (struct acpi_driver *driver);
int acpi_bus_scan (struct acpi_device *start);
-int acpi_bus_trim(struct acpi_device *start, int rmdevice);
int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
acpi_handle handle, int type);
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 0c964592a2c34b..c62e92ec43b289 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -56,7 +56,8 @@
/* ACPI PCI Interrupt Link (pci_link.c) */
int acpi_irq_penalty_init (void);
-int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
+int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level,
+ int *active_high_low, char **name);
/* ACPI PCI Interrupt Routing (pci_irq.c) */
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index 6b2284c9e8949f..c97843f6bcbc23 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -94,6 +94,7 @@ struct acpi_walk_state
union acpi_generic_state *control_state; /* List of control states (nested IFs) */
struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */
+ union acpi_operand_object *implicit_return_obj;
struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
struct acpi_namespace_node *method_call_node; /* Called method Node*/
union acpi_parse_object *method_call_op; /* method_call Op if running a method */
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index f39ed91b5bc885..7eee731112b18f 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -261,6 +261,8 @@ struct madt_local_sapic
u8 local_sapic_eid; /* SAPIC EID */
u8 reserved [3]; /* Reserved - must be zero */
LOCAL_APIC_FLAGS
+ u32 processor_uID; /* Numeric UID - ACPI 3.0 */
+ char processor_uIDstring[1]; /* String UID - ACPI 3.0 */
};
struct madt_interrupt_source
@@ -272,7 +274,7 @@ struct madt_interrupt_source
u8 processor_eid; /* Processor EID */
u8 io_sapic_vector; /* Vector value for PMI interrupts */
u32 interrupt; /* Global system interrupt */
- u32 reserved; /* Reserved - must be zero */
+ u32 flags; /* Interrupt Source Flags */
};
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index ea3ca08d88aa85..e1729c967e052a 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -108,7 +108,7 @@ struct facs_descriptor_rev2
/*
- * ACPI 2.0 Generic Address Structure (GAS)
+ * ACPI 2.0+ Generic Address Structure (GAS)
*/
struct acpi_generic_address
{
@@ -159,7 +159,7 @@ struct acpi_generic_address
u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/
/*
- * ACPI 2.0 Fixed ACPI Description Table (FADT)
+ * ACPI 2.0+ Fixed ACPI Description Table (FADT)
*/
struct fadt_descriptor_rev2
{
@@ -174,17 +174,25 @@ struct fadt_descriptor_rev2
u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
- u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits*/
+ u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits */
u32 dock_cap : 1; /* Supports Docking */
- u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG*/
- u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed. */
- u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices.*/
+ u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG */
+ u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed */
+ u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices */
u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */
- /* Must be executed after writing the SLP_TYPx register. */
- u32 reserved6 : 18; /* Reserved - must be zero */
+ /* must be executed after writing the SLP_TYPx register */
+ /* ACPI 3.0 flag bits */
+
+ u32 pci_exp_wak : 1; /* System supports PCIEXP_WAKE (STS/EN) bits */
+ u32 use_platform_clock : 1; /* OSPM should use platform-provided timer */
+ u32 S4rtc_sts_valid : 1; /* Contents of RTC_STS valid after S4 wake */
+ u32 remote_power_on_capable : 1; /* System is compatible with remote power on */
+ u32 force_apic_cluster_model : 1; /* All local APICs must use cluster model */
+ u32 force_apic_physical_destination_mode : 1; /* all local x_aPICs must use physical dest mode */
+ u32 reserved6 : 12;/* Reserved - must be zero */
struct acpi_generic_address reset_register; /* Reset register address in GAS format */
- u8 reset_value; /* Value to write to the reset_register port to reset the system. */
+ u8 reset_value; /* Value to write to the reset_register port to reset the system */
u8 reserved7[3]; /* These three bytes must be zero */
u64 xfirmware_ctrl; /* 64-bit physical address of FACS */
u64 Xdsdt; /* 64-bit physical address of DSDT */
@@ -199,7 +207,7 @@ struct fadt_descriptor_rev2
};
-/* "Downrevved" ACPI 2.0 FADT descriptor */
+/* "Down-revved" ACPI 2.0 FADT descriptor */
struct fadt_descriptor_rev2_minus
{
@@ -213,7 +221,7 @@ struct fadt_descriptor_rev2_minus
};
-/* Embedded Controller */
+/* ECDT - Embedded Controller Boot Resources Table */
struct ec_boot_resources
{
@@ -226,6 +234,55 @@ struct ec_boot_resources
};
+/* SRAT - System Resource Affinity Table */
+
+struct static_resource_alloc
+{
+ u8 type;
+ u8 length;
+ u8 proximity_domain_lo;
+ u8 apic_id;
+ u32 enabled :1;
+ u32 reserved3 :31;
+ u8 local_sapic_eid;
+ u8 proximity_domain_hi[3];
+ u32 reserved4;
+};
+
+struct memory_affinity
+{
+ u8 type;
+ u8 length;
+ u32 proximity_domain;
+ u16 reserved3;
+ u64 base_address;
+ u64 address_length;
+ u32 reserved4;
+ u32 enabled :1;
+ u32 hot_pluggable :1;
+ u32 non_volatile :1;
+ u32 reserved5 :29;
+ u64 reserved6;
+};
+
+struct system_resource_affinity
+{
+ ACPI_TABLE_HEADER_DEF
+ u32 reserved1; /* Must be value '1' */
+ u64 reserved2;
+};
+
+
+/* SLIT - System Locality Distance Information Table */
+
+struct system_locality_info
+{
+ ACPI_TABLE_HEADER_DEF
+ u64 locality_count;
+ u8 entry[1][1];
+};
+
+
#pragma pack()
#endif /* __ACTBL2_H__ */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 51cb780c241e9c..7acb550af3eb9f 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -653,24 +653,26 @@ typedef u8 acpi_adr_space_type;
#define ACPI_BITREG_SLEEP_BUTTON_STATUS 0x04
#define ACPI_BITREG_RT_CLOCK_STATUS 0x05
#define ACPI_BITREG_WAKE_STATUS 0x06
-
-#define ACPI_BITREG_TIMER_ENABLE 0x07
-#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x08
-#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x09
-#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0A
-#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0B
-#define ACPI_BITREG_WAKE_ENABLE 0x0C
-
-#define ACPI_BITREG_SCI_ENABLE 0x0D
-#define ACPI_BITREG_BUS_MASTER_RLD 0x0E
-#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x0F
-#define ACPI_BITREG_SLEEP_TYPE_A 0x10
-#define ACPI_BITREG_SLEEP_TYPE_B 0x11
-#define ACPI_BITREG_SLEEP_ENABLE 0x12
-
-#define ACPI_BITREG_ARB_DISABLE 0x13
-
-#define ACPI_BITREG_MAX 0x13
+#define ACPI_BITREG_PCIEXP_WAKE_STATUS 0x07
+
+#define ACPI_BITREG_TIMER_ENABLE 0x08
+#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x09
+#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x0A
+#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0B
+#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0C
+#define ACPI_BITREG_WAKE_ENABLE 0x0D
+#define ACPI_BITREG_PCIEXP_WAKE_DISABLE 0x0E
+
+#define ACPI_BITREG_SCI_ENABLE 0x0F
+#define ACPI_BITREG_BUS_MASTER_RLD 0x10
+#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x11
+#define ACPI_BITREG_SLEEP_TYPE_A 0x12
+#define ACPI_BITREG_SLEEP_TYPE_B 0x13
+#define ACPI_BITREG_SLEEP_ENABLE 0x14
+
+#define ACPI_BITREG_ARB_DISABLE 0x15
+
+#define ACPI_BITREG_MAX 0x15
#define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1
@@ -1206,6 +1208,7 @@ struct acpi_resource_address64
u64 max_address_range;
u64 address_translation_offset;
u64 address_length;
+ u64 type_specific_attributes;
struct acpi_resource_source resource_source;
};
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 5a956b549b1e58..57bf9362335dc4 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -226,6 +226,7 @@
*/
#define ACPI_STRSTR(s1,s2) strstr((s1), (s2))
+#define ACPI_STRCHR(s1,c) strchr((s1), (c))
#ifdef ACPI_FUTURE_USAGE
#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s))
@@ -294,6 +295,7 @@ typedef char *va_list;
#define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2))
+#define ACPI_STRCHR(s1,c) acpi_ut_strchr ((s1), (c))
#ifdef ACPI_FUTURE_USAGE
#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s))
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index d1c8a8b98f6a6e..2f50a5bb0c781d 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -201,7 +201,6 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) {
/* in processor_throttling.c */
int acpi_processor_get_throttling_info (struct acpi_processor *pr);
int acpi_processor_set_throttling (struct acpi_processor *pr, int state);
-int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file);
ssize_t acpi_processor_write_throttling (
struct file *file,
const char __user *buffer,
@@ -217,7 +216,6 @@ int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *dev
/* in processor_thermal.c */
int acpi_processor_get_limit_info (struct acpi_processor *pr);
-int acpi_processor_limit_open_fs(struct inode *inode, struct file *file);
ssize_t acpi_processor_write_limit (
struct file *file,
const char __user *buffer,
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index dc96af6e9caab8..2885972b0855ca 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -151,6 +151,7 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
#define atomic_inc_return(v) (atomic_add_return(1, v))
#define atomic_dec_return(v) (atomic_sub_return(1, v))
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
diff --git a/include/asm-arm/ipc.h b/include/asm-arm/ipc.h
index 2bbbf6335d9c3a..a46e3d9c2a3fc1 100644
--- a/include/asm-arm/ipc.h
+++ b/include/asm-arm/ipc.h
@@ -1,29 +1 @@
-#ifndef __ASMARM_IPC_H
-#define __ASMARM_IPC_H
-
-/*
- * These are used to wrap system calls on ARM.
- *
- * See arch/arm/kernel/sys-arm.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-arm26/ipc.h b/include/asm-arm26/ipc.h
index c330504ba3f4c1..a46e3d9c2a3fc1 100644
--- a/include/asm-arm26/ipc.h
+++ b/include/asm-arm26/ipc.h
@@ -1,28 +1 @@
-#ifndef __ASMARM_IPC_H
-#define __ASMARM_IPC_H
-
-/*
- * These are used to wrap system calls on ARM.
- *
- * See arch/arm/kernel/sys-arm.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-cris/ipc.h b/include/asm-cris/ipc.h
index f086af6fa03ff2..a46e3d9c2a3fc1 100644
--- a/include/asm-cris/ipc.h
+++ b/include/asm-cris/ipc.h
@@ -1,35 +1 @@
-#ifndef __CRIS_IPC_H__
-#define __CRIS_IPC_H__
-
-/*
- * These are used to wrap system calls on CRIS.
- *
- * See arch/cris/kernel/sys_cris.c for ugly details..
- *
- * Same as x86 version.
- *
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-frv/ipc.h b/include/asm-frv/ipc.h
index 2f72065c633773..a46e3d9c2a3fc1 100644
--- a/include/asm-frv/ipc.h
+++ b/include/asm-frv/ipc.h
@@ -1,33 +1 @@
-#ifndef __ASM_IPC_H__
-#define __ASM_IPC_H__
-
-/*
- * These are used to wrap system calls on FR-V
- *
- * See arch/frv/kernel/sys_frv.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
-
+#include <asm-generic/ipc.h>
diff --git a/include/asm-generic/ipc.h b/include/asm-generic/ipc.h
new file mode 100644
index 00000000000000..a40407a165cec6
--- /dev/null
+++ b/include/asm-generic/ipc.h
@@ -0,0 +1,31 @@
+#ifndef _ASM_GENERIC_IPC_H
+#define _ASM_GENERIC_IPC_H
+/*
+ * These are used to wrap system calls.
+ *
+ * See architecture code for ugly details..
+ */
+struct ipc_kludge {
+ struct msgbuf __user *msgp;
+ long msgtyp;
+};
+
+#define SEMOP 1
+#define SEMGET 2
+#define SEMCTL 3
+#define SEMTIMEDOP 4
+#define MSGSND 11
+#define MSGRCV 12
+#define MSGGET 13
+#define MSGCTL 14
+#define SHMAT 21
+#define SHMDT 22
+#define SHMGET 23
+#define SHMCTL 24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC 25
+
+#define IPCCALL(version,op) ((version)<<16 | (op))
+
+#endif /* _ASM_GENERIC_IPC_H */
diff --git a/include/asm-h8300/ipc.h b/include/asm-h8300/ipc.h
index 6219d8a90e552f..a46e3d9c2a3fc1 100644
--- a/include/asm-h8300/ipc.h
+++ b/include/asm-h8300/ipc.h
@@ -1,31 +1 @@
-#ifndef __H8300_IPC_H__
-#define __H8300_IPC_H__
-
-/*
- * These are used to wrap system calls on H8/300.
- *
- * See arch/h8300/kernel/sys_h8300.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index fb8cdcf41d4b5b..11e67811a9901b 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -4,6 +4,8 @@
#include <asm/ldt.h>
#include <asm/segment.h>
+#define CPU_16BIT_STACK_SIZE 1024
+
#ifndef __ASSEMBLY__
#include <linux/preempt.h>
@@ -15,6 +17,8 @@
extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
+DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
+
struct Xgt_desc_struct {
unsigned short size;
unsigned long address __attribute__((packed));
diff --git a/include/asm-i386/ipc.h b/include/asm-i386/ipc.h
index 810a449f8a7e9c..a46e3d9c2a3fc1 100644
--- a/include/asm-i386/ipc.h
+++ b/include/asm-i386/ipc.h
@@ -1,32 +1 @@
-#ifndef __i386_IPC_H__
-#define __i386_IPC_H__
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 8b28beda0e707c..be258b0e5a5fb6 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -146,6 +146,18 @@ static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
: "0" (op), "c"(0));
}
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op), "c" (count));
+}
+
/*
* CPUID functions returning a single datum
*/
diff --git a/include/asm-i386/seccomp.h b/include/asm-i386/seccomp.h
new file mode 100644
index 00000000000000..18da19e89bff29
--- /dev/null
+++ b/include/asm-i386/seccomp.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on i386"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index abe3440a93cebc..bb5ff5b2c02ec2 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -38,7 +38,7 @@
* 24 - APM BIOS support
* 25 - APM BIOS support
*
- * 26 - unused
+ * 26 - ESPFIX small SS
* 27 - unused
* 28 - unused
* 29 - unused
@@ -71,6 +71,9 @@
#define GDT_ENTRY_PNPBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 6)
#define GDT_ENTRY_APMBIOS_BASE (GDT_ENTRY_KERNEL_BASE + 11)
+#define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14)
+#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8)
+
#define GDT_ENTRY_DOUBLEFAULT_TSS 31
/*
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index d6838c9b7bb4ee..c4a227acfeb0a4 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -3,16 +3,14 @@
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 2001-2003 Hewlett-Packard Co
+ * (c) Copyright 2001-2003, 2005 Hewlett-Packard Development Company, L.P.
* David Mosberger-Tang <davidm@hpl.hp.com>
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
*/
#ifndef _ASM_IA64_SMP_H
#define _ASM_IA64_SMP_H
#include <linux/config.h>
-
-#ifdef CONFIG_SMP
-
#include <linux/init.h>
#include <linux/threads.h>
#include <linux/kernel.h>
@@ -24,6 +22,25 @@
#include <asm/processor.h>
#include <asm/ptrace.h>
+static inline unsigned int
+ia64_get_lid (void)
+{
+ union {
+ struct {
+ unsigned long reserved : 16;
+ unsigned long eid : 8;
+ unsigned long id : 8;
+ unsigned long ignored : 32;
+ } f;
+ unsigned long bits;
+ } lid;
+
+ lid.bits = ia64_getreg(_IA64_REG_CR_LID);
+ return lid.f.id << 8 | lid.f.eid;
+}
+
+#ifdef CONFIG_SMP
+
#define XTP_OFFSET 0x1e0008
#define SMP_IRQ_REDIRECTION (1 << 0)
@@ -90,22 +107,7 @@ max_xtp (void)
writeb(0x0f, ipi_base_addr + XTP_OFFSET); /* Set XTP to max */
}
-static inline unsigned int
-hard_smp_processor_id (void)
-{
- union {
- struct {
- unsigned long reserved : 16;
- unsigned long eid : 8;
- unsigned long id : 8;
- unsigned long ignored : 32;
- } f;
- unsigned long bits;
- } lid;
-
- lid.bits = ia64_getreg(_IA64_REG_CR_LID);
- return lid.f.id << 8 | lid.f.eid;
-}
+#define hard_smp_processor_id() ia64_get_lid()
/* Upping and downing of CPUs */
extern int __cpu_disable (void);
@@ -125,7 +127,8 @@ extern void unlock_ipi_calllock(void);
#else
-#define cpu_logical_id(cpuid) 0
+#define cpu_logical_id(i) 0
+#define cpu_physical_id(i) ia64_get_lid()
#endif /* CONFIG_SMP */
#endif /* _ASM_IA64_SMP_H */
diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h
index 3ce60976d474b8..c916bd22767a14 100644
--- a/include/asm-ia64/sn/addrs.h
+++ b/include/asm-ia64/sn/addrs.h
@@ -11,6 +11,7 @@
#include <asm/percpu.h>
#include <asm/sn/types.h>
+#include <asm/sn/arch.h>
#include <asm/sn/pda.h>
/*
@@ -57,9 +58,9 @@
/*
* Define basic shift & mask constants for manipulating NASIDs and AS values.
*/
-#define NASID_BITMASK (pda->nasid_bitmask)
-#define NASID_SHIFT (pda->nasid_shift)
-#define AS_SHIFT (pda->as_shift)
+#define NASID_BITMASK (sn_hub_info->nasid_bitmask)
+#define NASID_SHIFT (sn_hub_info->nasid_shift)
+#define AS_SHIFT (sn_hub_info->as_shift)
#define AS_BITMASK 0x3UL
#define NASID_MASK ((u64)NASID_BITMASK << NASID_SHIFT)
diff --git a/include/asm-ia64/sn/arch.h b/include/asm-ia64/sn/arch.h
index bfc922a0ab7179..7c349f07916a1b 100644
--- a/include/asm-ia64/sn/arch.h
+++ b/include/asm-ia64/sn/arch.h
@@ -12,10 +12,34 @@
#define _ASM_IA64_SN_ARCH_H
#include <asm/types.h>
+#include <asm/percpu.h>
#include <asm/sn/types.h>
#include <asm/sn/sn_cpuid.h>
/*
+ * The following defines attributes of the HUB chip. These attributes are
+ * frequently referenced. They are kept in the per-cpu data areas of each cpu.
+ * They are kept together in a struct to minimize cache misses.
+ */
+struct sn_hub_info_s {
+ u8 shub2;
+ u8 nasid_shift;
+ u8 as_shift;
+ u8 shub_1_1_found;
+ u16 nasid_bitmask;
+};
+DECLARE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
+#define sn_hub_info (&__get_cpu_var(__sn_hub_info))
+#define is_shub2() (sn_hub_info->shub2)
+#define is_shub1() (sn_hub_info->shub2 == 0)
+
+/*
+ * Use this macro to test if shub 1.1 wars should be enabled
+ */
+#define enable_shub_wars_1_1() (sn_hub_info->shub_1_1_found)
+
+
+/*
* This is the maximum number of nodes that can be part of a kernel.
* Effectively, it's the maximum number of compact node ids (cnodeid_t).
* This is not necessarily the same as MAX_NASIDS.
diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h
index 6465e8ab2bccd3..e940d3647c8043 100644
--- a/include/asm-ia64/sn/pda.h
+++ b/include/asm-ia64/sn/pda.h
@@ -37,11 +37,6 @@ typedef struct pda_s {
* Support for SN LEDs
*/
volatile short *led_address;
- u16 nasid_bitmask;
- u8 shub2;
- u8 nasid_shift;
- u8 as_shift;
- u8 shub_1_1_found;
u8 led_state;
u8 hb_state; /* supports blinking heartbeat leds */
unsigned int hb_count;
@@ -53,8 +48,6 @@ typedef struct pda_s {
unsigned long pio_write_status_val;
volatile unsigned long *pio_shub_war_cam_addr;
- struct bteinfo_s *cpu_bte_if[BTES_PER_NODE]; /* cpu interface order */
-
unsigned long sn_soft_irr[4];
unsigned long sn_in_service_ivecs[4];
short cnodeid_to_nasid_table[MAX_NUMNODES];
@@ -84,12 +77,4 @@ DECLARE_PER_CPU(struct pda_s, pda_percpu);
#define pdacpu(cpu) (&per_cpu(pda_percpu, cpu))
-/*
- * Use this macro to test if shub 1.1 wars should be enabled
- */
-#define enable_shub_wars_1_1() (pda->shub_1_1_found)
-
-#define is_shub2() (pda->shub2)
-#define is_shub1() (pda->shub2 == 0)
-
#endif /* _ASM_IA64_SN_PDA_H */
diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
index 749f45042cdcc1..685435af170d8d 100644
--- a/include/asm-ia64/sn/sn_cpuid.h
+++ b/include/asm-ia64/sn/sn_cpuid.h
@@ -135,9 +135,10 @@ extern int nasid_slice_to_cpuid(int, int);
#define nasid_to_cnodeid(nasid) (physical_node_map[nasid])
/*
- * partition_coherence_id - cget the coherence ID of the current partition
+ * partition_coherence_id - get the coherence ID of the current partition
*/
-#define partition_coherence_id() (get_nasid() >> 9)
+extern u8 sn_coherency_id;
+#define partition_coherence_id() (sn_coherency_id)
#endif /* _ASM_IA64_SN_SN_CPUID_H */
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 4ecc05e8ad5772..88c31b53dc0974 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -18,6 +18,7 @@
#include <asm/sn/arch.h>
#include <asm/sn/geo.h>
#include <asm/sn/nodepda.h>
+#include <asm/sn/shub_mmr.h>
// SGI Specific Calls
#define SN_SAL_POD_MODE 0x02000001
@@ -34,7 +35,7 @@
#define SN_SAL_PRINT_ERROR 0x02000012
#define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant
#define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant
-#define SN_SAL_GET_HUB_INFO 0x0200001c
+#define SN_SAL_GET_SN_INFO 0x0200001c
#define SN_SAL_GET_SAPIC_INFO 0x0200001d
#define SN_SAL_CONSOLE_PUTC 0x02000021
#define SN_SAL_CONSOLE_GETC 0x02000022
@@ -935,15 +936,24 @@ ia64_sn_get_sapic_info(int sapicid, int *nasid, int *subnode, int *slice)
/*
* Returns information about the HUB/SHUB.
* In:
- * arg0 - SN_SAL_GET_HUB_INFO
+ * arg0 - SN_SAL_GET_SN_INFO
* arg1 - 0 (other values reserved for future use)
* Out:
- * v0 - shub type (0=shub1, 1=shub2)
- * v1 - masid mask (ex., 0x7ff for 11 bit nasid)
- * v2 - bit position of low nasid bit
+ * v0
+ * [7:0] - shub type (0=shub1, 1=shub2)
+ * [15:8] - Log2 max number of nodes in entire system (includes
+ * C-bricks, I-bricks, etc)
+ * [23:16] - Log2 of nodes per sharing domain
+ * [31:24] - partition ID
+ * [39:32] - coherency_id
+ * [47:40] - regionsize
+ * v1
+ * [15:0] - nasid mask (ex., 0x7ff for 11 bit nasid)
+ * [23:15] - bit position of low nasid bit
*/
static inline u64
-ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3)
+ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift,
+ u8 *systemsize, u8 *sharing_domain_size, u8 *partid, u8 *coher, u8 *reg)
{
struct ia64_sal_retval ret_stuff;
@@ -951,13 +961,22 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3)
ret_stuff.v0 = 0;
ret_stuff.v1 = 0;
ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_HUB_INFO, fc, 0, 0, 0, 0, 0, 0);
+ SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO, fc, 0, 0, 0, 0, 0, 0);
/***** BEGIN HACK - temp til old proms no longer supported ********/
if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
- if (arg1) *arg1 = 0;
- if (arg2) *arg2 = 0x7ff;
- if (arg3) *arg3 = 38;
+ int nasid = get_sapicid() & 0xfff;;
+#define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL
+#define SH_SHUB_ID_NODES_PER_BIT_SHFT 48
+ if (shubtype) *shubtype = 0;
+ if (nasid_bitmask) *nasid_bitmask = 0x7ff;
+ if (nasid_shift) *nasid_shift = 38;
+ if (systemsize) *systemsize = 11;
+ if (sharing_domain_size) *sharing_domain_size = 9;
+ if (partid) *partid = ia64_sn_sysctl_partition_get(nasid);
+ if (coher) *coher = nasid >> 9;
+ if (reg) *reg = (HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_SHUB_ID)) & SH_SHUB_ID_NODES_PER_BIT_MASK) >>
+ SH_SHUB_ID_NODES_PER_BIT_SHFT;
return 0;
}
/***** END HACK *******/
@@ -965,9 +984,14 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3)
if (ret_stuff.status < 0)
return ret_stuff.status;
- if (arg1) *arg1 = ret_stuff.v0;
- if (arg2) *arg2 = ret_stuff.v1;
- if (arg3) *arg3 = ret_stuff.v2;
+ if (shubtype) *shubtype = ret_stuff.v0 & 0xff;
+ if (systemsize) *systemsize = (ret_stuff.v0 >> 8) & 0xff;
+ if (sharing_domain_size) *sharing_domain_size = (ret_stuff.v0 >> 16) & 0xff;
+ if (partid) *partid = (ret_stuff.v0 >> 24) & 0xff;
+ if (coher) *coher = (ret_stuff.v0 >> 32) & 0xff;
+ if (reg) *reg = (ret_stuff.v0 >> 40) & 0xff;
+ if (nasid_bitmask) *nasid_bitmask = (ret_stuff.v1 & 0xffff);
+ if (nasid_shift) *nasid_shift = (ret_stuff.v1 >> 16) & 0xff;
return 0;
}
diff --git a/include/asm-m32r/ipc.h b/include/asm-m32r/ipc.h
index 03aac6644b5873..a46e3d9c2a3fc1 100644
--- a/include/asm-m32r/ipc.h
+++ b/include/asm-m32r/ipc.h
@@ -1,35 +1 @@
-#ifndef __M32R_IPC_H__
-#define __M32R_IPC_H__
-
-/* orig : i386/ipc.h 2.6.0-test3 */
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __M32R_IPC_H__ */
-
+#include <asm-generic/ipc.h>
diff --git a/include/asm-m32r/spinlock.h b/include/asm-m32r/spinlock.h
index ecf80b74d2c112..6608d8371c5084 100644
--- a/include/asm-m32r/spinlock.h
+++ b/include/asm-m32r/spinlock.h
@@ -102,10 +102,8 @@ static inline void _raw_spin_lock(spinlock_t *lock)
unsigned long tmp0, tmp1;
#ifdef CONFIG_DEBUG_SPINLOCK
- __label__ here;
-here:
- if (lock->magic != SPINLOCK_MAGIC) {
- printk("pc: %p\n", &&here);
+ if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
+ printk("pc: %p\n", __builtin_return_address(0));
BUG();
}
#endif
diff --git a/include/asm-m68k/ipc.h b/include/asm-m68k/ipc.h
index 19e9cbe3f26613..a46e3d9c2a3fc1 100644
--- a/include/asm-m68k/ipc.h
+++ b/include/asm-m68k/ipc.h
@@ -1,31 +1 @@
-#ifndef __m68k_IPC_H__
-#define __m68k_IPC_H__
-
-/*
- * These are used to wrap system calls on m68k.
- *
- * See arch/m68k/kernel/sys_m68k.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-m68knommu/ipc.h b/include/asm-m68knommu/ipc.h
index d66c4b21940067..a46e3d9c2a3fc1 100644
--- a/include/asm-m68knommu/ipc.h
+++ b/include/asm-m68knommu/ipc.h
@@ -1 +1 @@
-#include <asm-m68k/ipc.h>
+#include <asm-generic/ipc.h>
diff --git a/include/asm-mips/ipc.h b/include/asm-mips/ipc.h
index 377bbd5ef62fc4..a46e3d9c2a3fc1 100644
--- a/include/asm-mips/ipc.h
+++ b/include/asm-mips/ipc.h
@@ -1,33 +1 @@
-#ifndef _ASM_IPC_H
-#define _ASM_IPC_H
-
-/*
- * These are used to wrap system calls on MIPS.
- *
- * See arch/mips/kernel/sysmips.c for ugly details..
- * FIXME: split up into ordinary syscalls ...
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* _ASM_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index 7dbda12a876d74..42fd1068cf2a41 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -86,7 +86,7 @@
*/
#define CPM_DATAONLY_BASE ((uint)128)
#define CPM_DP_NOSPACE ((uint)0x7fffffff)
-#ifdef CONFIG_8272
+#if defined(CONFIG_8272) || defined(CONFIG_MPC8555)
#define CPM_DATAONLY_SIZE ((uint)(8 * 1024) - CPM_DATAONLY_BASE)
#define CPM_FCC_SPECIAL_BASE ((uint)0x00009000)
#else
diff --git a/include/asm-ppc/ipc.h b/include/asm-ppc/ipc.h
index 512dfe962d8bb8..a46e3d9c2a3fc1 100644
--- a/include/asm-ppc/ipc.h
+++ b/include/asm-ppc/ipc.h
@@ -1,29 +1 @@
-#ifndef __PPC_IPC_H__
-#define __PPC_IPC_H__
-
-/*
- * These are used to wrap system calls on PowerPC.
- *
- * See arch/ppc/kernel/syscalls.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __PPC_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
index 8e77baad0c4a4d..06b86be61ed13e 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -171,7 +171,7 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_IRQS (NR_IPIC_INTS)
-#elif defined(CONFIG_CPM2) && defined(CONFIG_85xx)
+#elif defined(CONFIG_85xx)
/* Now include the board configuration specific associations.
*/
#include <asm/mpc85xx.h>
@@ -186,7 +186,7 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_CPM_INTS 64
#define NR_EPIC_INTS 44
#ifndef NR_8259_INTS
-#define NR_8259_INTS 0
+#define NR_8259_INTS 0
#endif
#define NUM_8259_INTERRUPTS NR_8259_INTS
@@ -196,13 +196,59 @@ static __inline__ int irq_canonicalize(int irq)
#define NR_IRQS (NR_EPIC_INTS + NR_CPM_INTS + NR_8259_INTS)
-/* These values must be zero-based and map 1:1 with the EPIC configuration.
- * They are used throughout the 8560 I/O subsystem to generate
- * interrupt masks, flags, and other control patterns. This is why the
- * current kernel assumption of the 8259 as the base controller is such
- * a pain in the butt.
- */
+/* Internal IRQs on MPC85xx OpenPIC */
+
+#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
+#ifdef CONFIG_CPM2
+#define MPC85xx_OPENPIC_IRQ_OFFSET (CPM_IRQ_OFFSET + NR_CPM_INTS)
+#else
+#define MPC85xx_OPENPIC_IRQ_OFFSET 0
+#endif
+#endif
+/* Not all of these exist on all MPC85xx implementations */
+#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* The 12 external interrupt lines */
+#define MPC85xx_IRQ_EXT0 (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT1 (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT2 (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT3 (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT4 (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT5 (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT6 (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT7 (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT8 (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT9 (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT10 (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT11 (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
+
+/* CPM related interrupts */
#define SIU_INT_ERROR ((uint)0x00+CPM_IRQ_OFFSET)
#define SIU_INT_I2C ((uint)0x01+CPM_IRQ_OFFSET)
#define SIU_INT_SPI ((uint)0x02+CPM_IRQ_OFFSET)
@@ -267,57 +313,62 @@ static __inline__ int irq_canonicalize(int irq)
* (Document errata updates have fixed this...make sure you have up to
* date processor documentation -- Dan).
*/
-#define NR_SIU_INTS 64
-
-#define SIU_INT_ERROR ((uint)0x00)
-#define SIU_INT_I2C ((uint)0x01)
-#define SIU_INT_SPI ((uint)0x02)
-#define SIU_INT_RISC ((uint)0x03)
-#define SIU_INT_SMC1 ((uint)0x04)
-#define SIU_INT_SMC2 ((uint)0x05)
-#define SIU_INT_IDMA1 ((uint)0x06)
-#define SIU_INT_IDMA2 ((uint)0x07)
-#define SIU_INT_IDMA3 ((uint)0x08)
-#define SIU_INT_IDMA4 ((uint)0x09)
-#define SIU_INT_SDMA ((uint)0x0a)
-#define SIU_INT_TIMER1 ((uint)0x0c)
-#define SIU_INT_TIMER2 ((uint)0x0d)
-#define SIU_INT_TIMER3 ((uint)0x0e)
-#define SIU_INT_TIMER4 ((uint)0x0f)
-#define SIU_INT_TMCNT ((uint)0x10)
-#define SIU_INT_PIT ((uint)0x11)
-#define SIU_INT_IRQ1 ((uint)0x13)
-#define SIU_INT_IRQ2 ((uint)0x14)
-#define SIU_INT_IRQ3 ((uint)0x15)
-#define SIU_INT_IRQ4 ((uint)0x16)
-#define SIU_INT_IRQ5 ((uint)0x17)
-#define SIU_INT_IRQ6 ((uint)0x18)
-#define SIU_INT_IRQ7 ((uint)0x19)
-#define SIU_INT_FCC1 ((uint)0x20)
-#define SIU_INT_FCC2 ((uint)0x21)
-#define SIU_INT_FCC3 ((uint)0x22)
-#define SIU_INT_MCC1 ((uint)0x24)
-#define SIU_INT_MCC2 ((uint)0x25)
-#define SIU_INT_SCC1 ((uint)0x28)
-#define SIU_INT_SCC2 ((uint)0x29)
-#define SIU_INT_SCC3 ((uint)0x2a)
-#define SIU_INT_SCC4 ((uint)0x2b)
-#define SIU_INT_PC15 ((uint)0x30)
-#define SIU_INT_PC14 ((uint)0x31)
-#define SIU_INT_PC13 ((uint)0x32)
-#define SIU_INT_PC12 ((uint)0x33)
-#define SIU_INT_PC11 ((uint)0x34)
-#define SIU_INT_PC10 ((uint)0x35)
-#define SIU_INT_PC9 ((uint)0x36)
-#define SIU_INT_PC8 ((uint)0x37)
-#define SIU_INT_PC7 ((uint)0x38)
-#define SIU_INT_PC6 ((uint)0x39)
-#define SIU_INT_PC5 ((uint)0x3a)
-#define SIU_INT_PC4 ((uint)0x3b)
-#define SIU_INT_PC3 ((uint)0x3c)
-#define SIU_INT_PC2 ((uint)0x3d)
-#define SIU_INT_PC1 ((uint)0x3e)
-#define SIU_INT_PC0 ((uint)0x3f)
+
+#ifndef CPM_IRQ_OFFSET
+#define CPM_IRQ_OFFSET 0
+#endif
+
+#define NR_CPM_INTS 64
+
+#define SIU_INT_ERROR ((uint)0x00 + CPM_IRQ_OFFSET)
+#define SIU_INT_I2C ((uint)0x01 + CPM_IRQ_OFFSET)
+#define SIU_INT_SPI ((uint)0x02 + CPM_IRQ_OFFSET)
+#define SIU_INT_RISC ((uint)0x03 + CPM_IRQ_OFFSET)
+#define SIU_INT_SMC1 ((uint)0x04 + CPM_IRQ_OFFSET)
+#define SIU_INT_SMC2 ((uint)0x05 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA1 ((uint)0x06 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA2 ((uint)0x07 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA3 ((uint)0x08 + CPM_IRQ_OFFSET)
+#define SIU_INT_IDMA4 ((uint)0x09 + CPM_IRQ_OFFSET)
+#define SIU_INT_SDMA ((uint)0x0a + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER1 ((uint)0x0c + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER2 ((uint)0x0d + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER3 ((uint)0x0e + CPM_IRQ_OFFSET)
+#define SIU_INT_TIMER4 ((uint)0x0f + CPM_IRQ_OFFSET)
+#define SIU_INT_TMCNT ((uint)0x10 + CPM_IRQ_OFFSET)
+#define SIU_INT_PIT ((uint)0x11 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ2 ((uint)0x14 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ3 ((uint)0x15 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ4 ((uint)0x16 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ5 ((uint)0x17 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ6 ((uint)0x18 + CPM_IRQ_OFFSET)
+#define SIU_INT_IRQ7 ((uint)0x19 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC1 ((uint)0x20 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC2 ((uint)0x21 + CPM_IRQ_OFFSET)
+#define SIU_INT_FCC3 ((uint)0x22 + CPM_IRQ_OFFSET)
+#define SIU_INT_MCC1 ((uint)0x24 + CPM_IRQ_OFFSET)
+#define SIU_INT_MCC2 ((uint)0x25 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC1 ((uint)0x28 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC2 ((uint)0x29 + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC3 ((uint)0x2a + CPM_IRQ_OFFSET)
+#define SIU_INT_SCC4 ((uint)0x2b + CPM_IRQ_OFFSET)
+#define SIU_INT_PC15 ((uint)0x30 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC14 ((uint)0x31 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC13 ((uint)0x32 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC12 ((uint)0x33 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC11 ((uint)0x34 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC10 ((uint)0x35 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC9 ((uint)0x36 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC8 ((uint)0x37 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC7 ((uint)0x38 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC6 ((uint)0x39 + CPM_IRQ_OFFSET)
+#define SIU_INT_PC5 ((uint)0x3a + CPM_IRQ_OFFSET)
+#define SIU_INT_PC4 ((uint)0x3b + CPM_IRQ_OFFSET)
+#define SIU_INT_PC3 ((uint)0x3c + CPM_IRQ_OFFSET)
+#define SIU_INT_PC2 ((uint)0x3d + CPM_IRQ_OFFSET)
+#define SIU_INT_PC1 ((uint)0x3e + CPM_IRQ_OFFSET)
+#define SIU_INT_PC0 ((uint)0x3f + CPM_IRQ_OFFSET)
#endif /* CONFIG_8260 */
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index edda15befa2de5..e5f80c22fbfcfc 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -10,7 +10,7 @@
* Originally written by Dale Farnsworth <dfarnsworth@mvista.com>
* for the 2.4 kernel.
*
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
*
* This file is licensed under the terms of the GNU General Public License
@@ -26,53 +26,73 @@
#include <asm/types.h>
struct pt_regs;
-struct ocp_def;
#endif /* __ASSEMBLY__ */
/* ======================================================================== */
+/* PPC Sys devices definition */
+/* ======================================================================== */
+
+enum ppc_sys_devices {
+ MPC52xx_MSCAN1,
+ MPC52xx_MSCAN2,
+ MPC52xx_SPI,
+ MPC52xx_USB,
+ MPC52xx_BDLC,
+ MPC52xx_PSC1,
+ MPC52xx_PSC2,
+ MPC52xx_PSC3,
+ MPC52xx_PSC4,
+ MPC52xx_PSC5,
+ MPC52xx_PSC6,
+ MPC52xx_FEC,
+ MPC52xx_ATA,
+ MPC52xx_I2C1,
+ MPC52xx_I2C2,
+};
+
+
+/* ======================================================================== */
/* Main registers/struct addresses */
/* ======================================================================== */
-/* Theses are PHYSICAL addresses ! */
-/* TODO : There should be no static mapping, but it's not yet the case, so */
-/* we require a 1:1 mapping */
+/* MBAR position */
#define MPC52xx_MBAR 0xf0000000 /* Phys address */
-#define MPC52xx_MBAR_SIZE 0x00010000
#define MPC52xx_MBAR_VIRT 0xf0000000 /* Virt address */
+#define MPC52xx_MBAR_SIZE 0x00010000
-#define MPC52xx_MMAP_CTL (MPC52xx_MBAR + 0x0000)
-#define MPC52xx_SDRAM (MPC52xx_MBAR + 0x0100)
-#define MPC52xx_CDM (MPC52xx_MBAR + 0x0200)
-#define MPC52xx_SFTRST (MPC52xx_MBAR + 0x0220)
-#define MPC52xx_SFTRST_BIT 0x01000000
-#define MPC52xx_INTR (MPC52xx_MBAR + 0x0500)
-#define MPC52xx_GPTx(x) (MPC52xx_MBAR + 0x0600 + ((x)<<4))
-#define MPC52xx_RTC (MPC52xx_MBAR + 0x0800)
-#define MPC52xx_MSCAN1 (MPC52xx_MBAR + 0x0900)
-#define MPC52xx_MSCAN2 (MPC52xx_MBAR + 0x0980)
-#define MPC52xx_GPIO (MPC52xx_MBAR + 0x0b00)
-#define MPC52xx_GPIO_WKUP (MPC52xx_MBAR + 0x0c00)
-#define MPC52xx_PCI (MPC52xx_MBAR + 0x0d00)
-#define MPC52xx_USB_OHCI (MPC52xx_MBAR + 0x1000)
-#define MPC52xx_SDMA (MPC52xx_MBAR + 0x1200)
-#define MPC52xx_XLB (MPC52xx_MBAR + 0x1f00)
-#define MPC52xx_PSCx(x) (MPC52xx_MBAR + 0x2000 + ((x)<<9))
-#define MPC52xx_PSC1 (MPC52xx_MBAR + 0x2000)
-#define MPC52xx_PSC2 (MPC52xx_MBAR + 0x2200)
-#define MPC52xx_PSC3 (MPC52xx_MBAR + 0x2400)
-#define MPC52xx_PSC4 (MPC52xx_MBAR + 0x2600)
-#define MPC52xx_PSC5 (MPC52xx_MBAR + 0x2800)
-#define MPC52xx_PSC6 (MPC52xx_MBAR + 0x2C00)
-#define MPC52xx_FEC (MPC52xx_MBAR + 0x3000)
-#define MPC52xx_ATA (MPC52xx_MBAR + 0x3a00)
-#define MPC52xx_I2C1 (MPC52xx_MBAR + 0x3d00)
-#define MPC52xx_I2C_MICR (MPC52xx_MBAR + 0x3d20)
-#define MPC52xx_I2C2 (MPC52xx_MBAR + 0x3d40)
+#define MPC52xx_PA(x) ((phys_addr_t)(MPC52xx_MBAR + (x)))
+#define MPC52xx_VA(x) ((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))
+
+/* Registers zone offset/size */
+#define MPC52xx_MMAP_CTL_OFFSET 0x0000
+#define MPC52xx_MMAP_CTL_SIZE 0x068
+#define MPC52xx_SDRAM_OFFSET 0x0100
+#define MPC52xx_SDRAM_SIZE 0x010
+#define MPC52xx_CDM_OFFSET 0x0200
+#define MPC52xx_CDM_SIZE 0x038
+#define MPC52xx_INTR_OFFSET 0x0500
+#define MPC52xx_INTR_SIZE 0x04c
+#define MPC52xx_GPTx_OFFSET(x) (0x0600 + ((x)<<4))
+#define MPC52xx_GPT_SIZE 0x010
+#define MPC52xx_RTC_OFFSET 0x0800
+#define MPC52xx_RTC_SIZE 0x024
+#define MPC52xx_GPIO_OFFSET 0x0b00
+#define MPC52xx_GPIO_SIZE 0x040
+#define MPC52xx_GPIO_WKUP_OFFSET 0x0c00
+#define MPC52xx_GPIO_WKUP_SIZE 0x028
+#define MPC52xx_PCI_OFFSET 0x0d00
+#define MPC52xx_PCI_SIZE 0x100
+#define MPC52xx_SDMA_OFFSET 0x1200
+#define MPC52xx_SDMA_SIZE 0x100
+#define MPC52xx_XLB_OFFSET 0x1f00
+#define MPC52xx_XLB_SIZE 0x100
+#define MPC52xx_PSCx_OFFSET(x) (((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
+#define MPC52xx_PSC_SIZE 0x0a0
/* SRAM used for SDMA */
-#define MPC52xx_SRAM (MPC52xx_MBAR + 0x8000)
-#define MPC52xx_SRAM_SIZE (16*1024)
+#define MPC52xx_SRAM_OFFSET 0x8000
+#define MPC52xx_SRAM_SIZE 0x4000
/* ======================================================================== */
@@ -119,11 +139,12 @@ struct ocp_def;
#define MPC52xx_SPI_SPIF_IRQ (MPC52xx_PERP_IRQ_BASE + 14)
#define MPC52xx_I2C1_IRQ (MPC52xx_PERP_IRQ_BASE + 15)
#define MPC52xx_I2C2_IRQ (MPC52xx_PERP_IRQ_BASE + 16)
-#define MPC52xx_CAN1_IRQ (MPC52xx_PERP_IRQ_BASE + 17)
-#define MPC52xx_CAN2_IRQ (MPC52xx_PERP_IRQ_BASE + 18)
+#define MPC52xx_MSCAN1_IRQ (MPC52xx_PERP_IRQ_BASE + 17)
+#define MPC52xx_MSCAN2_IRQ (MPC52xx_PERP_IRQ_BASE + 18)
#define MPC52xx_IR_RX_IRQ (MPC52xx_PERP_IRQ_BASE + 19)
#define MPC52xx_IR_TX_IRQ (MPC52xx_PERP_IRQ_BASE + 20)
#define MPC52xx_XLB_ARB_IRQ (MPC52xx_PERP_IRQ_BASE + 21)
+#define MPC52xx_BDLC_IRQ (MPC52xx_PERP_IRQ_BASE + 22)
@@ -163,7 +184,7 @@ struct mpc52xx_mmap_ctl {
u32 cs6_start; /* MMAP_CTRL + 0x58 */
u32 cs6_stop; /* MMAP_CTRL + 0x5c */
u32 cs7_start; /* MMAP_CTRL + 0x60 */
- u32 cs7_stop; /* MMAP_CTRL + 0x60 */
+ u32 cs7_stop; /* MMAP_CTRL + 0x64 */
};
/* SDRAM control */
@@ -209,7 +230,7 @@ struct mpc52xx_sdma {
u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */
- u8 ipr[32]; /* SDMA + 0x3c .. 5b */
+ u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */
u32 cReqSelect; /* SDMA + 0x5c */
u32 task_size0; /* SDMA + 0x60 */
@@ -391,10 +412,20 @@ extern void mpc52xx_halt(void);
extern void mpc52xx_power_off(void);
extern void mpc52xx_progress(char *s, unsigned short hex);
extern void mpc52xx_calibrate_decr(void);
-extern void mpc52xx_add_board_devices(struct ocp_def board_ocp[]);
extern void mpc52xx_find_bridges(void);
+
+ /* Matching of PSC function */
+struct mpc52xx_psc_func {
+ int id;
+ char *func;
+};
+
+extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
+extern struct mpc52xx_psc_func mpc52xx_psc_functions[];
+ /* This array is to be defined in platform file */
+
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 3f9e4237bf6f06..22713e331585a7 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -52,55 +52,6 @@
*/
extern unsigned char __res[];
-/* Internal IRQs on MPC85xx OpenPIC */
-/* Not all of these exist on all MPC85xx implementations */
-
-#ifndef MPC85xx_OPENPIC_IRQ_OFFSET
-#define MPC85xx_OPENPIC_IRQ_OFFSET 64
-#endif
-
-/* The 32 internal sources */
-#define MPC85xx_IRQ_L2CACHE ( 0 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_ECM ( 1 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DDR ( 2 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_LBIU ( 3 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA0 ( 4 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA1 ( 5 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA2 ( 6 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DMA3 ( 7 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PCI1 ( 8 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PCI2 ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_ERROR ( 9 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_BELL (10 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_TX (11 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_IIC1 (27 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_PERFMON (28 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_SEC2 (29 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
-
-/* The 12 external interrupt lines */
-#define MPC85xx_IRQ_EXT0 (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT1 (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT2 (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT3 (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT4 (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT5 (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT6 (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT7 (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT8 (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT9 (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT10 (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT11 (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
-
/* Offset from CCSRBAR */
#define MPC85xx_CPM_OFFSET (0x80000)
#define MPC85xx_CPM_SIZE (0x40000)
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 293e47f1d99a54..24b991c427694d 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -25,6 +25,8 @@
#include <asm/mpc83xx.h>
#elif defined(CONFIG_85xx)
#include <asm/mpc85xx.h>
+#elif defined(CONFIG_PPC_MPC52xx)
+#include <asm/mpc52xx.h>
#else
#error "need definition of ppc_sys_devices"
#endif
diff --git a/include/asm-ppc64/ipc.h b/include/asm-ppc64/ipc.h
index f91bf5b0d092ef..a46e3d9c2a3fc1 100644
--- a/include/asm-ppc64/ipc.h
+++ b/include/asm-ppc64/ipc.h
@@ -1,34 +1 @@
-#ifndef __PPC64_IPC_H__
-#define __PPC64_IPC_H__
-
-/*
- * These are used to wrap system calls on PowerPC.
- *
- * See arch/ppc64/kernel/syscalls.c for ugly details..
- *
- * 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.
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __PPC64_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
index 3da661161cc52d..a6cbca21ac1d70 100644
--- a/include/asm-ppc64/lmb.h
+++ b/include/asm-ppc64/lmb.h
@@ -51,6 +51,7 @@ extern unsigned long __init lmb_alloc_base(unsigned long, unsigned long,
extern unsigned long __init lmb_phys_mem_size(void);
extern unsigned long __init lmb_end_of_DRAM(void);
extern unsigned long __init lmb_abs_to_phys(unsigned long);
+extern void __init lmb_enforce_memory_limit(void);
extern void lmb_dump_all(void);
diff --git a/include/asm-ppc64/seccomp.h b/include/asm-ppc64/seccomp.h
new file mode 100644
index 00000000000000..c130c334bda1c1
--- /dev/null
+++ b/include/asm-ppc64/seccomp.h
@@ -0,0 +1,21 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h> /* already defines TIF_32BIT */
+
+#ifndef TIF_32BIT
+#error "unexpected TIF_32BIT on ppc64"
+#endif
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_read
+#define __NR_seccomp_write_32 __NR_write
+#define __NR_seccomp_exit_32 __NR_exit
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
index d4b978c26d7106..037b5e06083c0c 100644
--- a/include/asm-ppc64/thread_info.h
+++ b/include/asm-ppc64/thread_info.h
@@ -101,6 +101,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
#define TIF_SINGLESTEP 9 /* singlestepping active */
#define TIF_MEMDIE 10
+#define TIF_SECCOMP 11 /* secure computing */
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -113,7 +114,8 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
-#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_USER_WORK_MASK (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
_TIF_NEED_RESCHED)
diff --git a/include/asm-s390/ipc.h b/include/asm-s390/ipc.h
index d6c041e9ca9aa8..a46e3d9c2a3fc1 100644
--- a/include/asm-s390/ipc.h
+++ b/include/asm-s390/ipc.h
@@ -1,40 +1 @@
-/*
- * include/asm-s390/ipc.h
- *
- * S390 version
- *
- * Derived from "include/asm-i386/ipc.h"
- */
-
-#ifndef __s390_IPC_H__
-#define __s390_IPC_H__
-
-/*
- * These are used to wrap system calls on S390.
- *
- * See arch/s390/kernel/sys_s390.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sh/ipc.h b/include/asm-sh/ipc.h
index 6ced9bec6abcd3..a46e3d9c2a3fc1 100644
--- a/include/asm-sh/ipc.h
+++ b/include/asm-sh/ipc.h
@@ -1,32 +1 @@
-#ifndef __ASM_SH_IPC_H
-#define __ASM_SH_IPC_H
-
-/*
- * These are used to wrap system calls on x86.
- *
- * See arch/i386/kernel/sys_i386.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __ASM_SH_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sh64/ipc.h b/include/asm-sh64/ipc.h
index d8d9389bd3ce7a..a46e3d9c2a3fc1 100644
--- a/include/asm-sh64/ipc.h
+++ b/include/asm-sh64/ipc.h
@@ -1,6 +1 @@
-#ifndef __ASM_SH64_IPC_H
-#define __ASM_SH64_IPC_H
-
-#include <asm-sh/ipc.h>
-
-#endif /* __ASM_SH64_IPC_H */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc/ipc.h b/include/asm-sparc/ipc.h
index 3064aaf8fa27c3..a46e3d9c2a3fc1 100644
--- a/include/asm-sparc/ipc.h
+++ b/include/asm-sparc/ipc.h
@@ -1,32 +1 @@
-#ifndef __SPARC_IPC_H__
-#define __SPARC_IPC_H__
-
-/*
- * These are used to wrap system calls on the sparc.
- *
- * See arch/sparc/kernel/sys_sparc.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf __user *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-sparc64/ipc.h b/include/asm-sparc64/ipc.h
index 39261d5523ef9f..a46e3d9c2a3fc1 100644
--- a/include/asm-sparc64/ipc.h
+++ b/include/asm-sparc64/ipc.h
@@ -1,33 +1 @@
-#ifndef __SPARC64_IPC_H__
-#define __SPARC64_IPC_H__
-
-/*
- * These are used to wrap system calls on the sparc.
- *
- * See arch/sparc64/kernel/sys_sparc32.c for ugly details..
- */
-struct ipc_kludge {
- u32 msgp;
- s32 msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define SEMTIMEDOP 4
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-/* We don't need to maintain backward compatibility on 64bit, we've started fresh */
-#define IPCCALL(version,op) (op)
-
-#endif
+#include <asm-generic/ipc.h>
diff --git a/include/asm-v850/ipc.h b/include/asm-v850/ipc.h
index 5656799cd4e85d..a46e3d9c2a3fc1 100644
--- a/include/asm-v850/ipc.h
+++ b/include/asm-v850/ipc.h
@@ -1,31 +1 @@
-#ifndef __V850_IPC_H__
-#define __V850_IPC_H__
-
-/*
- * These are used to wrap system calls on v850.
- *
- * See arch/v850/kernel/syscalls.c for ugly details..
- */
-struct ipc_kludge {
- struct msgbuf *msgp;
- long msgtyp;
-};
-
-#define SEMOP 1
-#define SEMGET 2
-#define SEMCTL 3
-#define MSGSND 11
-#define MSGRCV 12
-#define MSGGET 13
-#define MSGCTL 14
-#define SHMAT 21
-#define SHMDT 22
-#define SHMGET 23
-#define SHMCTL 24
-
-/* Used by the DIPC package, try and avoid reusing it */
-#define DIPC 25
-
-#define IPCCALL(version,op) ((version)<<16 | (op))
-
-#endif /* __V850_IPC_H__ */
+#include <asm-generic/ipc.h>
diff --git a/include/asm-x86_64/ipc.h b/include/asm-x86_64/ipc.h
deleted file mode 100644
index 8736ba68c11835..00000000000000
--- a/include/asm-x86_64/ipc.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __x8664_IPC_H__
-#define __x8664_IPC_H__
-
-/* dummy */
-
-#endif
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index 2aac15a1290fc1..66f0be191ab4f5 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -80,6 +80,18 @@ extern inline void cpuid(int op, unsigned int *eax, unsigned int *ebx,
: "0" (op));
}
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(int op, int count, int *eax, int *ebx, int *ecx,
+ int *edx)
+{
+ __asm__("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (op), "c" (count));
+}
+
/*
* CPUID functions returning a single datum
*/
diff --git a/include/asm-x86_64/seccomp.h b/include/asm-x86_64/seccomp.h
new file mode 100644
index 00000000000000..553af65a2287aa
--- /dev/null
+++ b/include/asm-x86_64/seccomp.h
@@ -0,0 +1,24 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/thread_info.h>
+
+#ifdef TIF_32BIT
+#error "unexpected TIF_32BIT on x86_64"
+#else
+#define TIF_32BIT TIF_IA32
+#endif
+
+#include <linux/unistd.h>
+#include <asm/ia32_unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#define __NR_seccomp_read_32 __NR_ia32_read
+#define __NR_seccomp_write_32 __NR_ia32_write
+#define __NR_seccomp_exit_32 __NR_ia32_exit
+#define __NR_seccomp_sigreturn_32 __NR_ia32_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index f2a09f442d7dcc..a8ea0164f3ab01 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -774,7 +774,7 @@ asmlinkage long sys_pipe(int *fildes);
asmlinkage long sys_ptrace(long request, long pid,
unsigned long addr, long data);
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs);
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs);
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on);
struct sigaction;
asmlinkage long sys_rt_sigaction(int sig,
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 5cbf3486926f51..aefe6d051ace16 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -455,8 +455,6 @@ struct acpi_prt_list {
struct list_head entries;
};
-extern struct acpi_prt_list acpi_prt;
-
struct pci_dev;
int acpi_pci_irq_enable (struct pci_dev *dev);
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 3c369c6553e3ed..f7a1390d67f5b3 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -25,13 +25,39 @@ typedef int (congested_fn)(void *, int);
struct backing_dev_info {
unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */
unsigned long state; /* Always use atomic bitops on this */
- int memory_backed; /* Cannot clean pages with writepage */
+ unsigned int capabilities; /* Device capabilities */
congested_fn *congested_fn; /* Function pointer if device is md/dm */
void *congested_data; /* Pointer to aux data for congested func */
void (*unplug_io_fn)(struct backing_dev_info *, struct page *);
void *unplug_io_data;
};
+
+/*
+ * Flags in backing_dev_info::capability
+ * - The first two flags control whether dirty pages will contribute to the
+ * VM's accounting and whether writepages() should be called for dirty pages
+ * (something that would not, for example, be appropriate for ramfs)
+ * - These flags let !MMU mmap() govern direct device mapping vs immediate
+ * copying more easily for MAP_PRIVATE, especially for ROM filesystems
+ */
+#define BDI_CAP_NO_ACCT_DIRTY 0x00000001 /* Dirty pages shouldn't contribute to accounting */
+#define BDI_CAP_NO_WRITEBACK 0x00000002 /* Don't write pages back */
+#define BDI_CAP_MAP_COPY 0x00000004 /* Copy can be mapped (MAP_PRIVATE) */
+#define BDI_CAP_MAP_DIRECT 0x00000008 /* Can be mapped directly (MAP_SHARED) */
+#define BDI_CAP_READ_MAP 0x00000010 /* Can be mapped for reading */
+#define BDI_CAP_WRITE_MAP 0x00000020 /* Can be mapped for writing */
+#define BDI_CAP_EXEC_MAP 0x00000040 /* Can be mapped for execution */
+#define BDI_CAP_VMFLAGS \
+ (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP)
+
+#if defined(VM_MAYREAD) && \
+ (BDI_CAP_READ_MAP != VM_MAYREAD || \
+ BDI_CAP_WRITE_MAP != VM_MAYWRITE || \
+ BDI_CAP_EXEC_MAP != VM_MAYEXEC)
+#error please change backing_dev_info::capabilities flags
+#endif
+
extern struct backing_dev_info default_backing_dev_info;
void default_unplug_io_fn(struct backing_dev_info *bdi, struct page *page);
@@ -62,4 +88,17 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
(1 << BDI_write_congested));
}
+#define bdi_cap_writeback_dirty(bdi) \
+ (!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK))
+
+#define bdi_cap_account_dirty(bdi) \
+ (!((bdi)->capabilities & BDI_CAP_NO_ACCT_DIRTY))
+
+#define mapping_cap_writeback_dirty(mapping) \
+ bdi_cap_writeback_dirty((mapping)->backing_dev_info)
+
+#define mapping_cap_account_dirty(mapping) \
+ bdi_cap_account_dirty((mapping)->backing_dev_info)
+
+
#endif /* _LINUX_BACKING_DEV_H */
diff --git a/include/linux/console.h b/include/linux/console.h
index b9b183e986e5e4..721371382ae5ff 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -59,7 +59,6 @@ struct consw {
extern const struct consw *conswitchp;
extern const struct consw dummy_con; /* dummy console buffer */
-extern const struct consw fb_con; /* frame buffer based console */
extern const struct consw vga_con; /* VGA text console */
extern const struct consw newport_con; /* SGI Newport console */
extern const struct consw prom_con; /* SPARC PROM console */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 9d1507c87cecc5..b45d3e2d711a38 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -702,9 +702,7 @@ struct fb_tile_ops {
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
-#define FBINFO_MISC_MODESWITCH 0x20000 /* mode switch */
-#define FBINFO_MISC_MODESWITCHLATE 0x40000 /* init hardware later */
-#define FBINFO_MISC_TILEBLITTING 0x80000 /* use tile blitting */
+#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
struct fb_info {
int node;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 723f41b51cedb4..5df687d940fa11 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -445,7 +445,6 @@ struct inode {
unsigned long i_version;
unsigned long i_blocks;
unsigned short i_bytes;
- unsigned char i_sock;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
struct semaphore i_sem;
struct rw_semaphore i_alloc_sem;
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index da901fd6b59086..9f2ae600683c63 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -306,9 +306,6 @@ struct i2c_client_address_data {
#define ANY_I2C_BUS 0xffff
#define ANY_I2C_ISA_BUS 9191
-/* The length of the option lists */
-#define I2C_CLIENT_MAX_OPTS 48
-
/* ----- functions exported by i2c.o */
@@ -526,6 +523,9 @@ union i2c_smbus_data {
#define I2C_MAJOR 89 /* Device major number */
/* These defines are used for probing i2c client addresses */
+/* The length of the option lists */
+#define I2C_CLIENT_MAX_OPTS 48
+
/* Default fill of many variables */
#define I2C_CLIENT_DEFAULTS {I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
@@ -544,19 +544,12 @@ union i2c_smbus_data {
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END}
-/* This is ugly. We need to evaluate I2C_CLIENT_MAX_OPTS before it is
- stringified */
-#define I2C_CLIENT_MODPARM_AUX1(x) "1-" #x "h"
-#define I2C_CLIENT_MODPARM_AUX(x) I2C_CLIENT_MODPARM_AUX1(x)
-#define I2C_CLIENT_MODPARM I2C_CLIENT_MODPARM_AUX(I2C_CLIENT_MAX_OPTS)
-
/* I2C_CLIENT_MODULE_PARM creates a module parameter, and puts it in the
module header */
#define I2C_CLIENT_MODULE_PARM(var,desc) \
static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \
static unsigned int var##_num; \
- /*MODULE_PARM(var,I2C_CLIENT_MODPARM);*/ \
module_param_array(var, short, &var##_num, 0); \
MODULE_PARM_DESC(var,desc)
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index e04b71cd9e731c..6fafb27877a7d5 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -7,7 +7,6 @@
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
#include <linux/timer.h>
-#include <linux/rtnetlink.h>
struct ipv4_devconf
{
@@ -132,25 +131,6 @@ static __inline__ int bad_mask(u32 mask, u32 addr)
return 0;
}
-static inline int inet_ifa_match_local_prefixlen(struct ifaddrmsg *ifm,
- struct in_ifaddr *ifa)
-{
- int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
-
- /*
- * Since the prefix length hasn't been taken into account in
- * previous kernel versions, parts of the userspace rely on the fact
- * that the deletion of an address without specifying a prefix works.
- * We cannot break this and thus a prefix length of 32 still represents
- * a wildcard if no exact match is requested.
- */
- if (real_prefixlen != 32 || ifm->ifa_prefixlen & IFA_PREFIX_EXACT_DEL)
- if (real_prefixlen != ifa->ifa_prefixlen)
- return 0;
-
- return 1;
-}
-
#define for_primary_ifa(in_dev) { struct in_ifaddr *ifa; \
for (ifa = (in_dev)->ifa_list; ifa && !(ifa->ifa_flags&IFA_F_SECONDARY); ifa = ifa->ifa_next)
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 53a5afeb4e79cd..8438c68591f99c 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -164,7 +164,7 @@ static inline void __inet_sk_copy_descendant(struct sock *sk_to,
const int ancestor_size)
{
memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1,
- sk_from->sk_prot->slab_obj_size - ancestor_size);
+ sk_from->sk_prot->obj_size - ancestor_size);
}
#if !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE))
static inline void inet_sk_copy_descendant(struct sock *sk_to,
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 1b4e5122d697fc..32e52769a00b6e 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -398,19 +398,6 @@ enum
#define IFA_MAX (__IFA_MAX - 1)
-/*
- * Quirk for IPv4 address deletion to allow exact deletion of equal
- * addresses varying only in prefix length. A explicit exact comparison
- * of the prefix length will only be done if IFA_PREFIX_EXACT_DEL is
- * ORed to ifa_prefixlen.
- *
- * Note: This special treatment is only understood while deleting
- * addresses and will lead to unexpected behaviour if used
- * otherwise.
- */
-#define IFA_PREFIX_EXACT_DEL 0x40
-#define IFA_REAL_DEL_PREFIX(l) ((l) & 0x3f)
-
/* ifa_flags */
#define IFA_F_SECONDARY 0x01
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index ee989b6ee22aa1..3a2702bbb1d67d 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -8,6 +8,7 @@
#define NR_SECCOMP_MODES 1
#include <linux/thread_info.h>
+#include <asm/seccomp.h>
typedef struct { int mode; } seccomp_t;
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 29a1b14bb218bd..c119ce7cbd22ae 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -26,21 +26,23 @@ struct svc_cred {
struct svc_rqst; /* forward decl */
/* Authentication is done in the context of a domain.
- * For a server, a domain represents a group of clients using
+ *
+ * Currently, the nfs server uses the auth_domain to stand
+ * for the "client" listed in /etc/exports.
+ *
+ * More generally, a domain might represent a group of clients using
* a common mechanism for authentication and having a common mapping
* between local identity (uid) and network identity. All clients
* in a domain have similar general access rights. Each domain can
* contain multiple principals which will have different specific right
* based on normal Discretionary Access Control.
*
- * For a client, a domain represents a number of servers which all
- * use a common authentication mechanism and network identity name space.
- *
* A domain is created by an authentication flavour module based on name
* only. Userspace then fills in detail on demand.
*
- * The creation of a domain typically implies creation of one or
- * more caches for storing domain specific information.
+ * In the case of auth_unix and auth_null, the auth_domain is also
+ * associated with entries in another cache representing the mapping
+ * of ip addresses to the given client.
*/
struct auth_domain {
struct cache_head h;
diff --git a/include/net/llc_conn.h b/include/net/llc_conn.h
index 179e98e2aac864..8ad3bc2c23d78d 100644
--- a/include/net/llc_conn.h
+++ b/include/net/llc_conn.h
@@ -92,7 +92,7 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
return skb->cb[sizeof(skb->cb) - 1];
}
-extern struct sock *llc_sk_alloc(int family, int priority);
+extern struct sock *llc_sk_alloc(int family, int priority, struct proto *prot);
extern void llc_sk_free(struct sock *sk);
extern void llc_sk_reset(struct sock *sk);
diff --git a/include/net/sock.h b/include/net/sock.h
index fb789af4ab0887..be81cabd0da3f8 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -154,12 +154,10 @@ struct sock_common {
* @sk_sndtimeo - %SO_SNDTIMEO setting
* @sk_filter - socket filtering instructions
* @sk_protinfo - private area, net family specific, when not using slab
- * @sk_slab - the slabcache this instance was allocated from
* @sk_timer - sock cleanup timer
* @sk_stamp - time stamp of last packet received
* @sk_socket - Identd and reporting IO signals
* @sk_user_data - RPC layer private data
- * @sk_owner - module that owns this socket
* @sk_sndmsg_page - cached page for sendmsg
* @sk_sndmsg_off - cached offset for sendmsg
* @sk_send_head - front of stuff to transmit
@@ -231,12 +229,10 @@ struct sock {
long sk_sndtimeo;
struct sk_filter *sk_filter;
void *sk_protinfo;
- kmem_cache_t *sk_slab;
struct timer_list sk_timer;
struct timeval sk_stamp;
struct socket *sk_socket;
void *sk_user_data;
- struct module *sk_owner;
struct page *sk_sndmsg_page;
struct sk_buff *sk_send_head;
__u32 sk_sndmsg_off;
@@ -546,37 +542,22 @@ struct proto {
int max_header;
kmem_cache_t *slab;
- int slab_obj_size;
+ unsigned int obj_size;
struct module *owner;
char name[32];
+ struct list_head node;
+
struct {
int inuse;
u8 __pad[SMP_CACHE_BYTES - sizeof(int)];
} stats[NR_CPUS];
};
-extern int sk_alloc_slab(struct proto *prot, char *name);
-extern void sk_free_slab(struct proto *prot);
-
-static __inline__ void sk_set_owner(struct sock *sk, struct module *owner)
-{
- /*
- * One should use sk_set_owner just once, after struct sock creation,
- * be it shortly after sk_alloc or after a function that returns a new
- * struct sock (and that down the call chain called sk_alloc), e.g. the
- * IPv4 and IPv6 modules share tcp_create_openreq_child, so if
- * tcp_create_openreq_child called sk_set_owner IPv6 would have to
- * change the ownership of this struct sock, with one not needed
- * transient sk_set_owner call.
- */
- BUG_ON(sk->sk_owner != NULL);
-
- sk->sk_owner = owner;
- __module_get(owner);
-}
+extern int proto_register(struct proto *prot, int alloc_slab);
+extern void proto_unregister(struct proto *prot);
/* Called with local bh disabled */
static __inline__ void sock_prot_inc_use(struct proto *prot)
@@ -696,8 +677,8 @@ extern void FASTCALL(release_sock(struct sock *sk));
#define bh_lock_sock(__sk) spin_lock(&((__sk)->sk_lock.slock))
#define bh_unlock_sock(__sk) spin_unlock(&((__sk)->sk_lock.slock))
-extern struct sock * sk_alloc(int family, int priority, int zero_it,
- kmem_cache_t *slab);
+extern struct sock *sk_alloc(int family, int priority,
+ struct proto *prot, int zero_it);
extern void sk_free(struct sock *sk);
extern struct sk_buff *sock_wmalloc(struct sock *sk,
diff --git a/include/video/s1d13xxxfb.h b/include/video/s1d13xxxfb.h
new file mode 100644
index 00000000000000..f06cc88607f51d
--- /dev/null
+++ b/include/video/s1d13xxxfb.h
@@ -0,0 +1,166 @@
+/* drivers/video/s1d3xxxfb.h
+ *
+ * (c) 2004 Simtec Electronics
+ * (c) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ * Header file for Epson S1D13XXX driver code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef S1D13XXXFB_H
+#define S1D13XXXFB_H
+
+#define S1D_PALETTE_SIZE 256
+#define S1D_CHIP_REV 7 /* expected chip revision number for s1d13806 */
+#define S1D_FBID "S1D13806"
+#define S1D_DEVICENAME "s1d13806fb"
+
+/* register definitions (tested on s1d13896) */
+#define S1DREG_REV_CODE 0x0000 /* Revision Code Register */
+#define S1DREG_MISC 0x0001 /* Miscellaneous Register */
+#define S1DREG_GPIO_CNF0 0x0004 /* General IO Pins Configuration Register 0 */
+#define S1DREG_GPIO_CNF1 0x0005 /* General IO Pins Configuration Register 1 */
+#define S1DREG_GPIO_CTL0 0x0008 /* General IO Pins Control Register 0 */
+#define S1DREG_GPIO_CTL1 0x0009 /* General IO Pins Control Register 1 */
+#define S1DREG_CNF_STATUS 0x000C /* Configuration Status Readback Register */
+#define S1DREG_CLK_CNF 0x0010 /* Memory Clock Configuration Register */
+#define S1DREG_LCD_CLK_CNF 0x0014 /* LCD Pixel Clock Configuration Register */
+#define S1DREG_CRT_CLK_CNF 0x0018 /* CRT/TV Pixel Clock Configuration Register */
+#define S1DREG_MPLUG_CLK_CNF 0x001C /* MediaPlug Clock Configuration Register */
+#define S1DREG_CPU2MEM_WST_SEL 0x001E /* CPU To Memory Wait State Select Register */
+#define S1DREG_MEM_CNF 0x0020 /* Memory Configuration Register */
+#define S1DREG_SDRAM_REF_RATE 0x0021 /* SDRAM Refresh Rate Register */
+#define S1DREG_SDRAM_TC0 0x002A /* SDRAM Timing Control Register 0 */
+#define S1DREG_SDRAM_TC1 0x002B /* SDRAM Timing Control Register 1 */
+#define S1DREG_PANEL_TYPE 0x0030 /* Panel Type Register */
+#define S1DREG_MOD_RATE 0x0031 /* MOD Rate Register */
+#define S1DREG_LCD_DISP_HWIDTH 0x0032 /* LCD Horizontal Display Width Register: ((val)+1)*8)=pix/line */
+#define S1DREG_LCD_NDISP_HPER 0x0034 /* LCD Horizontal Non-Display Period Register: ((val)+1)*8)=NDpix/line */
+#define S1DREG_TFT_FPLINE_START 0x0035 /* TFT FPLINE Start Position Register */
+#define S1DREG_TFT_FPLINE_PWIDTH 0x0036 /* TFT FPLINE Pulse Width Register. */
+#define S1DREG_LCD_DISP_VHEIGHT0 0x0038 /* LCD Vertical Display Height Register 0 */
+#define S1DREG_LCD_DISP_VHEIGHT1 0x0039 /* LCD Vertical Display Height Register 1 */
+#define S1DREG_LCD_NDISP_VPER 0x003A /* LCD Vertical Non-Display Period Register: (val)+1=NDlines */
+#define S1DREG_TFT_FPFRAME_START 0x003B /* TFT FPFRAME Start Position Register */
+#define S1DREG_TFT_FPFRAME_PWIDTH 0x003C /* TFT FPFRAME Pulse Width Register */
+#define S1DREG_LCD_DISP_MODE 0x0040 /* LCD Display Mode Register */
+#define S1DREG_LCD_MISC 0x0041 /* LCD Miscellaneous Register */
+#define S1DREG_LCD_DISP_START0 0x0042 /* LCD Display Start Address Register 0 */
+#define S1DREG_LCD_DISP_START1 0x0043 /* LCD Display Start Address Register 1 */
+#define S1DREG_LCD_DISP_START2 0x0044 /* LCD Display Start Address Register 2 */
+#define S1DREG_LCD_MEM_OFF0 0x0046 /* LCD Memory Address Offset Register 0 */
+#define S1DREG_LCD_MEM_OFF1 0x0047 /* LCD Memory Address Offset Register 1 */
+#define S1DREG_LCD_PIX_PAN 0x0048 /* LCD Pixel Panning Register */
+#define S1DREG_LCD_DISP_FIFO_HTC 0x004A /* LCD Display FIFO High Threshold Control Register */
+#define S1DREG_LCD_DISP_FIFO_LTC 0x004B /* LCD Display FIFO Low Threshold Control Register */
+#define S1DREG_CRT_DISP_HWIDTH 0x0050 /* CRT/TV Horizontal Display Width Register: ((val)+1)*8)=pix/line */
+#define S1DREG_CRT_NDISP_HPER 0x0052 /* CRT/TV Horizontal Non-Display Period Register */
+#define S1DREG_CRT_HRTC_START 0x0053 /* CRT/TV HRTC Start Position Register */
+#define S1DREG_CRT_HRTC_PWIDTH 0x0054 /* CRT/TV HRTC Pulse Width Register */
+#define S1DREG_CRT_DISP_VHEIGHT0 0x0056 /* CRT/TV Vertical Display Height Register 0 */
+#define S1DREG_CRT_DISP_VHEIGHT1 0x0057 /* CRT/TV Vertical Display Height Register 1 */
+#define S1DREG_CRT_NDISP_VPER 0x0058 /* CRT/TV Vertical Non-Display Period Register */
+#define S1DREG_CRT_VRTC_START 0x0059 /* CRT/TV VRTC Start Position Register */
+#define S1DREG_CRT_VRTC_PWIDTH 0x005A /* CRT/TV VRTC Pulse Width Register */
+#define S1DREG_TV_OUT_CTL 0x005B /* TV Output Control Register */
+#define S1DREG_CRT_DISP_MODE 0x0060 /* CRT/TV Display Mode Register */
+#define S1DREG_CRT_DISP_START0 0x0062 /* CRT/TV Display Start Address Register 0 */
+#define S1DREG_CRT_DISP_START1 0x0063 /* CRT/TV Display Start Address Register 1 */
+#define S1DREG_CRT_DISP_START2 0x0064 /* CRT/TV Display Start Address Register 2 */
+#define S1DREG_CRT_MEM_OFF0 0x0066 /* CRT/TV Memory Address Offset Register 0 */
+#define S1DREG_CRT_MEM_OFF1 0x0067 /* CRT/TV Memory Address Offset Register 1 */
+#define S1DREG_CRT_PIX_PAN 0x0068 /* CRT/TV Pixel Panning Register */
+#define S1DREG_CRT_DISP_FIFO_HTC 0x006A /* CRT/TV Display FIFO High Threshold Control Register */
+#define S1DREG_CRT_DISP_FIFO_LTC 0x006B /* CRT/TV Display FIFO Low Threshold Control Register */
+#define S1DREG_LCD_CUR_CTL 0x0070 /* LCD Ink/Cursor Control Register */
+#define S1DREG_LCD_CUR_START 0x0071 /* LCD Ink/Cursor Start Address Register */
+#define S1DREG_LCD_CUR_XPOS0 0x0072 /* LCD Cursor X Position Register 0 */
+#define S1DREG_LCD_CUR_XPOS1 0x0073 /* LCD Cursor X Position Register 1 */
+#define S1DREG_LCD_CUR_YPOS0 0x0074 /* LCD Cursor Y Position Register 0 */
+#define S1DREG_LCD_CUR_YPOS1 0x0075 /* LCD Cursor Y Position Register 1 */
+#define S1DREG_LCD_CUR_BCTL0 0x0076 /* LCD Ink/Cursor Blue Color 0 Register */
+#define S1DREG_LCD_CUR_GCTL0 0x0077 /* LCD Ink/Cursor Green Color 0 Register */
+#define S1DREG_LCD_CUR_RCTL0 0x0078 /* LCD Ink/Cursor Red Color 0 Register */
+#define S1DREG_LCD_CUR_BCTL1 0x007A /* LCD Ink/Cursor Blue Color 1 Register */
+#define S1DREG_LCD_CUR_GCTL1 0x007B /* LCD Ink/Cursor Green Color 1 Register */
+#define S1DREG_LCD_CUR_RCTL1 0x007C /* LCD Ink/Cursor Red Color 1 Register */
+#define S1DREG_LCD_CUR_FIFO_HTC 0x007E /* LCD Ink/Cursor FIFO High Threshold Register */
+#define S1DREG_CRT_CUR_CTL 0x0080 /* CRT/TV Ink/Cursor Control Register */
+#define S1DREG_CRT_CUR_START 0x0081 /* CRT/TV Ink/Cursor Start Address Register */
+#define S1DREG_CRT_CUR_XPOS0 0x0082 /* CRT/TV Cursor X Position Register 0 */
+#define S1DREG_CRT_CUR_XPOS1 0x0083 /* CRT/TV Cursor X Position Register 1 */
+#define S1DREG_CRT_CUR_YPOS0 0x0084 /* CRT/TV Cursor Y Position Register 0 */
+#define S1DREG_CRT_CUR_YPOS1 0x0085 /* CRT/TV Cursor Y Position Register 1 */
+#define S1DREG_CRT_CUR_BCTL0 0x0086 /* CRT/TV Ink/Cursor Blue Color 0 Register */
+#define S1DREG_CRT_CUR_GCTL0 0x0087 /* CRT/TV Ink/Cursor Green Color 0 Register */
+#define S1DREG_CRT_CUR_RCTL0 0x0088 /* CRT/TV Ink/Cursor Red Color 0 Register */
+#define S1DREG_CRT_CUR_BCTL1 0x008A /* CRT/TV Ink/Cursor Blue Color 1 Register */
+#define S1DREG_CRT_CUR_GCTL1 0x008B /* CRT/TV Ink/Cursor Green Color 1 Register */
+#define S1DREG_CRT_CUR_RCTL1 0x008C /* CRT/TV Ink/Cursor Red Color 1 Register */
+#define S1DREG_CRT_CUR_FIFO_HTC 0x008E /* CRT/TV Ink/Cursor FIFO High Threshold Register */
+#define S1DREG_BBLT_CTL0 0x0100 /* BitBLT Control Register 0 */
+#define S1DREG_BBLT_CTL1 0x0101 /* BitBLT Control Register 1 */
+#define S1DREG_BBLT_CC_EXP 0x0102 /* BitBLT Code/Color Expansion Register */
+#define S1DREG_BBLT_OP 0x0103 /* BitBLT Operation Register */
+#define S1DREG_BBLT_SRC_START0 0x0104 /* BitBLT Source Start Address Register 0 */
+#define S1DREG_BBLT_SRC_START1 0x0105 /* BitBLT Source Start Address Register 1 */
+#define S1DREG_BBLT_SRC_START2 0x0106 /* BitBLT Source Start Address Register 2 */
+#define S1DREG_BBLT_DST_START0 0x0108 /* BitBLT Destination Start Address Register 0 */
+#define S1DREG_BBLT_DST_START1 0x0109 /* BitBLT Destination Start Address Register 1 */
+#define S1DREG_BBLT_DST_START2 0x010A /* BitBLT Destination Start Address Register 2 */
+#define S1DREG_BBLT_MEM_OFF0 0x010C /* BitBLT Memory Address Offset Register 0 */
+#define S1DREG_BBLT_MEM_OFF1 0x010D /* BitBLT Memory Address Offset Register 1 */
+#define S1DREG_BBLT_WIDTH0 0x0110 /* BitBLT Width Register 0 */
+#define S1DREG_BBLT_WIDTH1 0x0111 /* BitBLT Width Register 1 */
+#define S1DREG_BBLT_HEIGHT0 0x0112 /* BitBLT Height Register 0 */
+#define S1DREG_BBLT_HEIGHT1 0x0113 /* BitBLT Height Register 1 */
+#define S1DREG_BBLT_BGC0 0x0114 /* BitBLT Background Color Register 0 */
+#define S1DREG_BBLT_BGC1 0x0115 /* BitBLT Background Color Register 1 */
+#define S1DREG_BBLT_FGC0 0x0118 /* BitBLT Foreground Color Register 0 */
+#define S1DREG_BBLT_FGC1 0x0119 /* BitBLT Foreground Color Register 1 */
+#define S1DREG_LKUP_MODE 0x01E0 /* Look-Up Table Mode Register */
+#define S1DREG_LKUP_ADDR 0x01E2 /* Look-Up Table Address Register */
+#define S1DREG_LKUP_DATA 0x01E4 /* Look-Up Table Data Register */
+#define S1DREG_PS_CNF 0x01F0 /* Power Save Configuration Register */
+#define S1DREG_PS_STATUS 0x01F1 /* Power Save Status Register */
+#define S1DREG_CPU2MEM_WDOGT 0x01F4 /* CPU-to-Memory Access Watchdog Timer Register */
+#define S1DREG_COM_DISP_MODE 0x01FC /* Common Display Mode Register */
+
+#define S1DREG_DELAYOFF 0xFFFE
+#define S1DREG_DELAYON 0xFFFF
+
+/* Note: all above defines should go in separate header files
+ when implementing other S1D13xxx chip support. */
+
+struct s1d13xxxfb_regval {
+ u16 addr;
+ u8 value;
+};
+
+
+struct s1d13xxxfb_par {
+ void __iomem *regs;
+ unsigned char display;
+
+ unsigned int pseudo_palette[16];
+#ifdef CONFIG_PM
+ void *regs_save; /* pm saves all registers here */
+ void *disp_save; /* pm saves entire screen here */
+#endif
+};
+
+struct s1d13xxxfb_pdata {
+ const struct s1d13xxxfb_regval *initregs;
+ const unsigned int initregssize;
+ void (*platform_init_video)(void);
+#ifdef CONFIG_PM
+ int (*platform_suspend_video)(void);
+ int (*platform_resume_video)(void);
+#endif
+};
+
+#endif
+
diff --git a/include/video/trident.h b/include/video/trident.h
index abe7d67756de7b..200be255168191 100644
--- a/include/video/trident.h
+++ b/include/video/trident.h
@@ -9,7 +9,7 @@
#define debug(f,a...)
#endif
-#define output(f, a...) printk("tridentfb: " f, ## a)
+#define output(f, a...) pr_info("tridentfb: " f, ## a)
#define Kb (1024)
#define Mb (Kb*Kb)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index cd942ce30b7384..a6584d9099d32a 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -193,7 +193,7 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry);
static struct backing_dev_info cpuset_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
static struct inode *cpuset_new_inode(mode_t mode)
@@ -1456,7 +1456,7 @@ void cpuset_init_current_mems_allowed(void)
* Do not call this routine if in_interrupt().
*/
-void cpuset_update_current_mems_allowed()
+void cpuset_update_current_mems_allowed(void)
{
struct cpuset *cs = current->cpuset;
diff --git a/kernel/printk.c b/kernel/printk.c
index 5d5754964bf40a..1498689548d1e6 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,7 +54,12 @@ int console_printk[4] = {
EXPORT_SYMBOL(console_printk);
+/*
+ * Low lever drivers may need that to know if they can schedule in
+ * their unblank() callback or not. So let's export it.
+ */
int oops_in_progress;
+EXPORT_SYMBOL(oops_in_progress);
/*
* console_sem protects the console_drivers list, and also
@@ -751,12 +756,15 @@ void console_unblank(void)
struct console *c;
/*
- * Try to get the console semaphore. If someone else owns it
- * we have to return without unblanking because console_unblank
- * may be called in interrupt context.
+ * console_unblank can no longer be called in interrupt context unless
+ * oops_in_progress is set to 1..
*/
- if (down_trylock(&console_sem) != 0)
- return;
+ if (oops_in_progress) {
+ if (down_trylock(&console_sem) != 0)
+ return;
+ } else
+ acquire_console_sem();
+
console_locked = 1;
console_may_schedule = 0;
for (c = console_drivers; c != NULL; c = c->next)
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index f0ae3c3c013eb6..d00eded75d71f8 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -465,6 +465,6 @@ void synchronize_kernel(void)
}
module_param(maxbatch, int, 0);
-EXPORT_SYMBOL(call_rcu);
-EXPORT_SYMBOL(call_rcu_bh);
-EXPORT_SYMBOL(synchronize_kernel);
+EXPORT_SYMBOL_GPL(call_rcu);
+EXPORT_SYMBOL_GPL(call_rcu_bh);
+EXPORT_SYMBOL_GPL(synchronize_kernel);
diff --git a/kernel/sched.c b/kernel/sched.c
index dff94ba6df3860..f69c4a5361e3b8 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -314,7 +314,6 @@ static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags)
static int show_schedstat(struct seq_file *seq, void *v)
{
int cpu;
- enum idle_type itype;
seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
seq_printf(seq, "timestamp %lu\n", jiffies);
@@ -340,6 +339,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
#ifdef CONFIG_SMP
/* domain-specific stats */
for_each_domain(cpu, sd) {
+ enum idle_type itype;
char mask_str[NR_CPUS];
cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index b6c5b35c737c04..c3391b6020e855 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -8,10 +8,6 @@
#include <linux/seccomp.h>
#include <linux/sched.h>
-#include <asm/unistd.h>
-#ifdef TIF_IA32
-#include <asm/ia32_unistd.h>
-#endif
/* #define SECCOMP_DEBUG 1 */
@@ -21,27 +17,13 @@
* to limit the stack allocations too.
*/
static int mode1_syscalls[] = {
- __NR_read, __NR_write, __NR_exit,
- /*
- * Allow either sigreturn or rt_sigreturn, newer archs
- * like x86-64 only defines __NR_rt_sigreturn.
- */
-#ifdef __NR_sigreturn
- __NR_sigreturn,
-#else
- __NR_rt_sigreturn,
-#endif
+ __NR_seccomp_read, __NR_seccomp_write, __NR_seccomp_exit, __NR_seccomp_sigreturn,
0, /* null terminated */
};
-#ifdef TIF_IA32
-static int mode1_syscalls_32bit[] = {
- __NR_ia32_read, __NR_ia32_write, __NR_ia32_exit,
- /*
- * Allow either sigreturn or rt_sigreturn, newer archs
- * like x86-64 only defines __NR_rt_sigreturn.
- */
- __NR_ia32_sigreturn,
+#ifdef TIF_32BIT
+static int mode1_syscalls_32[] = {
+ __NR_seccomp_read_32, __NR_seccomp_write_32, __NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
0, /* null terminated */
};
#endif
@@ -54,9 +36,9 @@ void __secure_computing(int this_syscall)
switch (mode) {
case 1:
syscall = mode1_syscalls;
-#ifdef TIF_IA32
- if (test_thread_flag(TIF_IA32))
- syscall = mode1_syscalls_32bit;
+#ifdef TIF_32BIT
+ if (test_thread_flag(TIF_32BIT))
+ syscall = mode1_syscalls_32;
#endif
do {
if (*syscall == this_syscall)
diff --git a/mm/filemap.c b/mm/filemap.c
index 553681db603d48..439b2bea8e3421 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -172,7 +172,7 @@ static int __filemap_fdatawrite_range(struct address_space *mapping,
.end = end,
};
- if (mapping->backing_dev_info->memory_backed)
+ if (!mapping_cap_writeback_dirty(mapping))
return 0;
ret = do_writepages(mapping, &wbc);
@@ -269,7 +269,7 @@ int sync_page_range(struct inode *inode, struct address_space *mapping,
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
int ret;
- if (mapping->backing_dev_info->memory_backed || !count)
+ if (!mapping_cap_writeback_dirty(mapping) || !count)
return 0;
ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
if (ret == 0) {
@@ -295,7 +295,7 @@ int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
int ret;
- if (mapping->backing_dev_info->memory_backed || !count)
+ if (!mapping_cap_writeback_dirty(mapping) || !count)
return 0;
ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
if (ret == 0)
diff --git a/mm/nommu.c b/mm/nommu.c
index a9cf49a0e03507..f613db39e84743 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -396,6 +396,7 @@ unsigned long do_mmap_pgoff(struct file *file,
unsigned int vm_flags;
void *result;
int ret, membacked;
+ unsigned long reqprot = prot;
/* do the simple checks first */
if (flags & MAP_FIXED || addr) {
@@ -506,7 +507,7 @@ unsigned long do_mmap_pgoff(struct file *file,
}
/* allow the security API to have its say */
- ret = security_file_mmap(file, prot, flags);
+ ret = security_file_mmap(file, reqprot, prot, flags);
if (ret)
return ret;
@@ -1063,3 +1064,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
return -ENOMEM;
}
+int in_gate_area_no_task(unsigned long addr)
+{
+ return 0;
+}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index ab35f448db18e0..6ddd6a29c73b20 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -627,7 +627,7 @@ int __set_page_dirty_nobuffers(struct page *page)
mapping2 = page_mapping(page);
if (mapping2) { /* Race with truncate? */
BUG_ON(mapping2 != mapping);
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
inc_page_state(nr_dirty);
radix_tree_tag_set(&mapping->page_tree,
page_index(page), PAGECACHE_TAG_DIRTY);
@@ -713,7 +713,7 @@ int test_clear_page_dirty(struct page *page)
page_index(page),
PAGECACHE_TAG_DIRTY);
write_unlock_irqrestore(&mapping->tree_lock, flags);
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
dec_page_state(nr_dirty);
return 1;
}
@@ -744,7 +744,7 @@ int clear_page_dirty_for_io(struct page *page)
if (mapping) {
if (TestClearPageDirty(page)) {
- if (!mapping->backing_dev_info->memory_backed)
+ if (mapping_cap_account_dirty(mapping))
dec_page_state(nr_dirty);
return 1;
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e87a9e1809f271..c73dbbc1cd8f5f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -780,6 +780,9 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
/*
* Go through the zonelist again. Let __GFP_HIGH and allocations
* coming from realtime tasks to go deeper into reserves
+ *
+ * This is the last chance, in general, before the goto nopage.
+ * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc.
*/
for (i = 0; (z = zones[i]) != NULL; i++) {
if (!zone_watermark_ok(z, order, z->pages_min,
@@ -787,7 +790,7 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
gfp_mask & __GFP_HIGH))
continue;
- if (!cpuset_zone_allowed(z))
+ if (wait && !cpuset_zone_allowed(z))
continue;
page = buffered_rmqueue(z, order, gfp_mask);
diff --git a/mm/readahead.c b/mm/readahead.c
index 8c4ac1267120f4..b840e7c6ea7404 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -23,6 +23,7 @@ EXPORT_SYMBOL(default_unplug_io_fn);
struct backing_dev_info default_backing_dev_info = {
.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
.state = 0,
+ .capabilities = BDI_CAP_MAP_COPY,
.unplug_io_fn = default_unplug_io_fn,
};
EXPORT_SYMBOL_GPL(default_backing_dev_info);
diff --git a/mm/shmem.c b/mm/shmem.c
index c1d60dd5579ef4..61574b81d979f3 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -184,8 +184,8 @@ static struct vm_operations_struct shmem_vm_ops;
static struct backing_dev_info shmem_backing_dev_info = {
.ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
- .unplug_io_fn = default_unplug_io_fn,
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
+ .unplug_io_fn = default_unplug_io_fn,
};
static LIST_HEAD(shmem_swaplist);
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 994c262ae084d7..a063a902ed0347 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -29,7 +29,7 @@ static struct address_space_operations swap_aops = {
};
static struct backing_dev_info swap_backing_dev_info = {
- .memory_backed = 1, /* Does not contribute to dirty memory */
+ .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
.unplug_io_fn = swap_unplug_io_fn,
};
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 8c55dbce87582c..d1fea5c3dda1b0 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1015,6 +1015,12 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
return sum ? htons((unsigned short)sum) : 0xFFFF;
}
+static struct proto ddp_proto = {
+ .name = "DDP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct atalk_sock),
+};
+
/*
* Create a socket. Initialise the socket, blank the addresses
* set the state.
@@ -1031,14 +1037,12 @@ static int atalk_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
goto out;
rc = -ENOMEM;
- sk = sk_alloc(PF_APPLETALK, GFP_KERNEL,
- sizeof(struct atalk_sock), NULL);
+ sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1);
if (!sk)
goto out;
rc = 0;
sock->ops = &atalk_dgram_ops;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
/* Checksums on by default */
sock_set_flag(sk, SOCK_ZAPPED);
@@ -1874,6 +1878,11 @@ static char atalk_err_snap[] __initdata =
/* Called by proto.c on kernel start up */
static int __init atalk_init(void)
{
+ int rc = proto_register(&ddp_proto, 0);
+
+ if (rc != 0)
+ goto out;
+
(void)sock_register(&atalk_family_ops);
ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv);
if (!ddp_dl)
@@ -1886,7 +1895,8 @@ static int __init atalk_init(void)
aarp_proto_init();
atalk_proc_init();
atalk_register_sysctl();
- return 0;
+out:
+ return rc;
}
module_init(atalk_init);
@@ -1911,6 +1921,7 @@ static void __exit atalk_exit(void)
dev_remove_pack(&ppptalk_packet_type);
unregister_snap_client(ddp_dl);
sock_unregister(PF_APPLETALK);
+ proto_unregister(&ddp_proto);
}
module_exit(atalk_exit);
diff --git a/net/atm/common.c b/net/atm/common.c
index 30a6a753256055..6d16be334ea0a3 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -127,6 +127,11 @@ static void vcc_write_space(struct sock *sk)
read_unlock(&sk->sk_callback_lock);
}
+static struct proto vcc_proto = {
+ .name = "VCC",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct atm_vcc),
+};
int vcc_create(struct socket *sock, int protocol, int family)
{
@@ -136,11 +141,10 @@ int vcc_create(struct socket *sock, int protocol, int family)
sock->sk = NULL;
if (sock->type == SOCK_STREAM)
return -EINVAL;
- sk = sk_alloc(family, GFP_KERNEL, sizeof(struct atm_vcc), NULL);
+ sk = sk_alloc(family, GFP_KERNEL, &vcc_proto, 1);
if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_state_change = vcc_def_wakeup;
sk->sk_write_space = vcc_write_space;
@@ -157,7 +161,6 @@ int vcc_create(struct socket *sock, int protocol, int family)
vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
vcc->atm_options = vcc->aal_options = 0;
sk->sk_destruct = vcc_sock_destruct;
- sock->sk = sk;
return 0;
}
@@ -759,24 +762,30 @@ static int __init atm_init(void)
{
int error;
+ if ((error = proto_register(&vcc_proto, 0)) < 0)
+ goto out;
+
if ((error = atmpvc_init()) < 0) {
printk(KERN_ERR "atmpvc_init() failed with %d\n", error);
- goto failure;
+ goto out_unregister_vcc_proto;
}
if ((error = atmsvc_init()) < 0) {
printk(KERN_ERR "atmsvc_init() failed with %d\n", error);
- goto failure;
+ goto out_atmpvc_exit;
}
if ((error = atm_proc_init()) < 0) {
printk(KERN_ERR "atm_proc_init() failed with %d\n",error);
- goto failure;
+ goto out_atmsvc_exit;
}
- return 0;
-
-failure:
- atmsvc_exit();
- atmpvc_exit();
+out:
return error;
+out_atmsvc_exit:
+ atmsvc_exit();
+out_atmpvc_exit:
+ atmsvc_exit();
+out_unregister_vcc_proto:
+ proto_unregister(&vcc_proto);
+ goto out;
}
static void __exit atm_exit(void)
@@ -784,6 +793,7 @@ static void __exit atm_exit(void)
atm_proc_exit();
atmsvc_exit();
atmpvc_exit();
+ proto_unregister(&vcc_proto);
}
module_init(atm_init);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index fbef221c2f6577..33b1a376302702 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -760,6 +760,16 @@ out:
return res;
}
+/*
+ * XXX: when creating ax25_sock we should update the .obj_size setting
+ * below.
+ */
+static struct proto ax25_proto = {
+ .name = "AX25",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct sock),
+};
+
static int ax25_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -810,7 +820,7 @@ static int ax25_create(struct socket *sock, int protocol)
return -ESOCKTNOSUPPORT;
}
- if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1, NULL)) == NULL)
+ if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
return -ENOMEM;
ax25 = sk->sk_protinfo = ax25_create_cb();
@@ -820,7 +830,6 @@ static int ax25_create(struct socket *sock, int protocol)
}
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_destruct = ax25_free_sock;
sock->ops = &ax25_proto_ops;
@@ -836,7 +845,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
struct sock *sk;
ax25_cb *ax25, *oax25;
- if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1, NULL)) == NULL)
+ if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
return NULL;
if ((ax25 = ax25_create_cb()) == NULL) {
@@ -856,7 +865,6 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
}
sock_init_data(NULL, sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_destruct = ax25_free_sock;
sk->sk_type = osk->sk_type;
@@ -1998,6 +2006,11 @@ EXPORT_SYMBOL(ax25_display_timer);
static int __init ax25_init(void)
{
+ int rc = proto_register(&ax25_proto, 0);
+
+ if (rc != 0)
+ goto out;
+
sock_register(&ax25_family_ops);
dev_add_pack(&ax25_packet_type);
register_netdevice_notifier(&ax25_dev_notifier);
@@ -2006,8 +2019,8 @@ static int __init ax25_init(void)
proc_net_fops_create("ax25_route", S_IRUGO, &ax25_route_fops);
proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops);
proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops);
-
- return 0;
+out:
+ return rc;
}
module_init(ax25_init);
@@ -2032,5 +2045,6 @@ static void __exit ax25_exit(void)
dev_remove_pack(&ax25_packet_type);
sock_unregister(PF_AX25);
+ proto_unregister(&ax25_proto);
}
module_exit(ax25_exit);
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index b17a39ee8161f9..9a8d99a39b6dbc 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -167,6 +167,12 @@ static struct proto_ops bnep_sock_ops = {
.mmap = sock_no_mmap
};
+static struct proto bnep_proto = {
+ .name = "BNEP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct bt_sock)
+};
+
static int bnep_sock_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -176,13 +182,12 @@ static int bnep_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct bt_sock), NULL)))
+ sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
+ if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
-
sock->ops = &bnep_sock_ops;
sock->state = SS_UNCONNECTED;
@@ -203,13 +208,30 @@ static struct net_proto_family bnep_sock_family_ops = {
int __init bnep_sock_init(void)
{
- bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
+ int err;
+
+ err = proto_register(&bnep_proto, 0);
+ if (err < 0)
+ return err;
+
+ err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops);
+ if (err < 0)
+ goto error;
+
return 0;
+
+error:
+ BT_ERR("Can't register BNEP socket");
+ proto_unregister(&bnep_proto);
+ return err;
}
int __exit bnep_sock_cleanup(void)
{
- if (bt_sock_unregister(BTPROTO_BNEP))
+ if (bt_sock_unregister(BTPROTO_BNEP) < 0)
BT_ERR("Can't unregister BNEP socket");
+
+ proto_unregister(&bnep_proto);
+
return 0;
}
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index e4beaad22adf65..4c7f9e20dade01 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -158,6 +158,12 @@ static struct proto_ops cmtp_sock_ops = {
.mmap = sock_no_mmap
};
+static struct proto cmtp_proto = {
+ .name = "CMTP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct bt_sock)
+};
+
static int cmtp_sock_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -167,13 +173,12 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct bt_sock), NULL)))
+ sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
+ if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
-
sock->ops = &cmtp_sock_ops;
sock->state = SS_UNCONNECTED;
@@ -194,13 +199,28 @@ static struct net_proto_family cmtp_sock_family_ops = {
int cmtp_init_sockets(void)
{
- bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
+ int err;
+
+ err = proto_register(&cmtp_proto, 0);
+ if (err < 0)
+ return err;
+
+ err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops);
+ if (err < 0)
+ goto error;
return 0;
+
+error:
+ BT_ERR("Can't register CMTP socket");
+ proto_unregister(&cmtp_proto);
+ return err;
}
void cmtp_cleanup_sockets(void)
{
- if (bt_sock_unregister(BTPROTO_CMTP))
+ if (bt_sock_unregister(BTPROTO_CMTP) < 0)
BT_ERR("Can't unregister CMTP socket");
+
+ proto_unregister(&cmtp_proto);
}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 841bdba0b877a0..c9792ba751221e 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -590,6 +590,12 @@ static struct proto_ops hci_sock_ops = {
.mmap = sock_no_mmap
};
+static struct proto hci_sk_proto = {
+ .name = "HCI",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct hci_pinfo)
+};
+
static int hci_sock_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -601,7 +607,7 @@ static int hci_sock_create(struct socket *sock, int protocol)
sock->ops = &hci_sock_ops;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct hci_pinfo), NULL);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
if (!sk)
return -ENOMEM;
@@ -611,8 +617,6 @@ static int hci_sock_create(struct socket *sock, int protocol)
sk->sk_protocol = protocol;
- sk_set_owner(sk, THIS_MODULE);
-
sock->state = SS_UNCONNECTED;
sk->sk_state = BT_OPEN;
@@ -668,23 +672,36 @@ static struct notifier_block hci_sock_nblock = {
int __init hci_sock_init(void)
{
- if (bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops)) {
- BT_ERR("HCI socket registration failed");
- return -EPROTO;
- }
+ int err;
+
+ err = proto_register(&hci_sk_proto, 0);
+ if (err < 0)
+ return err;
+
+ err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops);
+ if (err < 0)
+ goto error;
hci_register_notifier(&hci_sock_nblock);
BT_INFO("HCI socket layer initialized");
return 0;
+
+error:
+ BT_ERR("HCI socket registration failed");
+ proto_unregister(&hci_sk_proto);
+ return err;
}
int __exit hci_sock_cleanup(void)
{
- if (bt_sock_unregister(BTPROTO_HCI))
+ if (bt_sock_unregister(BTPROTO_HCI) < 0)
BT_ERR("HCI socket unregistration failed");
hci_unregister_notifier(&hci_sock_nblock);
+
+ proto_unregister(&hci_sk_proto);
+
return 0;
}
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index dc642f667eea59..fabb36d4666b4b 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -164,6 +164,12 @@ static struct proto_ops hidp_sock_ops = {
.mmap = sock_no_mmap
};
+static struct proto hidp_proto = {
+ .name = "HIDP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct bt_sock)
+};
+
static int hidp_sock_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -173,13 +179,12 @@ static int hidp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- if (!(sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, sizeof(struct bt_sock), NULL)))
+ sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1);
+ if (!sk)
return -ENOMEM;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
-
sock->ops = &hidp_sock_ops;
sock->state = SS_UNCONNECTED;
@@ -202,10 +207,19 @@ int __init hidp_init_sockets(void)
{
int err;
+ err = proto_register(&hidp_proto, 0);
+ if (err < 0)
+ return err;
+
err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops);
if (err < 0)
- BT_ERR("Can't register HIDP socket");
+ goto error;
+ return 0;
+
+error:
+ BT_ERR("Can't register HIDP socket");
+ proto_unregister(&hidp_proto);
return err;
}
@@ -213,4 +227,6 @@ void __exit hidp_cleanup_sockets(void)
{
if (bt_sock_unregister(BTPROTO_HIDP) < 0)
BT_ERR("Can't unregister HIDP socket");
+
+ proto_unregister(&hidp_proto);
}
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 59b58661c1a829..c12babcf0b3ccb 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -367,19 +367,23 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
}
+static struct proto l2cap_proto = {
+ .name = "L2CAP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct l2cap_pinfo)
+};
+
static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio)
{
struct sock *sk;
- sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct l2cap_pinfo), NULL);
+ sk = sk_alloc(PF_BLUETOOTH, prio, &l2cap_proto, 1);
if (!sk)
return NULL;
sock_init_data(sock, sk);
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
- sk_set_owner(sk, THIS_MODULE);
-
sk->sk_destruct = l2cap_sock_destruct;
sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
@@ -2263,15 +2267,22 @@ static struct hci_proto l2cap_hci_proto = {
static int __init l2cap_init(void)
{
int err;
+
+ err = proto_register(&l2cap_proto, 0);
+ if (err < 0)
+ return err;
- if ((err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops))) {
+ err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
+ if (err < 0) {
BT_ERR("L2CAP socket registration failed");
- return err;
+ goto error;
}
- if ((err = hci_register_proto(&l2cap_hci_proto))) {
+ err = hci_register_proto(&l2cap_hci_proto);
+ if (err < 0) {
BT_ERR("L2CAP protocol registration failed");
- return err;
+ bt_sock_unregister(BTPROTO_L2CAP);
+ goto error;
}
l2cap_proc_init();
@@ -2280,18 +2291,23 @@ static int __init l2cap_init(void)
BT_INFO("L2CAP socket layer initialized");
return 0;
+
+error:
+ proto_unregister(&l2cap_proto);
+ return err;
}
static void __exit l2cap_exit(void)
{
l2cap_proc_cleanup();
- /* Unregister socket and protocol */
- if (bt_sock_unregister(BTPROTO_L2CAP))
+ if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
BT_ERR("L2CAP socket unregistration failed");
- if (hci_unregister_proto(&l2cap_hci_proto))
+ if (hci_unregister_proto(&l2cap_hci_proto) < 0)
BT_ERR("L2CAP protocol unregistration failed");
+
+ proto_unregister(&l2cap_proto);
}
void l2cap_load(void)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 097e007cd9b0dc..640028a2183cd9 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -279,20 +279,24 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
pi->dlc->link_mode = pi->link_mode;
}
+static struct proto rfcomm_proto = {
+ .name = "RFCOMM",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct rfcomm_pinfo)
+};
+
static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio)
{
struct rfcomm_dlc *d;
struct sock *sk;
- sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct rfcomm_pinfo), NULL);
+ sk = sk_alloc(PF_BLUETOOTH, prio, &rfcomm_proto, 1);
if (!sk)
return NULL;
sock_init_data(sock, sk);
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
- sk_set_owner(sk, THIS_MODULE);
-
d = rfcomm_dlc_alloc(prio);
if (!d) {
sk_free(sk);
@@ -975,24 +979,32 @@ int __init rfcomm_init_sockets(void)
{
int err;
- if ((err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops))) {
- BT_ERR("RFCOMM socket layer registration failed. %d", err);
+ err = proto_register(&rfcomm_proto, 0);
+ if (err < 0)
return err;
- }
+
+ err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops);
+ if (err < 0)
+ goto error;
rfcomm_sock_proc_init();
BT_INFO("RFCOMM socket layer initialized");
+
return 0;
+
+error:
+ BT_ERR("RFCOMM socket layer registration failed");
+ proto_unregister(&rfcomm_proto);
+ return err;
}
void __exit rfcomm_cleanup_sockets(void)
{
- int err;
-
rfcomm_sock_proc_cleanup();
- /* Unregister socket, protocol and notifier */
- if ((err = bt_sock_unregister(BTPROTO_RFCOMM)))
- BT_ERR("RFCOMM socket layer unregistration failed. %d", err);
+ if (bt_sock_unregister(BTPROTO_RFCOMM) < 0)
+ BT_ERR("RFCOMM socket layer unregistration failed");
+
+ proto_unregister(&rfcomm_proto);
}
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index d1361367d74955..3e750ef09e6011 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -349,7 +349,7 @@ static void sco_sock_cleanup_listen(struct sock *parent)
}
parent->sk_state = BT_CLOSED;
- sock_set_flag(sk, SOCK_ZAPPED);
+ sock_set_flag(parent, SOCK_ZAPPED);
}
/* Kill socket (only if zapped and orphan)
@@ -413,19 +413,23 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)
sk->sk_type = parent->sk_type;
}
+static struct proto sco_proto = {
+ .name = "SCO",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct sco_pinfo)
+};
+
static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio)
{
struct sock *sk;
- sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct sco_pinfo), NULL);
+ sk = sk_alloc(PF_BLUETOOTH, prio, &sco_proto, 1);
if (!sk)
return NULL;
sock_init_data(sock, sk);
INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
- sk_set_owner(sk, THIS_MODULE);
-
sk->sk_destruct = sco_sock_destruct;
sk->sk_sndtimeo = SCO_CONN_TIMEOUT;
@@ -1015,14 +1019,21 @@ static int __init sco_init(void)
{
int err;
- if ((err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops))) {
- BT_ERR("SCO socket registration failed");
+ err = proto_register(&sco_proto, 0);
+ if (err < 0)
return err;
+
+ err = bt_sock_register(BTPROTO_SCO, &sco_sock_family_ops);
+ if (err < 0) {
+ BT_ERR("SCO socket registration failed");
+ goto error;
}
- if ((err = hci_register_proto(&sco_hci_proto))) {
+ err = hci_register_proto(&sco_hci_proto);
+ if (err < 0) {
BT_ERR("SCO protocol registration failed");
- return err;
+ bt_sock_unregister(BTPROTO_SCO);
+ goto error;
}
sco_proc_init();
@@ -1031,20 +1042,23 @@ static int __init sco_init(void)
BT_INFO("SCO socket layer initialized");
return 0;
+
+error:
+ proto_unregister(&sco_proto);
+ return err;
}
static void __exit sco_exit(void)
{
- int err;
-
sco_proc_cleanup();
- /* Unregister socket, protocol and notifier */
- if ((err = bt_sock_unregister(BTPROTO_SCO)))
- BT_ERR("SCO socket unregistration failed. %d", err);
+ if (bt_sock_unregister(BTPROTO_SCO) < 0)
+ BT_ERR("SCO socket unregistration failed");
+
+ if (hci_unregister_proto(&sco_hci_proto) < 0)
+ BT_ERR("SCO protocol unregistration failed");
- if ((err = hci_unregister_proto(&sco_hci_proto)))
- BT_ERR("SCO protocol unregistration failed. %d", err);
+ proto_unregister(&sco_proto);
}
module_init(sco_init);
diff --git a/net/core/sock.c b/net/core/sock.c
index 18365fb8853f98..29e8a34d83edb4 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -99,6 +99,8 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
@@ -613,48 +615,36 @@ lenout:
return 0;
}
-static kmem_cache_t *sk_cachep;
-
/**
* sk_alloc - All socket objects are allocated here
* @family - protocol family
* @priority - for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
- * @zero_it - zeroes the allocated sock
- * @slab - alternate slab
- *
- * All socket objects are allocated here. If @zero_it is non-zero
- * it should have the size of the are to be zeroed, because the
- * private slabcaches have different sizes of the generic struct sock.
- * 1 has been kept as a way to say sizeof(struct sock).
+ * @prot - struct proto associated with this new sock instance
+ * @zero_it - if we should zero the newly allocated sock
*/
-struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
+struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it)
{
struct sock *sk = NULL;
-
- /*
- * Transitional, this test will be removed when sk_cachep is killed
- */
- if (slab == NULL && zero_it == 1)
- slab = sk_cachep;
+ kmem_cache_t *slab = prot->slab;
if (slab != NULL)
sk = kmem_cache_alloc(slab, priority);
else
- sk = kmalloc(zero_it, priority);
+ sk = kmalloc(prot->obj_size, priority);
if (sk) {
if (zero_it) {
- memset(sk, 0,
- zero_it == 1 ? sizeof(struct sock) : zero_it);
+ memset(sk, 0, prot->obj_size);
sk->sk_family = family;
+ sk->sk_prot = prot;
sock_lock_init(sk);
}
- sk->sk_slab = slab;
if (security_sk_alloc(sk, family, priority)) {
kmem_cache_free(slab, sk);
sk = NULL;
- }
+ } else
+ __module_get(prot->owner);
}
return sk;
}
@@ -662,7 +652,7 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
void sk_free(struct sock *sk)
{
struct sk_filter *filter;
- struct module *owner = sk->sk_owner;
+ struct module *owner = sk->sk_prot->owner;
if (sk->sk_destruct)
sk->sk_destruct(sk);
@@ -680,8 +670,8 @@ void sk_free(struct sock *sk)
__FUNCTION__, atomic_read(&sk->sk_omem_alloc));
security_sk_free(sk);
- if (sk->sk_slab != NULL)
- kmem_cache_free(sk->sk_slab, sk);
+ if (sk->sk_prot->slab != NULL)
+ kmem_cache_free(sk->sk_prot->slab, sk);
else
kfree(sk);
module_put(owner);
@@ -689,11 +679,6 @@ void sk_free(struct sock *sk)
void __init sk_init(void)
{
- sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (!sk_cachep)
- printk(KERN_CRIT "sk_init: Cannot create sock SLAB cache!");
-
if (num_physpages <= 4096) {
sysctl_wmem_max = 32767;
sysctl_rmem_max = 32767;
@@ -1227,7 +1212,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->sk_rcvlowat = 1;
sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
- sk->sk_owner = NULL;
sk->sk_stamp.tv_sec = -1L;
sk->sk_stamp.tv_usec = -1L;
@@ -1368,32 +1352,183 @@ void sk_common_release(struct sock *sk)
EXPORT_SYMBOL(sk_common_release);
-int sk_alloc_slab(struct proto *prot, char *name)
+static rwlock_t proto_list_lock;
+static LIST_HEAD(proto_list);
+
+int proto_register(struct proto *prot, int alloc_slab)
{
- prot->slab = kmem_cache_create(name,
- prot->slab_obj_size, 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ int rc = -ENOBUFS;
- if (prot->slab == NULL) {
- printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
- prot->name);
- return -ENOBUFS;
+ write_lock(&proto_list_lock);
+
+ if (alloc_slab) {
+ prot->slab = kmem_cache_create(prot->name, prot->obj_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+ if (prot->slab == NULL) {
+ printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n",
+ prot->name);
+ goto out_unlock;
+ }
}
- return 0;
+ list_add(&prot->node, &proto_list);
+ rc = 0;
+out_unlock:
+ write_unlock(&proto_list_lock);
+ return rc;
}
-EXPORT_SYMBOL(sk_alloc_slab);
+EXPORT_SYMBOL(proto_register);
-void sk_free_slab(struct proto *prot)
+void proto_unregister(struct proto *prot)
{
+ write_lock(&proto_list_lock);
+
if (prot->slab != NULL) {
kmem_cache_destroy(prot->slab);
prot->slab = NULL;
}
+
+ list_del(&prot->node);
+ write_unlock(&proto_list_lock);
+}
+
+EXPORT_SYMBOL(proto_unregister);
+
+#ifdef CONFIG_PROC_FS
+static inline struct proto *__proto_head(void)
+{
+ return list_entry(proto_list.next, struct proto, node);
+}
+
+static inline struct proto *proto_head(void)
+{
+ return list_empty(&proto_list) ? NULL : __proto_head();
+}
+
+static inline struct proto *proto_next(struct proto *proto)
+{
+ return proto->node.next == &proto_list ? NULL :
+ list_entry(proto->node.next, struct proto, node);
+}
+
+static inline struct proto *proto_get_idx(loff_t pos)
+{
+ struct proto *proto;
+ loff_t i = 0;
+
+ list_for_each_entry(proto, &proto_list, node)
+ if (i++ == pos)
+ goto out;
+
+ proto = NULL;
+out:
+ return proto;
}
-EXPORT_SYMBOL(sk_free_slab);
+static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ read_lock(&proto_list_lock);
+ return *pos ? proto_get_idx(*pos - 1) : SEQ_START_TOKEN;
+}
+
+static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ return v == SEQ_START_TOKEN ? proto_head() : proto_next(v);
+}
+
+static void proto_seq_stop(struct seq_file *seq, void *v)
+{
+ read_unlock(&proto_list_lock);
+}
+
+static char proto_method_implemented(const void *method)
+{
+ return method == NULL ? 'n' : 'y';
+}
+
+static void proto_seq_printf(struct seq_file *seq, struct proto *proto)
+{
+ seq_printf(seq, "%-9s %4u %6d %6d %-3s %6u %-3s %-10s "
+ "%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n",
+ proto->name,
+ proto->obj_size,
+ proto->sockets_allocated != NULL ? atomic_read(proto->sockets_allocated) : -1,
+ proto->memory_allocated != NULL ? atomic_read(proto->memory_allocated) : -1,
+ proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI",
+ proto->max_header,
+ proto->slab == NULL ? "no" : "yes",
+ module_name(proto->owner),
+ proto_method_implemented(proto->close),
+ proto_method_implemented(proto->connect),
+ proto_method_implemented(proto->disconnect),
+ proto_method_implemented(proto->accept),
+ proto_method_implemented(proto->ioctl),
+ proto_method_implemented(proto->init),
+ proto_method_implemented(proto->destroy),
+ proto_method_implemented(proto->shutdown),
+ proto_method_implemented(proto->setsockopt),
+ proto_method_implemented(proto->getsockopt),
+ proto_method_implemented(proto->sendmsg),
+ proto_method_implemented(proto->recvmsg),
+ proto_method_implemented(proto->sendpage),
+ proto_method_implemented(proto->bind),
+ proto_method_implemented(proto->backlog_rcv),
+ proto_method_implemented(proto->hash),
+ proto_method_implemented(proto->unhash),
+ proto_method_implemented(proto->get_port),
+ proto_method_implemented(proto->enter_memory_pressure));
+}
+
+static int proto_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == SEQ_START_TOKEN)
+ seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s",
+ "protocol",
+ "size",
+ "sockets",
+ "memory",
+ "press",
+ "maxhdr",
+ "slab",
+ "module",
+ "cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n");
+ else
+ proto_seq_printf(seq, v);
+ return 0;
+}
+
+static struct seq_operations proto_seq_ops = {
+ .start = proto_seq_start,
+ .next = proto_seq_next,
+ .stop = proto_seq_stop,
+ .show = proto_seq_show,
+};
+
+static int proto_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &proto_seq_ops);
+}
+
+static struct file_operations proto_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = proto_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init proto_init(void)
+{
+ /* register /proc/net/protocols */
+ return proc_net_fops_create("protocols", S_IRUGO, &proto_seq_fops) == NULL ? -ENOBUFS : 0;
+}
+
+subsys_initcall(proto_init);
+
+#endif /* PROC_FS */
EXPORT_SYMBOL(sk_alloc);
EXPORT_SYMBOL(sk_free);
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 442075a7eaec01..29bb3cd219655b 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -149,7 +149,6 @@ static void dn_keepalive(struct sock *sk);
#define DN_SK_HASH_MASK (DN_SK_HASH_SIZE - 1)
-static kmem_cache_t *dn_sk_cachep;
static struct proto_ops dn_proto_ops;
static DEFINE_RWLOCK(dn_hash_lock);
static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
@@ -447,11 +446,16 @@ static void dn_destruct(struct sock *sk)
dst_release(xchg(&sk->sk_dst_cache, NULL));
}
+static struct proto dn_proto = {
+ .name = "DECNET",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct dn_sock),
+};
+
static struct sock *dn_alloc_sock(struct socket *sock, int gfp)
{
struct dn_scp *scp;
- struct sock *sk = sk_alloc(PF_DECnet, gfp, sizeof(struct dn_sock),
- dn_sk_cachep);
+ struct sock *sk = sk_alloc(PF_DECnet, gfp, &dn_proto, 1);
if (!sk)
goto out;
@@ -459,7 +463,6 @@ static struct sock *dn_alloc_sock(struct socket *sock, int gfp)
if (sock)
sock->ops = &dn_proto_ops;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_backlog_rcv = dn_nsp_backlog_rcv;
sk->sk_destruct = dn_destruct;
@@ -2349,14 +2352,13 @@ static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.68s (
static int __init decnet_init(void)
{
+ int rc;
+
printk(banner);
- dn_sk_cachep = kmem_cache_create("decnet_socket_cache",
- sizeof(struct dn_sock),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (!dn_sk_cachep)
- return -ENOMEM;
+ rc = proto_register(&dn_proto, 1);
+ if (rc != 0)
+ goto out;
dn_neigh_init();
dn_dev_init();
@@ -2369,8 +2371,8 @@ static int __init decnet_init(void)
proc_net_fops_create("decnet", S_IRUGO, &dn_socket_seq_fops);
dn_register_sysctl();
-
- return 0;
+out:
+ return rc;
}
module_init(decnet_init);
@@ -2397,7 +2399,7 @@ static void __exit decnet_exit(void)
proc_net_remove("decnet");
- kmem_cache_destroy(dn_sk_cachep);
+ proto_unregister(&dn_proto);
}
module_exit(decnet_exit);
#endif
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 70f01713d89b08..de691e119e173f 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -555,6 +555,12 @@ static int econet_release(struct socket *sock)
return 0;
}
+static struct proto econet_proto = {
+ .name = "ECONET",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct econet_sock),
+};
+
/*
* Create an Econet socket
*/
@@ -572,15 +578,13 @@ static int econet_create(struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
err = -ENOBUFS;
- sk = sk_alloc(PF_ECONET, GFP_KERNEL,
- sizeof(struct econet_sock), NULL);
+ sk = sk_alloc(PF_ECONET, GFP_KERNEL, &econet_proto, 1);
if (sk == NULL)
goto out;
sk->sk_reuse = 1;
sock->ops = &econet_ops;
- sock_init_data(sock,sk);
- sk_set_owner(sk, THIS_MODULE);
+ sock_init_data(sock, sk);
eo = ec_sk(sk);
sock_reset_flag(sk, SOCK_ZAPPED);
@@ -1096,10 +1100,15 @@ static void __exit econet_proto_exit(void)
#endif
unregister_netdevice_notifier(&econet_netdev_notifier);
sock_unregister(econet_family_ops.family);
+ proto_unregister(&econet_proto);
}
static int __init econet_proto_init(void)
{
+ int err = proto_register(&econet_proto, 0);
+
+ if (err != 0)
+ goto out;
sock_register(&econet_family_ops);
#ifdef CONFIG_ECONET_AUNUDP
spin_lock_init(&aun_queue_lock);
@@ -1109,7 +1118,8 @@ static int __init econet_proto_init(void)
econet_hw_initialise();
#endif
register_netdevice_notifier(&econet_netdev_notifier);
- return 0;
+out:
+ return err;
}
module_init(econet_proto_init);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index aa4fb251c54c7c..c34dab67e4612a 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -281,14 +281,11 @@ static int inet_create(struct socket *sock, int protocol)
BUG_TRAP(answer_prot->slab != NULL);
err = -ENOBUFS;
- sk = sk_alloc(PF_INET, GFP_KERNEL,
- answer_prot->slab_obj_size,
- answer_prot->slab);
+ sk = sk_alloc(PF_INET, GFP_KERNEL, answer_prot, 1);
if (sk == NULL)
goto out;
err = 0;
- sk->sk_prot = answer_prot;
sk->sk_no_check = answer_no_check;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
@@ -309,7 +306,6 @@ static int inet_create(struct socket *sock, int protocol)
inet->id = 0;
sock_init_data(sock, sk);
- sk_set_owner(sk, sk->sk_prot->owner);
sk->sk_destruct = inet_sock_destruct;
sk->sk_family = PF_INET;
@@ -1026,17 +1022,17 @@ static int __init inet_init(void)
goto out;
}
- rc = sk_alloc_slab(&tcp_prot, "tcp_sock");
+ rc = proto_register(&tcp_prot, 1);
if (rc)
goto out;
- rc = sk_alloc_slab(&udp_prot, "udp_sock");
+ rc = proto_register(&udp_prot, 1);
if (rc)
- goto out_tcp_free_slab;
+ goto out_unregister_tcp_proto;
- rc = sk_alloc_slab(&raw_prot, "raw_sock");
+ rc = proto_register(&raw_prot, 1);
if (rc)
- goto out_udp_free_slab;
+ goto out_unregister_udp_proto;
/*
* Tell SOCKET that we are alive...
@@ -1110,10 +1106,10 @@ static int __init inet_init(void)
rc = 0;
out:
return rc;
-out_tcp_free_slab:
- sk_free_slab(&tcp_prot);
-out_udp_free_slab:
- sk_free_slab(&udp_prot);
+out_unregister_tcp_proto:
+ proto_unregister(&tcp_prot);
+out_unregister_udp_proto:
+ proto_unregister(&udp_prot);
goto out;
}
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 25b94e0be09ee4..eea7ef0107767d 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -389,7 +389,6 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
struct in_device *in_dev;
struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
struct in_ifaddr *ifa, **ifap;
- int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
ASSERT_RTNL();
@@ -400,13 +399,12 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
ifap = &ifa->ifa_next) {
if ((rta[IFA_LOCAL - 1] &&
- (!inet_ifa_match_local_prefixlen(ifm, ifa) ||
memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
- &ifa->ifa_local, 4))) ||
+ &ifa->ifa_local, 4)) ||
(rta[IFA_LABEL - 1] &&
rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||
(rta[IFA_ADDRESS - 1] &&
- (real_prefixlen != ifa->ifa_prefixlen ||
+ (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
!inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
ifa))))
continue;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 49eef7b3ec40ed..1a23c5263b993a 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -167,32 +167,22 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
hdr_len = iph->ihl * 4;
if ((skb->len - hdr_len) < ipcd->threshold) {
/* Don't bother compressing */
- if (x->props.mode) {
- ip_send_check(iph);
- }
goto out_ok;
}
if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
skb_linearize(skb, GFP_ATOMIC) != 0) {
- err = -ENOMEM;
- goto error;
+ goto out_ok;
}
err = ipcomp_compress(x, skb);
+ iph = skb->nh.iph;
+
if (err) {
- if (err == -EMSGSIZE) {
- if (x->props.mode) {
- iph = skb->nh.iph;
- ip_send_check(iph);
- }
- goto out_ok;
- }
- goto error;
+ goto out_ok;
}
/* Install ipcomp header, convert into ipcomp datagram. */
- iph = skb->nh.iph;
iph->tot_len = htons(skb->len);
ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4);
ipch->nexthdr = iph->protocol;
@@ -200,12 +190,12 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
ipch->cpi = htons((u16 )ntohl(x->id.spi));
iph->protocol = IPPROTO_COMP;
ip_send_check(iph);
+ return 0;
out_ok:
- err = 0;
-
-error:
- return err;
+ if (x->props.mode)
+ ip_send_check(iph);
+ return 0;
}
static void ipcomp4_err(struct sk_buff *skb, u32 info)
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 7b923d40861e1a..f1937190cd771c 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -42,8 +42,6 @@
/* FIXME: this is just for IP_NF_ASSERRT */
#include <linux/netfilter_ipv4/ip_conntrack.h>
-#define MS2JIFFIES(x) ((x*HZ)/1000)
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables match for limiting per hash-bucket");
@@ -117,18 +115,18 @@ hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst)
static inline struct dsthash_ent *
__dsthash_find(const struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
{
- struct dsthash_ent *ent = NULL;
+ struct dsthash_ent *ent;
struct hlist_node *pos;
u_int32_t hash = hash_dst(ht, dst);
if (!hlist_empty(&ht->hash[hash]))
hlist_for_each_entry(ent, pos, &ht->hash[hash], node) {
if (dst_cmp(ent, dst)) {
- break;
+ return ent;
}
}
- return ent;
+ return NULL;
}
/* allocate dsthash_ent, initialize dst, put in htable and lock it */
@@ -230,7 +228,7 @@ static int htable_create(struct ipt_hashlimit_info *minfo)
hinfo->pde->data = hinfo;
init_timer(&hinfo->timer);
- hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
+ hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval);
hinfo->timer.data = (unsigned long )hinfo;
hinfo->timer.function = htable_gc;
add_timer(&hinfo->timer);
@@ -281,7 +279,7 @@ static void htable_gc(unsigned long htlong)
htable_selective_cleanup(ht, select_gc);
/* re-add the timer accordingly */
- ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
+ ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval);
add_timer(&ht->timer);
}
@@ -475,7 +473,7 @@ hashlimit_match(const struct sk_buff *skb,
return 0;
}
- dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
+ dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
dh->rateinfo.prev = jiffies;
dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
@@ -489,7 +487,7 @@ hashlimit_match(const struct sk_buff *skb,
}
/* update expiration timeout */
- dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
+ dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
rateinfo_recalc(dh, now);
if (dh->rateinfo.credit >= dh->rateinfo.cost) {
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 1e71ed6507fd48..93624a32eb9ae3 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -724,7 +724,7 @@ struct proto raw_prot = {
.backlog_rcv = raw_rcv_skb,
.hash = raw_v4_hash,
.unhash = raw_v4_unhash,
- .slab_obj_size = sizeof(struct raw_sock),
+ .obj_size = sizeof(struct raw_sock),
};
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 4b87a4f11f4656..e923d2f021aa8b 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -179,10 +179,9 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct sock *child;
child = tp->af_specific->syn_recv_sock(sk, skb, req, dst);
- if (child) {
- sk_set_owner(child, sk->sk_owner);
+ if (child)
tcp_acceptq_queue(sk, req, child);
- } else
+ else
tcp_openreq_free(req);
return child;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index fa30d1d83d0377..3ac6659869c41e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2614,7 +2614,7 @@ struct proto tcp_prot = {
.sysctl_wmem = sysctl_tcp_wmem,
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
- .slab_obj_size = sizeof(struct tcp_sock),
+ .obj_size = sizeof(struct tcp_sock),
};
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 2faf1a9c3eba26..fd70509f0d53df 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -688,8 +688,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
{
/* allocate the newsk from the same slab of the master sock,
* if not, at sk_free time we'll try to free it from the wrong
- * slabcache (i.e. is it TCPv4 or v6?) -acme */
- struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0, sk->sk_prot->slab);
+ * slabcache (i.e. is it TCPv4 or v6?), this is handled thru sk->sk_prot -acme */
+ struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, sk->sk_prot, 0);
if(newsk != NULL) {
struct tcp_sock *newtp;
@@ -807,7 +807,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
keepalive_time_when(newtp));
newsk->sk_socket = NULL;
newsk->sk_sleep = NULL;
- newsk->sk_owner = NULL;
newtp->rx_opt.tstamp_ok = req->tstamp_ok;
if((newtp->rx_opt.sack_ok = req->sack_ok) != 0) {
@@ -1019,7 +1018,6 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
if (child == NULL)
goto listen_overflow;
- sk_set_owner(child, sk->sk_owner);
tcp_synq_unlink(tp, req, prev);
tcp_synq_removed(sk, req);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index eac0bd84d7a674..6baddfbedca3f9 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1371,7 +1371,7 @@ struct proto udp_prot = {
.hash = udp_v4_hash,
.unhash = udp_v4_unhash,
.get_port = udp_v4_get_port,
- .slab_obj_size = sizeof(struct udp_sock),
+ .obj_size = sizeof(struct udp_sock),
};
/* ------------------------------------------------------------------------ */
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 2f1e7b439e2f4c..768b11703daf7f 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -107,7 +107,7 @@ static void inet6_sock_destruct(struct sock *sk)
static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
{
- const int offset = sk->sk_prot->slab_obj_size - sizeof(struct ipv6_pinfo);
+ const int offset = sk->sk_prot->obj_size - sizeof(struct ipv6_pinfo);
return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
}
@@ -166,15 +166,11 @@ static int inet6_create(struct socket *sock, int protocol)
BUG_TRAP(answer_prot->slab != NULL);
rc = -ENOBUFS;
- sk = sk_alloc(PF_INET6, GFP_KERNEL,
- answer_prot->slab_obj_size,
- answer_prot->slab);
+ sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1);
if (sk == NULL)
goto out;
sock_init_data(sock, sk);
- sk->sk_prot = answer_prot;
- sk_set_owner(sk, sk->sk_prot->owner);
rc = 0;
sk->sk_no_check = answer_no_check;
@@ -710,17 +706,17 @@ static int __init inet6_init(void)
return -EINVAL;
}
- err = sk_alloc_slab(&tcpv6_prot, "tcpv6_sock");
+ err = proto_register(&tcpv6_prot, 1);
if (err)
goto out;
- err = sk_alloc_slab(&udpv6_prot, "udpv6_sock");
+ err = proto_register(&udpv6_prot, 1);
if (err)
- goto out_tcp_free_slab;
+ goto out_unregister_tcp_proto;
- err = sk_alloc_slab(&rawv6_prot, "rawv6_sock");
+ err = proto_register(&rawv6_prot, 1);
if (err)
- goto out_udp_free_slab;
+ goto out_unregister_udp_proto;
/* Register the socket-side information for inet6_create. */
@@ -740,7 +736,7 @@ static int __init inet6_init(void)
/* Initialise ipv6 mibs */
err = init_ipv6_mibs();
if (err)
- goto out_raw_free_slab;
+ goto out_unregister_raw_proto;
/*
* ipngwg API draft makes clear that the correct semantics
@@ -827,12 +823,12 @@ icmp_fail:
ipv6_sysctl_unregister();
#endif
cleanup_ipv6_mibs();
-out_raw_free_slab:
- sk_free_slab(&rawv6_prot);
-out_udp_free_slab:
- sk_free_slab(&udpv6_prot);
-out_tcp_free_slab:
- sk_free_slab(&tcpv6_prot);
+out_unregister_raw_proto:
+ proto_unregister(&rawv6_prot);
+out_unregister_udp_proto:
+ proto_unregister(&udpv6_prot);
+out_unregister_tcp_proto:
+ proto_unregister(&tcpv6_prot);
goto out;
}
module_init(inet6_init);
@@ -862,9 +858,9 @@ static void __exit inet6_exit(void)
ipv6_sysctl_unregister();
#endif
cleanup_ipv6_mibs();
- sk_free_slab(&rawv6_prot);
- sk_free_slab(&udpv6_prot);
- sk_free_slab(&tcpv6_prot);
+ proto_unregister(&rawv6_prot);
+ proto_unregister(&udpv6_prot);
+ proto_unregister(&tcpv6_prot);
}
module_exit(inet6_exit);
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index ecea6cf66055a2..6cde5310cd76b1 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -160,8 +160,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
skb_linearize(skb, GFP_ATOMIC) != 0) {
- err = -ENOMEM;
- goto error;
+ goto out_ok;
}
/* compression */
@@ -174,11 +173,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
tfm = *per_cpu_ptr(ipcd->tfms, cpu);
err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
- if (err) {
- put_cpu();
- goto error;
- }
- if ((dlen + sizeof(struct ipv6_comp_hdr)) >= plen) {
+ if (err || (dlen + sizeof(struct ipv6_comp_hdr)) >= plen) {
put_cpu();
goto out_ok;
}
@@ -198,10 +193,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
*skb->nh.raw = IPPROTO_COMP;
out_ok:
- err = 0;
-
-error:
- return err;
+ return 0;
}
static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a8b4acfab951b5..5488ad0de4f6bd 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -977,7 +977,7 @@ static int rawv6_init_sk(struct sock *sk)
}
struct proto rawv6_prot = {
- .name = "RAW",
+ .name = "RAWv6",
.owner = THIS_MODULE,
.close = rawv6_close,
.connect = ip6_datagram_connect,
@@ -993,7 +993,7 @@ struct proto rawv6_prot = {
.backlog_rcv = rawv6_rcv_skb,
.hash = raw_v6_hash,
.unhash = raw_v6_unhash,
- .slab_obj_size = sizeof(struct raw6_sock),
+ .obj_size = sizeof(struct raw6_sock),
};
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 40a50e82ed55aa..4760c85e19db83 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2235,7 +2235,7 @@ struct proto tcpv6_prot = {
.sysctl_wmem = sysctl_tcp_wmem,
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
- .slab_obj_size = sizeof(struct tcp6_sock),
+ .obj_size = sizeof(struct tcp6_sock),
};
static struct inet6_protocol tcpv6_protocol = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index badbcc26c338ae..e251d0ba4f3936 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1036,7 +1036,7 @@ void udp6_proc_exit(void) {
/* ------------------------------------------------------------------------ */
struct proto udpv6_prot = {
- .name = "UDP",
+ .name = "UDPv6",
.owner = THIS_MODULE,
.close = udpv6_close,
.connect = ip6_datagram_connect,
@@ -1051,7 +1051,7 @@ struct proto udpv6_prot = {
.hash = udp_v6_hash,
.unhash = udp_v6_unhash,
.get_port = udp_v6_get_port,
- .slab_obj_size = sizeof(struct udp6_sock),
+ .obj_size = sizeof(struct udp6_sock),
};
extern struct proto_ops inet6_dgram_ops;
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 65309f9d9e532d..5a27e5df5886e9 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -80,8 +80,6 @@ static struct proto_ops ipx_dgram_ops;
LIST_HEAD(ipx_interfaces);
DEFINE_SPINLOCK(ipx_interfaces_lock);
-static kmem_cache_t *ipx_sk_slab;
-
struct ipx_interface *ipx_primary_net;
struct ipx_interface *ipx_internal_net;
@@ -1347,6 +1345,12 @@ out:
return rc;
}
+static struct proto ipx_proto = {
+ .name = "IPX",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct ipx_sock),
+};
+
static int ipx_create(struct socket *sock, int protocol)
{
int rc = -ESOCKTNOSUPPORT;
@@ -1361,8 +1365,8 @@ static int ipx_create(struct socket *sock, int protocol)
if (sock->type != SOCK_DGRAM)
goto out;
- sk = sk_alloc(PF_IPX, GFP_KERNEL, sizeof(struct ipx_sock), ipx_sk_slab);
rc = -ENOMEM;
+ sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1);
if (!sk)
goto out;
#ifdef IPX_REFCNT_DEBUG
@@ -1371,7 +1375,6 @@ static int ipx_create(struct socket *sock, int protocol)
atomic_read(&ipx_sock_nr));
#endif
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_no_check = 1; /* Checksum off by default */
sock->ops = &ipx_dgram_ops;
rc = 0;
@@ -1954,12 +1957,10 @@ static char ipx_snap_err_msg[] __initdata =
static int __init ipx_init(void)
{
- ipx_sk_slab = kmem_cache_create("ipx_sock",
- sizeof(struct ipx_sock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
+ int rc = proto_register(&ipx_proto, 1);
- if (ipx_sk_slab == NULL)
- return -ENOMEM;
+ if (rc != 0)
+ goto out;
sock_register(&ipx_family_ops);
@@ -1986,7 +1987,8 @@ static int __init ipx_init(void)
register_netdevice_notifier(&ipx_dev_notifier);
ipx_register_sysctl();
ipx_proc_init();
- return 0;
+out:
+ return rc;
}
static void __exit ipx_proto_finito(void)
@@ -2012,11 +2014,7 @@ static void __exit ipx_proto_finito(void)
destroy_EII_client(pEII_datalink);
pEII_datalink = NULL;
- if (ipx_sk_slab != NULL) {
- kmem_cache_destroy(ipx_sk_slab);
- ipx_sk_slab = NULL;
- }
-
+ proto_unregister(&ipx_proto);
sock_unregister(ipx_family_ops.family);
}
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index a6f32b96d3b56c..92c6e8d4e731b1 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1071,6 +1071,12 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
return 0;
}
+static struct proto irda_proto = {
+ .name = "IRDA",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct irda_sock),
+};
+
/*
* Function irda_create (sock, protocol)
*
@@ -1095,8 +1101,7 @@ static int irda_create(struct socket *sock, int protocol)
}
/* Allocate networking socket */
- sk = sk_alloc(PF_IRDA, GFP_ATOMIC,
- sizeof(struct irda_sock), NULL);
+ sk = sk_alloc(PF_IRDA, GFP_ATOMIC, &irda_proto, 1);
if (sk == NULL)
return -ENOMEM;
@@ -1107,7 +1112,6 @@ static int irda_create(struct socket *sock, int protocol)
/* Initialise networking socket struct */
sock_init_data(sock, sk); /* Note : set sk->sk_refcnt to 1 */
- sk_set_owner(sk, THIS_MODULE);
sk->sk_family = PF_IRDA;
sk->sk_protocol = protocol;
@@ -2561,9 +2565,12 @@ SOCKOPS_WRAP(irda_ultra, PF_IRDA);
*/
int __init irsock_init(void)
{
- sock_register(&irda_family_ops);
+ int rc = proto_register(&irda_proto, 0);
- return 0;
+ if (rc == 0)
+ rc = sock_register(&irda_family_ops);
+
+ return rc;
}
/*
@@ -2575,6 +2582,5 @@ int __init irsock_init(void)
void __exit irsock_cleanup(void)
{
sock_unregister(PF_IRDA);
-
- return;
+ proto_unregister(&irda_proto);
}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 6682c7e261acb1..ce980aa94ed8e4 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -129,6 +129,12 @@ static void pfkey_remove(struct sock *sk)
pfkey_table_ungrab();
}
+static struct proto key_proto = {
+ .name = "KEY",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct pfkey_sock),
+};
+
static int pfkey_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -142,13 +148,12 @@ static int pfkey_create(struct socket *sock, int protocol)
return -EPROTONOSUPPORT;
err = -ENOMEM;
- sk = sk_alloc(PF_KEY, GFP_KERNEL, sizeof(struct pfkey_sock), NULL);
+ sk = sk_alloc(PF_KEY, GFP_KERNEL, &key_proto, 1);
if (sk == NULL)
goto out;
sock->ops = &pfkey_ops;
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_family = PF_KEY;
sk->sk_destruct = pfkey_sock_destruct;
@@ -2858,16 +2863,38 @@ static void __exit ipsec_pfkey_exit(void)
xfrm_unregister_km(&pfkeyv2_mgr);
remove_proc_entry("net/pfkey", NULL);
sock_unregister(PF_KEY);
+ proto_unregister(&key_proto);
}
static int __init ipsec_pfkey_init(void)
{
- sock_register(&pfkey_family_ops);
+ int err = proto_register(&key_proto, 0);
+
+ if (err != 0)
+ goto out;
+
+ err = sock_register(&pfkey_family_ops);
+ if (err != 0)
+ goto out_unregister_key_proto;
#ifdef CONFIG_PROC_FS
- create_proc_read_entry("net/pfkey", 0, NULL, pfkey_read_proc, NULL);
+ err = -ENOMEM;
+ if (create_proc_read_entry("net/pfkey", 0, NULL, pfkey_read_proc, NULL) == NULL)
+ goto out_sock_unregister;
#endif
- xfrm_register_km(&pfkeyv2_mgr);
- return 0;
+ err = xfrm_register_km(&pfkeyv2_mgr);
+ if (err != 0)
+ goto out_remove_proc_entry;
+out:
+ return err;
+out_remove_proc_entry:
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("net/pfkey", NULL);
+out_sock_unregister:
+#endif
+ sock_unregister(PF_KEY);
+out_unregister_key_proto:
+ proto_unregister(&key_proto);
+ goto out;
}
module_init(ipsec_pfkey_init);
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 2e11283e5062e1..20b4cfebd74ca5 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -135,6 +135,12 @@ static void llc_ui_sk_init(struct socket *sock, struct sock *sk)
sock->ops = &llc_ui_ops;
}
+static struct proto llc_proto = {
+ .name = "DDP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct llc_sock),
+};
+
/**
* llc_ui_create - alloc and init a new llc_ui socket
* @sock: Socket to initialize and attach allocated sk to.
@@ -151,7 +157,7 @@ static int llc_ui_create(struct socket *sock, int protocol)
if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) {
rc = -ENOMEM;
- sk = llc_sk_alloc(PF_LLC, GFP_KERNEL);
+ sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);
if (sk) {
rc = 0;
llc_ui_sk_init(sock, sk);
@@ -1033,18 +1039,25 @@ extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
static int __init llc2_init(void)
{
- int rc;
+ int rc = proto_register(&llc_proto, 0);
+
+ if (rc != 0)
+ goto out;
llc_build_offset_table();
llc_station_init();
llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
rc = llc_proc_init();
- if (!rc) {
- sock_register(&llc_ui_family_ops);
- llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
- llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
- }
+ if (rc != 0)
+ goto out_unregister_llc_proto;
+ sock_register(&llc_ui_family_ops);
+ llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
+ llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
+out:
return rc;
+out_unregister_llc_proto:
+ proto_unregister(&llc_proto);
+ goto out;
}
static void __exit llc2_exit(void)
@@ -1054,6 +1067,7 @@ static void __exit llc2_exit(void)
llc_remove_pack(LLC_DEST_CONN);
sock_unregister(PF_LLC);
llc_proc_exit();
+ proto_unregister(&llc_proto);
}
module_init(llc2_init);
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index cc587ebf42c15a..eba812a9c69c6e 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -683,7 +683,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
goto drop;
}
- sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC);
+ sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot);
if (!sk) {
sock_put(parent);
goto drop;
@@ -830,16 +830,14 @@ static void llc_sk_init(struct sock* sk)
* Allocates a LLC sock and initializes it. Returns the new LLC sock
* or %NULL if there's no memory available for one
*/
-struct sock *llc_sk_alloc(int family, int priority)
+struct sock *llc_sk_alloc(int family, int priority, struct proto *prot)
{
- struct sock *sk = sk_alloc(family, priority,
- sizeof(struct llc_sock), NULL);
+ struct sock *sk = sk_alloc(family, priority, prot, 1);
if (!sk)
goto out;
llc_sk_init(sk);
sock_init_data(NULL, sk);
- sk_set_owner(sk, THIS_MODULE);
#ifdef LLC_REFCNT_DEBUG
atomic_inc(&llc_sock_nr);
printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 65f1a89ac6dead..1d5905c90cd4bd 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -321,6 +321,12 @@ static void netlink_remove(struct sock *sk)
netlink_table_ungrab();
}
+static struct proto netlink_proto = {
+ .name = "NETLINK",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct netlink_sock),
+};
+
static int netlink_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -336,13 +342,11 @@ static int netlink_create(struct socket *sock, int protocol)
sock->ops = &netlink_ops;
- sk = sk_alloc(PF_NETLINK, GFP_KERNEL,
- sizeof(struct netlink_sock), NULL);
+ sk = sk_alloc(PF_NETLINK, GFP_KERNEL, &netlink_proto, 1);
if (!sk)
return -ENOMEM;
- sock_init_data(sock,sk);
- sk_set_owner(sk, THIS_MODULE);
+ sock_init_data(sock, sk);
nlk = nlk_sk(sk);
@@ -558,13 +562,12 @@ static struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid)
struct sock *netlink_getsockbyfilp(struct file *filp)
{
struct inode *inode = filp->f_dentry->d_inode;
- struct socket *socket;
struct sock *sock;
- if (!inode->i_sock || !(socket = SOCKET_I(inode)))
+ if (!S_ISSOCK(inode->i_mode))
return ERR_PTR(-ENOTSOCK);
- sock = socket->sk;
+ sock = SOCKET_I(inode)->sk;
if (sock->sk_family != AF_NETLINK)
return ERR_PTR(-EINVAL);
@@ -1080,11 +1083,9 @@ static int netlink_dump(struct sock *sk)
len = cb->dump(skb, cb);
if (len > 0) {
- sock_hold(sk);
spin_unlock(&nlk->cb_lock);
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, len);
- sock_put(sk);
return 0;
}
@@ -1099,7 +1100,7 @@ static int netlink_dump(struct sock *sk)
spin_unlock(&nlk->cb_lock);
netlink_destroy_callback(cb);
- sock_put(sk);
+ __sock_put(sk);
return 0;
}
@@ -1138,9 +1139,11 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
return -EBUSY;
}
nlk->cb = cb;
+ sock_hold(sk);
spin_unlock(&nlk->cb_lock);
netlink_dump(sk);
+ sock_put(sk);
return 0;
}
@@ -1369,6 +1372,10 @@ static int __init netlink_proto_init(void)
int i;
unsigned long max;
unsigned int order;
+ int err = proto_register(&netlink_proto, 0);
+
+ if (err != 0)
+ goto out;
if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb))
netlink_skb_parms_too_large();
@@ -1415,15 +1422,17 @@ enomem:
#endif
/* The netlink device handler may be needed early. */
rtnetlink_init();
- return 0;
+out:
+ return err;
}
static void __exit netlink_proto_exit(void)
{
- sock_unregister(PF_NETLINK);
- proc_net_remove("netlink");
- kfree(nl_table);
- nl_table = NULL;
+ sock_unregister(PF_NETLINK);
+ proc_net_remove("netlink");
+ kfree(nl_table);
+ nl_table = NULL;
+ proto_unregister(&netlink_proto);
}
core_initcall(netlink_proto_init);
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 024217b2f9e583..31ed4a9a1d066c 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -64,11 +64,6 @@ static DEFINE_SPINLOCK(nr_list_lock);
static struct proto_ops nr_proto_ops;
-static struct sock *nr_alloc_sock(void)
-{
- return sk_alloc(PF_NETROM, GFP_ATOMIC, sizeof(struct nr_sock), NULL);
-}
-
/*
* Socket removal during an interrupt is now safe.
*/
@@ -398,6 +393,12 @@ static int nr_listen(struct socket *sock, int backlog)
return -EOPNOTSUPP;
}
+static struct proto nr_proto = {
+ .name = "NETROM",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct nr_sock),
+};
+
static int nr_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -406,13 +407,12 @@ static int nr_create(struct socket *sock, int protocol)
if (sock->type != SOCK_SEQPACKET || protocol != 0)
return -ESOCKTNOSUPPORT;
- if ((sk = nr_alloc_sock()) == NULL)
+ if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, &nr_proto, 1)) == NULL)
return -ENOMEM;
nr = nr_sk(sk);
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
sock->ops = &nr_proto_ops;
sk->sk_protocol = protocol;
@@ -444,13 +444,12 @@ static struct sock *nr_make_new(struct sock *osk)
if (osk->sk_type != SOCK_SEQPACKET)
return NULL;
- if ((sk = nr_alloc_sock()) == NULL)
+ if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
return NULL;
nr = nr_sk(sk);
sock_init_data(NULL, sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_type = osk->sk_type;
sk->sk_socket = osk->sk_socket;
@@ -1368,6 +1367,10 @@ static char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.
static int __init nr_proto_init(void)
{
int i;
+ int rc = proto_register(&nr_proto, 0);
+
+ if (rc != 0)
+ goto out;
if (nr_ndevs > 0x7fffffff/sizeof(struct net_device *)) {
printk(KERN_ERR "NET/ROM: nr_proto_init - nr_ndevs parameter to large\n");
@@ -1423,15 +1426,17 @@ static int __init nr_proto_init(void)
proc_net_fops_create("nr", S_IRUGO, &nr_info_fops);
proc_net_fops_create("nr_neigh", S_IRUGO, &nr_neigh_fops);
proc_net_fops_create("nr_nodes", S_IRUGO, &nr_nodes_fops);
- return 0;
-
- fail:
+out:
+ return rc;
+fail:
while (--i >= 0) {
unregister_netdev(dev_nr[i]);
free_netdev(dev_nr[i]);
}
kfree(dev_nr);
- return -1;
+ proto_unregister(&nr_proto);
+ rc = -1;
+ goto out;
}
module_init(nr_proto_init);
@@ -1475,5 +1480,6 @@ static void __exit nr_exit(void)
}
kfree(dev_nr);
+ proto_unregister(&nr_proto);
}
module_exit(nr_exit);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 1c994ed5cf3561..64acea0adaaea6 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -955,6 +955,11 @@ out:
return err;
}
+static struct proto packet_proto = {
+ .name = "PACKET",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct packet_sock),
+};
/*
* Create a packet of type SOCK_PACKET.
@@ -978,8 +983,7 @@ static int packet_create(struct socket *sock, int protocol)
sock->state = SS_UNCONNECTED;
err = -ENOBUFS;
- sk = sk_alloc(PF_PACKET, GFP_KERNEL,
- sizeof(struct packet_sock), NULL);
+ sk = sk_alloc(PF_PACKET, GFP_KERNEL, &packet_proto, 1);
if (sk == NULL)
goto out;
@@ -988,8 +992,7 @@ static int packet_create(struct socket *sock, int protocol)
if (sock->type == SOCK_PACKET)
sock->ops = &packet_ops_spkt;
#endif
- sock_init_data(sock,sk);
- sk_set_owner(sk, THIS_MODULE);
+ sock_init_data(sock, sk);
po = pkt_sk(sk);
sk->sk_family = PF_PACKET;
@@ -1881,16 +1884,21 @@ static void __exit packet_exit(void)
proc_net_remove("packet");
unregister_netdevice_notifier(&packet_netdev_notifier);
sock_unregister(PF_PACKET);
- return;
+ proto_unregister(&packet_proto);
}
static int __init packet_init(void)
{
+ int rc = proto_register(&packet_proto, 0);
+
+ if (rc != 0)
+ goto out;
+
sock_register(&packet_family_ops);
register_netdevice_notifier(&packet_netdev_notifier);
proc_net_fops_create("packet", 0, &packet_seq_fops);
-
- return 0;
+out:
+ return rc;
}
module_init(packet_init);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 68da687c9142ad..7eb6a5bf93ea19 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -126,11 +126,6 @@ int rosecmpm(rose_address *addr1, rose_address *addr2, unsigned short mask)
return 0;
}
-static struct sock *rose_alloc_sock(void)
-{
- return sk_alloc(PF_ROSE, GFP_ATOMIC, sizeof(struct rose_sock), NULL);
-}
-
/*
* Socket removal during an interrupt is now safe.
*/
@@ -488,6 +483,12 @@ static int rose_listen(struct socket *sock, int backlog)
return -EOPNOTSUPP;
}
+static struct proto rose_proto = {
+ .name = "ROSE",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct rose_sock),
+};
+
static int rose_create(struct socket *sock, int protocol)
{
struct sock *sk;
@@ -496,13 +497,12 @@ static int rose_create(struct socket *sock, int protocol)
if (sock->type != SOCK_SEQPACKET || protocol != 0)
return -ESOCKTNOSUPPORT;
- if ((sk = rose_alloc_sock()) == NULL)
+ if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
return -ENOMEM;
rose = rose_sk(sk);
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
skb_queue_head_init(&rose->ack_queue);
#ifdef M_BIT
@@ -535,13 +535,12 @@ static struct sock *rose_make_new(struct sock *osk)
if (osk->sk_type != SOCK_SEQPACKET)
return NULL;
- if ((sk = rose_alloc_sock()) == NULL)
+ if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
return NULL;
rose = rose_sk(sk);
sock_init_data(NULL, sk);
- sk_set_owner(sk, THIS_MODULE);
skb_queue_head_init(&rose->ack_queue);
#ifdef M_BIT
@@ -1472,6 +1471,10 @@ static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62
static int __init rose_proto_init(void)
{
int i;
+ int rc = proto_register(&rose_proto, 0);
+
+ if (rc != 0)
+ goto out;
rose_callsign = null_ax25_address;
@@ -1524,14 +1527,15 @@ static int __init rose_proto_init(void)
proc_net_fops_create("rose_neigh", S_IRUGO, &rose_neigh_fops);
proc_net_fops_create("rose_nodes", S_IRUGO, &rose_nodes_fops);
proc_net_fops_create("rose_routes", S_IRUGO, &rose_routes_fops);
-
- return 0;
+out:
+ return rc;
fail:
while (--i >= 0) {
unregister_netdev(dev_rose[i]);
free_netdev(dev_rose[i]);
}
kfree(dev_rose);
+ proto_unregister(&rose_proto);
return -ENOMEM;
}
module_init(rose_proto_init);
@@ -1579,6 +1583,7 @@ static void __exit rose_exit(void)
}
kfree(dev_rose);
+ proto_unregister(&rose_proto);
}
module_exit(rose_exit);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 10714716d4c7bf..4323a74eea30bc 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -406,11 +406,29 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
ops = qdisc_lookup_ops(kind);
#ifdef CONFIG_KMOD
- if (ops==NULL && tca[TCA_KIND-1] != NULL) {
+ if (ops == NULL && kind != NULL) {
char name[IFNAMSIZ];
if (rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
+ /* We dropped the RTNL semaphore in order to
+ * perform the module load. So, even if we
+ * succeeded in loading the module we have to
+ * tell the caller to replay the request. We
+ * indicate this using -EAGAIN.
+ * We replay the request because the device may
+ * go away in the mean time.
+ */
+ rtnl_unlock();
request_module("sch_%s", name);
+ rtnl_lock();
ops = qdisc_lookup_ops(kind);
+ if (ops != NULL) {
+ /* We will try again qdisc_lookup_ops,
+ * so don't keep a reference.
+ */
+ module_put(ops->owner);
+ err = -EAGAIN;
+ goto err_out;
+ }
}
}
#endif
@@ -606,14 +624,20 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
{
- struct tcmsg *tcm = NLMSG_DATA(n);
- struct rtattr **tca = arg;
+ struct tcmsg *tcm;
+ struct rtattr **tca;
struct net_device *dev;
- u32 clid = tcm->tcm_parent;
- struct Qdisc *q = NULL;
- struct Qdisc *p = NULL;
+ u32 clid;
+ struct Qdisc *q, *p;
int err;
+replay:
+ /* Reinit, just in case something touches this. */
+ tcm = NLMSG_DATA(n);
+ tca = arg;
+ clid = tcm->tcm_parent;
+ q = p = NULL;
+
if ((dev = __dev_get_by_index(tcm->tcm_ifindex)) == NULL)
return -ENODEV;
@@ -707,8 +731,11 @@ create_n_graft:
q = qdisc_create(dev, tcm->tcm_parent, tca, &err);
else
q = qdisc_create(dev, tcm->tcm_handle, tca, &err);
- if (q == NULL)
+ if (q == NULL) {
+ if (err == -EAGAIN)
+ goto replay;
return err;
+ }
graft:
if (1) {
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index c8259cbe652c3f..31c29deb139d3e 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -152,9 +152,6 @@ static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
/* Always queue at tail to keep packets in order */
if (likely(q->delayed.qlen < q->limit)) {
__skb_queue_tail(&q->delayed, skb);
- sch->bstats.bytes += skb->len;
- sch->bstats.packets++;
-
if (!timer_pending(&q->timer)) {
q->timer.expires = jiffies + PSCHED_US2JIFFIE(td);
add_timer(&q->timer);
@@ -162,7 +159,6 @@ static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
return NET_XMIT_SUCCESS;
}
- sch->qstats.drops++;
kfree_skb(skb);
return NET_XMIT_DROP;
}
@@ -170,6 +166,8 @@ static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
+ struct sk_buff *skb2;
+ int ret;
pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
@@ -182,12 +180,16 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
}
/* Random duplication */
- if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
- struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
-
+ if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)
+ && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
pr_debug("netem_enqueue: dup %p\n", skb2);
- if (skb2)
- delay_skb(sch, skb2);
+
+ if (delay_skb(sch, skb2)) {
+ sch->q.qlen++;
+ sch->bstats.bytes += skb2->len;
+ sch->bstats.packets++;
+ } else
+ sch->qstats.drops++;
}
/* If doing simple delay then gap == 0 so all packets
@@ -196,22 +198,21 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
* packets will be delayed.
*/
if (q->counter < q->gap) {
- int ret;
-
++q->counter;
ret = q->qdisc->enqueue(skb, q->qdisc);
- if (likely(ret == NET_XMIT_SUCCESS)) {
- sch->q.qlen++;
- sch->bstats.bytes += skb->len;
- sch->bstats.packets++;
- } else
- sch->qstats.drops++;
- return ret;
+ } else {
+ q->counter = 0;
+ ret = delay_skb(sch, skb);
}
-
- q->counter = 0;
- return delay_skb(sch, skb);
+ if (likely(ret == NET_XMIT_SUCCESS)) {
+ sch->q.qlen++;
+ sch->bstats.bytes += skb->len;
+ sch->bstats.packets++;
+ } else
+ sch->qstats.drops++;
+
+ return ret;
}
/* Requeue packets but don't change time stamp */
@@ -283,10 +284,10 @@ static void netem_watchdog(unsigned long arg)
}
__skb_unlink(skb, &q->delayed);
- if (q->qdisc->enqueue(skb, q->qdisc))
+ if (q->qdisc->enqueue(skb, q->qdisc)) {
+ sch->q.qlen--;
sch->qstats.drops++;
- else
- sch->q.qlen++;
+ }
}
qdisc_run(dev);
spin_unlock_bh(&dev->queue_lock);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ee1be46dd57094..e42c74e3ec1e8f 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -594,13 +594,11 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct sctp6_sock *newsctp6sk;
- newsk = sk_alloc(PF_INET6, GFP_KERNEL, sk->sk_prot->slab_obj_size,
- sk->sk_prot->slab);
+ newsk = sk_alloc(PF_INET6, GFP_KERNEL, sk->sk_prot, 1);
if (!newsk)
goto out;
sock_init_data(NULL, newsk);
- sk_set_owner(newsk, THIS_MODULE);
newsk->sk_type = SOCK_STREAM;
@@ -974,14 +972,14 @@ static struct sctp_pf sctp_pf_inet6_specific = {
/* Initialize IPv6 support and register with inet6 stack. */
int sctp_v6_init(void)
{
- int rc = sk_alloc_slab(&sctpv6_prot, "sctpv6_sock");
+ int rc = proto_register(&sctpv6_prot, 1);
if (rc)
goto out;
/* Register inet6 protocol. */
rc = -EAGAIN;
if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
- goto out_sctp_free_slab;
+ goto out_unregister_sctp_proto;
/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
inet6_register_protosw(&sctpv6_seqpacket_protosw);
@@ -998,8 +996,8 @@ int sctp_v6_init(void)
rc = 0;
out:
return rc;
-out_sctp_free_slab:
- sk_free_slab(&sctpv6_prot);
+out_unregister_sctp_proto:
+ proto_unregister(&sctpv6_prot);
goto out;
}
@@ -1011,5 +1009,5 @@ void sctp_v6_exit(void)
inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
inet6_unregister_protosw(&sctpv6_stream_protosw);
unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
- sk_free_slab(&sctpv6_prot);
+ proto_unregister(&sctpv6_prot);
}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 49214c3b45f43b..b9813cf3d91c6e 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -550,21 +550,17 @@ static int sctp_v4_is_ce(const struct sk_buff *skb)
static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
struct sctp_association *asoc)
{
- struct sock *newsk;
struct inet_sock *inet = inet_sk(sk);
struct inet_sock *newinet;
+ struct sock *newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot, 1);
- newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot->slab_obj_size,
- sk->sk_prot->slab);
if (!newsk)
goto out;
sock_init_data(NULL, newsk);
- sk_set_owner(newsk, THIS_MODULE);
newsk->sk_type = SOCK_STREAM;
- newsk->sk_prot = sk->sk_prot;
newsk->sk_no_check = sk->sk_no_check;
newsk->sk_reuse = sk->sk_reuse;
newsk->sk_shutdown = sk->sk_shutdown;
@@ -970,7 +966,7 @@ SCTP_STATIC __init int sctp_init(void)
if (!sctp_sanity_check())
goto out;
- status = sk_alloc_slab(&sctp_prot, "sctp_sock");
+ status = proto_register(&sctp_prot, 1);
if (status)
goto out;
@@ -1164,7 +1160,7 @@ SCTP_STATIC __init int sctp_init(void)
out:
return status;
err_add_protocol:
- sk_free_slab(&sctp_prot);
+ proto_unregister(&sctp_prot);
err_ctl_sock_init:
sctp_v6_exit();
err_v6_init:
@@ -1233,7 +1229,7 @@ SCTP_STATIC __exit void sctp_exit(void)
inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
inet_unregister_protosw(&sctp_seqpacket_protosw);
inet_unregister_protosw(&sctp_stream_protosw);
- sk_free_slab(&sctp_prot);
+ proto_unregister(&sctp_prot);
}
module_init(sctp_init);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6f66ee49078460..e8c21018257105 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4768,7 +4768,7 @@ struct proto sctp_prot = {
.hash = sctp_hash,
.unhash = sctp_unhash,
.get_port = sctp_get_port,
- .slab_obj_size = sizeof(struct sctp_sock),
+ .obj_size = sizeof(struct sctp_sock),
};
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -4792,6 +4792,6 @@ struct proto sctpv6_prot = {
.hash = sctp_hash,
.unhash = sctp_unhash,
.get_port = sctp_get_port,
- .slab_obj_size = sizeof(struct sctp6_sock),
+ .obj_size = sizeof(struct sctp6_sock),
};
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
diff --git a/net/socket.c b/net/socket.c
index f2391d68fad3b4..2cd44990d8d3da 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -437,13 +437,13 @@ struct socket *sockfd_lookup(int fd, int *err)
}
inode = file->f_dentry->d_inode;
- if (!inode->i_sock || !(sock = SOCKET_I(inode)))
- {
+ if (!S_ISSOCK(inode->i_mode)) {
*err = -ENOTSOCK;
fput(file);
return NULL;
}
+ sock = SOCKET_I(inode);
if (sock->file != file) {
printk(KERN_ERR "socki_lookup: socket file changed!\n");
sock->file = file;
@@ -471,7 +471,6 @@ static struct socket *sock_alloc(void)
sock = SOCKET_I(inode);
inode->i_mode = S_IFSOCK|S_IRWXUGO;
- inode->i_sock = 1;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 20165335e27b88..acc73fe686983d 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -121,8 +121,6 @@
int sysctl_unix_max_dgram_qlen = 10;
-static kmem_cache_t *unix_sk_cachep;
-
struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
DEFINE_RWLOCK(unix_table_lock);
static atomic_t unix_nr_socks = ATOMIC_INIT(0);
@@ -539,6 +537,12 @@ static struct proto_ops unix_seqpacket_ops = {
.sendpage = sock_no_sendpage,
};
+static struct proto unix_proto = {
+ .name = "UNIX",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct unix_sock),
+};
+
static struct sock * unix_create1(struct socket *sock)
{
struct sock *sk = NULL;
@@ -547,15 +551,13 @@ static struct sock * unix_create1(struct socket *sock)
if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files)
goto out;
- sk = sk_alloc(PF_UNIX, GFP_KERNEL, sizeof(struct unix_sock),
- unix_sk_cachep);
+ sk = sk_alloc(PF_UNIX, GFP_KERNEL, &unix_proto, 1);
if (!sk)
goto out;
atomic_inc(&unix_nr_socks);
sock_init_data(sock,sk);
- sk_set_owner(sk, THIS_MODULE);
sk->sk_write_space = unix_write_space;
sk->sk_max_ack_backlog = sysctl_unix_max_dgram_qlen;
@@ -2057,26 +2059,28 @@ static inline void unix_sysctl_unregister(void) {}
static int __init af_unix_init(void)
{
+ int rc = -1;
struct sk_buff *dummy_skb;
if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) {
printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
- return -1;
+ goto out;
+ }
+
+ rc = proto_register(&unix_proto, 1);
+ if (rc != 0) {
+ printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n",
+ __FUNCTION__);
+ goto out;
}
- /* allocate our sock slab cache */
- unix_sk_cachep = kmem_cache_create("unix_sock",
- sizeof(struct unix_sock), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (!unix_sk_cachep)
- printk(KERN_CRIT
- "af_unix_init: Cannot create unix_sock SLAB cache!\n");
sock_register(&unix_family_ops);
#ifdef CONFIG_PROC_FS
proc_net_fops_create("unix", 0, &unix_seq_fops);
#endif
unix_sysctl_register();
- return 0;
+out:
+ return rc;
}
static void __exit af_unix_exit(void)
@@ -2084,7 +2088,7 @@ static void __exit af_unix_exit(void)
sock_unregister(PF_UNIX);
unix_sysctl_unregister();
proc_net_remove("unix");
- kmem_cache_destroy(unix_sk_cachep);
+ proto_unregister(&unix_proto);
}
module_init(af_unix_init);
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index 3d5e1a5f433f0e..4bd95c8f5934a5 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -100,7 +100,7 @@ static struct sock *unix_get_socket(struct file *filp)
/*
* Socket ?
*/
- if (inode->i_sock) {
+ if (S_ISSOCK(inode->i_mode)) {
struct socket * sock = SOCKET_I(inode);
struct sock * s = sock->sk;
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 6698c872c96b9e..d93b19faaab7f9 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -477,6 +477,17 @@ static struct sock *wanpipe_make_new(struct sock *osk)
return sk;
}
+/*
+ * FIXME: wanpipe_opt has to include a sock in its definition and stop using
+ * sk_protinfo, but this code is not even compilable now, so lets leave it for
+ * later.
+ */
+static struct proto wanpipe_proto = {
+ .name = "WANPIPE",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct sock),
+};
+
/*============================================================
* wanpipe_make_new
*
@@ -495,7 +506,7 @@ static struct sock *wanpipe_alloc_socket(void)
struct sock *sk;
struct wanpipe_opt *wan_opt;
- if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, 1, NULL)) == NULL)
+ if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, &wanpipe_proto, 1)) == NULL)
return NULL;
if ((wan_opt = kmalloc(sizeof(struct wanpipe_opt), GFP_ATOMIC)) == NULL) {
@@ -2577,17 +2588,23 @@ void cleanup_module(void)
printk(KERN_INFO "wansock: Cleaning up \n");
unregister_netdevice_notifier(&wanpipe_netdev_notifier);
sock_unregister(PF_WANPIPE);
- return;
+ proto_unregister(&wanpipe_proto);
}
-
int init_module(void)
{
+ int rc;
printk(KERN_INFO "wansock: Registering Socket \n");
+
+ rc = proto_register(&wanpipe_proto, 0);
+ if (rc != 0)
+ goto out;
+
sock_register(&wanpipe_family_ops);
register_netdevice_notifier(&wanpipe_netdev_notifier);
- return 0;
+out:
+ return rc;
}
#endif
MODULE_LICENSE("GPL");
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index e05189a7f85fda..2a24b243b841aa 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -442,17 +442,21 @@ static int x25_listen(struct socket *sock, int backlog)
return rc;
}
+static struct proto x25_proto = {
+ .name = "X25",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct x25_sock),
+};
+
static struct sock *x25_alloc_socket(void)
{
struct x25_sock *x25;
- struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC,
- sizeof(struct x25_sock), NULL);
+ struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC, &x25_proto, 1);
if (!sk)
goto out;
sock_init_data(NULL, sk);
- sk_set_owner(sk, THIS_MODULE);
x25 = x25_sk(sk);
skb_queue_head_init(&x25->ack_queue);
@@ -481,7 +485,6 @@ static int x25_create(struct socket *sock, int protocol)
x25 = x25_sk(sk);
sock_init_data(sock, sk);
- sk_set_owner(sk, THIS_MODULE);
x25_init_timers(sk);
@@ -1385,6 +1388,11 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
static int __init x25_init(void)
{
+ int rc = proto_register(&x25_proto, 0);
+
+ if (rc != 0)
+ goto out;
+
sock_register(&x25_family_ops);
dev_add_pack(&x25_packet_type);
@@ -1397,7 +1405,8 @@ static int __init x25_init(void)
x25_register_sysctl();
#endif
x25_proc_init();
- return 0;
+out:
+ return rc;
}
module_init(x25_init);
@@ -1416,6 +1425,7 @@ static void __exit x25_exit(void)
dev_remove_pack(&x25_packet_type);
sock_unregister(AF_X25);
+ proto_unregister(&x25_proto);
}
module_exit(x25_exit);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index fbf8270619255c..80828078733dd9 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -13,6 +13,7 @@
*
*/
+#include <asm/bug.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/kmod.h>
@@ -300,20 +301,20 @@ static void xfrm_policy_gc_task(void *data)
static void xfrm_policy_kill(struct xfrm_policy *policy)
{
+ int dead;
+
write_lock_bh(&policy->lock);
- if (policy->dead) {
- write_unlock_bh(&policy->lock);
+ dead = policy->dead;
+ policy->dead = 1;
+ write_unlock_bh(&policy->lock);
+
+ if (unlikely(dead)) {
+ WARN_ON(1);
return;
}
- policy->dead = 1;
spin_lock(&xfrm_policy_gc_lock);
list_add(&policy->list, &xfrm_policy_gc_list);
- /*
- * Unlock the policy (out of order unlocking), to make sure
- * the GC context does not free it with an active lock:
- */
- write_unlock_bh(&policy->lock);
spin_unlock(&xfrm_policy_gc_lock);
schedule_work(&xfrm_policy_gc_work);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 78d6c52a65ccbf..1db59f11f37d68 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -48,6 +48,8 @@ static struct work_struct xfrm_state_gc_work;
static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list);
static DEFINE_SPINLOCK(xfrm_state_gc_lock);
+static int xfrm_state_gc_flush_bundles;
+
static void __xfrm_state_delete(struct xfrm_state *x);
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
@@ -81,6 +83,11 @@ static void xfrm_state_gc_task(void *data)
struct list_head *entry, *tmp;
struct list_head gc_list = LIST_HEAD_INIT(gc_list);
+ if (xfrm_state_gc_flush_bundles) {
+ xfrm_state_gc_flush_bundles = 0;
+ xfrm_flush_bundles();
+ }
+
spin_lock_bh(&xfrm_state_gc_lock);
list_splice_init(&xfrm_state_gc_list, &gc_list);
spin_unlock_bh(&xfrm_state_gc_lock);
@@ -228,8 +235,10 @@ static void __xfrm_state_delete(struct xfrm_state *x)
* our caller holds. A larger value means that
* there are DSTs attached to this xfrm_state.
*/
- if (atomic_read(&x->refcnt) > 2)
- xfrm_flush_bundles();
+ if (atomic_read(&x->refcnt) > 2) {
+ xfrm_state_gc_flush_bundles = 1;
+ schedule_work(&xfrm_state_gc_work);
+ }
/* All xfrm_state objects are created by xfrm_state_alloc.
* The xfrm_state_alloc call gives a reference, and that
@@ -295,10 +304,17 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
unsigned short family)
{
unsigned h = xfrm_dst_hash(daddr, family);
- struct xfrm_state *x;
+ struct xfrm_state *x, *x0;
int acquire_in_progress = 0;
int error = 0;
struct xfrm_state *best = NULL;
+ struct xfrm_state_afinfo *afinfo;
+
+ afinfo = xfrm_state_get_afinfo(family);
+ if (afinfo == NULL) {
+ *err = -EAFNOSUPPORT;
+ return NULL;
+ }
spin_lock_bh(&xfrm_state_lock);
list_for_each_entry(x, xfrm_state_bydst+h, bydst) {
@@ -306,7 +322,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
x->props.reqid == tmpl->reqid &&
xfrm_state_addr_check(x, daddr, saddr, family) &&
tmpl->mode == x->props.mode &&
- tmpl->id.proto == x->id.proto) {
+ tmpl->id.proto == x->id.proto &&
+ (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) {
/* Resolution logic:
1. There is a valid state with matching selector.
Done.
@@ -333,14 +350,24 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
} else if (x->km.state == XFRM_STATE_ERROR ||
x->km.state == XFRM_STATE_EXPIRED) {
if (xfrm_selector_match(&x->sel, fl, family))
- error = 1;
+ error = -ESRCH;
}
}
}
x = best;
- if (!x && !error && !acquire_in_progress &&
- ((x = xfrm_state_alloc()) != NULL)) {
+ if (!x && !error && !acquire_in_progress) {
+ x0 = afinfo->state_lookup(&tmpl->id.daddr, tmpl->id.spi, tmpl->id.proto);
+ if (x0 != NULL) {
+ xfrm_state_put(x0);
+ error = -EEXIST;
+ goto out;
+ }
+ x = xfrm_state_alloc();
+ if (x == NULL) {
+ error = -ENOMEM;
+ goto out;
+ }
/* Initialize temporary selector matching only
* to current session. */
xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
@@ -362,15 +389,16 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
x = NULL;
- error = 1;
+ error = -ESRCH;
}
}
+out:
if (x)
xfrm_state_hold(x);
else
- *err = acquire_in_progress ? -EAGAIN :
- (error ? -ESRCH : -ENOMEM);
+ *err = acquire_in_progress ? -EAGAIN : error;
spin_unlock_bh(&xfrm_state_lock);
+ xfrm_state_put_afinfo(afinfo);
return x;
}