aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/Changes11
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/journal-api.tmpl2
-rw-r--r--Documentation/DocBook/kernel-api.tmpl7
-rw-r--r--Documentation/DocBook/rapidio.tmpl160
-rw-r--r--Documentation/MSI-HOWTO.txt174
-rw-r--r--Documentation/RCU/whatisRCU.txt2
-rw-r--r--Documentation/device-mapper/snapshot.txt5
-rw-r--r--Documentation/fb/vesafb.txt4
-rw-r--r--Documentation/feature-removal-schedule.txt16
-rw-r--r--Documentation/filesystems/dentry-locking.txt173
-rw-r--r--Documentation/filesystems/devfs/README5
-rw-r--r--Documentation/filesystems/ramfs-rootfs-initramfs.txt195
-rw-r--r--Documentation/filesystems/vfs.txt434
-rw-r--r--Documentation/hpet.txt34
-rw-r--r--Documentation/magic-number.txt2
-rw-r--r--Documentation/networking/decnet.txt2
-rw-r--r--Documentation/oops-tracing.txt2
-rw-r--r--Documentation/power/video.txt17
-rw-r--r--Documentation/s390/driver-model.txt21
-rw-r--r--Documentation/sparse.txt4
-rw-r--r--Documentation/video4linux/bttv/README.freeze6
-rw-r--r--Documentation/vm/hugetlbpage.txt25
-rw-r--r--MAINTAINERS26
-rw-r--r--arch/arm/kernel/ptrace.c49
-rw-r--r--arch/arm/mach-aaec2000/clock.c1
-rw-r--r--arch/arm/mach-epxa10db/mm.c1
-rw-r--r--arch/arm/mach-integrator/impd1.c3
-rw-r--r--arch/arm/mach-pxa/corgi_lcd.c1
-rw-r--r--arch/arm26/kernel/ptrace.c49
-rw-r--r--arch/cris/arch-v10/README.mm6
-rw-r--r--arch/cris/arch-v10/kernel/ptrace.c51
-rw-r--r--arch/cris/arch-v10/kernel/signal.c2
-rw-r--r--arch/cris/arch-v32/drivers/cryptocop.c14
-rw-r--r--arch/cris/arch-v32/kernel/ptrace.c51
-rw-r--r--arch/cris/arch-v32/kernel/signal.c2
-rw-r--r--arch/cris/mm/ioremap.c2
-rw-r--r--arch/frv/kernel/ptrace.c43
-rw-r--r--arch/h8300/kernel/ptrace.c39
-rw-r--r--arch/i386/Kconfig13
-rw-r--r--arch/i386/Kconfig.debug10
-rw-r--r--arch/i386/kernel/apic.c10
-rw-r--r--arch/i386/kernel/apm.c5
-rw-r--r--arch/i386/kernel/cpu/common.c5
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/k7.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/mce.c4
-rw-r--r--arch/i386/kernel/cpu/mcheck/p4.c4
-rw-r--r--arch/i386/kernel/cpu/mcheck/p5.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/p6.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/winchip.c2
-rw-r--r--arch/i386/kernel/kprobes.c180
-rw-r--r--arch/i386/kernel/ldt.c1
-rw-r--r--arch/i386/kernel/mca.c2
-rw-r--r--arch/i386/kernel/ptrace.c44
-rw-r--r--arch/i386/kernel/reboot_fixups.c3
-rw-r--r--arch/i386/kernel/scx200.c1
-rw-r--r--arch/i386/kernel/smpboot.c4
-rw-r--r--arch/i386/oprofile/Kconfig6
-rw-r--r--arch/i386/power/cpu.c1
-rw-r--r--arch/ia64/Kconfig13
-rw-r--r--arch/ia64/Kconfig.debug11
-rw-r--r--arch/ia64/hp/sim/simserial.c6
-rw-r--r--arch/ia64/kernel/kprobes.c126
-rw-r--r--arch/ia64/kernel/perfmon.c2
-rw-r--r--arch/ia64/kernel/setup.c7
-rw-r--r--arch/ia64/oprofile/Kconfig6
-rw-r--r--arch/m68k/atari/time.c6
-rw-r--r--arch/m68k/kernel/ptrace.c47
-rw-r--r--arch/m68knommu/Kconfig17
-rw-r--r--arch/m68knommu/Makefile7
-rw-r--r--arch/m68knommu/kernel/asm-offsets.c1
-rw-r--r--arch/m68knommu/kernel/ptrace.c39
-rw-r--r--arch/m68knommu/kernel/setup.c5
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S9
-rw-r--r--arch/m68knommu/platform/520x/Makefile19
-rw-r--r--arch/m68knommu/platform/520x/config.c65
-rw-r--r--arch/m68knommu/platform/5307/Makefile1
-rw-r--r--arch/m68knommu/platform/5307/head.S3
-rw-r--r--arch/m68knommu/platform/5307/ints.c1
-rw-r--r--arch/m68knommu/platform/5307/pit.c12
-rw-r--r--arch/mips/kernel/ptrace.c55
-rw-r--r--arch/parisc/kernel/ptrace.c50
-rw-r--r--arch/powerpc/Kconfig14
-rw-r--r--arch/powerpc/Kconfig.debug10
-rw-r--r--arch/powerpc/kernel/cputable.c10
-rw-r--r--arch/powerpc/kernel/ptrace.c43
-rw-r--r--arch/powerpc/kernel/time.c1
-rw-r--r--arch/powerpc/mm/hash_utils_64.c6
-rw-r--r--arch/powerpc/mm/hugetlbpage.c6
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c4
-rw-r--r--arch/powerpc/mm/slb_low.S13
-rw-r--r--arch/powerpc/oprofile/Kconfig6
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c6
-rw-r--r--arch/ppc/4xx_io/serial_sicc.c17
-rw-r--r--arch/ppc/8260_io/fcc_enet.c3
-rw-r--r--arch/ppc/8xx_io/cs4218_tdm.c3
-rw-r--r--arch/ppc/Kconfig18
-rw-r--r--arch/ppc/boot/simple/Makefile27
-rw-r--r--arch/ppc/boot/simple/misc.c16
-rw-r--r--arch/ppc/boot/simple/openbios.c106
-rw-r--r--arch/ppc/configs/ev64360_defconfig73
-rw-r--r--arch/ppc/configs/stx_gp3_defconfig86
-rw-r--r--arch/ppc/kernel/Makefile1
-rw-r--r--arch/ppc/kernel/head_44x.S4
-rw-r--r--arch/ppc/kernel/rio.c52
-rw-r--r--arch/ppc/platforms/4xx/Kconfig19
-rw-r--r--arch/ppc/platforms/4xx/Makefile2
-rw-r--r--arch/ppc/platforms/4xx/bubinga.c2
-rw-r--r--arch/ppc/platforms/4xx/bubinga.h64
-rw-r--r--arch/ppc/platforms/4xx/ebony.h4
-rw-r--r--arch/ppc/platforms/4xx/ppc440spe.c148
-rw-r--r--arch/ppc/platforms/4xx/ppc440spe.h66
-rw-r--r--arch/ppc/platforms/4xx/sycamore.c7
-rw-r--r--arch/ppc/platforms/4xx/sycamore.h67
-rw-r--r--arch/ppc/platforms/4xx/walnut.c2
-rw-r--r--arch/ppc/platforms/4xx/walnut.h67
-rw-r--r--arch/ppc/platforms/4xx/yucca.c395
-rw-r--r--arch/ppc/platforms/4xx/yucca.h111
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_ads_common.c10
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c14
-rw-r--r--arch/ppc/platforms/ev64360.c12
-rw-r--r--arch/ppc/syslib/Makefile4
-rw-r--r--arch/ppc/syslib/ibm440sp_common.c4
-rw-r--r--arch/ppc/syslib/ibm44x_common.c12
-rw-r--r--arch/ppc/syslib/ppc405_pci.c7
-rw-r--r--arch/ppc/syslib/ppc440spe_pcie.c442
-rw-r--r--arch/ppc/syslib/ppc440spe_pcie.h149
-rw-r--r--arch/ppc/syslib/ppc4xx_pic.c37
-rw-r--r--arch/ppc/syslib/ppc85xx_rio.c938
-rw-r--r--arch/ppc/syslib/ppc85xx_rio.h21
-rw-r--r--arch/ppc/syslib/ppc_sys.c1
-rw-r--r--arch/ppc/syslib/prom.c6
-rw-r--r--arch/ppc64/boot/main.c11
-rw-r--r--arch/ppc64/kernel/kprobes.c138
-rw-r--r--arch/ppc64/kernel/lparcfg.c4
-rw-r--r--arch/ppc64/kernel/scanlog.c3
-rw-r--r--arch/ppc64/kernel/sysfs.c1
-rw-r--r--arch/s390/Makefile4
-rw-r--r--arch/s390/kernel/Makefile4
-rw-r--r--arch/s390/kernel/entry.S4
-rw-r--r--arch/s390/kernel/entry64.S4
-rw-r--r--arch/s390/kernel/head.S383
-rw-r--r--arch/s390/kernel/head31.S336
-rw-r--r--arch/s390/kernel/head64.S543
-rw-r--r--arch/s390/kernel/time.c8
-rw-r--r--arch/s390/kernel/traps.c29
-rw-r--r--arch/s390/mm/extmem.c8
-rw-r--r--arch/s390/mm/fault.c113
-rw-r--r--arch/sh/Kconfig28
-rw-r--r--arch/sh/Makefile8
-rw-r--r--arch/sh/drivers/Makefile5
-rw-r--r--arch/sh/drivers/superhyway/Makefile6
-rw-r--r--arch/sh/drivers/superhyway/ops-sh4-202.c171
-rw-r--r--arch/sh/kernel/ptrace.c44
-rw-r--r--arch/sh/kernel/setup.c26
-rw-r--r--arch/sh/mm/init.c21
-rw-r--r--arch/sh/mm/tlb-sh3.c19
-rw-r--r--arch/sh/ramdisk/Makefile20
-rw-r--r--arch/sh/ramdisk/ld.script9
-rw-r--r--arch/sh64/kernel/ptrace.c83
-rw-r--r--arch/sh64/kernel/syscalls.S2
-rw-r--r--arch/sparc64/Kconfig13
-rw-r--r--arch/sparc64/Kconfig.debug10
-rw-r--r--arch/sparc64/kernel/kprobes.c165
-rw-r--r--arch/sparc64/kernel/us2e_cpufreq.c7
-rw-r--r--arch/sparc64/kernel/us3_cpufreq.c7
-rw-r--r--arch/sparc64/oprofile/Kconfig6
-rw-r--r--arch/um/Kconfig46
-rw-r--r--arch/um/Makefile2
-rw-r--r--arch/um/Makefile-i3862
-rw-r--r--arch/um/drivers/chan_user.c1
-rw-r--r--arch/um/drivers/harddog_kern.c1
-rw-r--r--arch/um/drivers/harddog_user.c1
-rw-r--r--arch/um/drivers/net_kern.c38
-rw-r--r--arch/um/drivers/net_user.c1
-rw-r--r--arch/um/drivers/port_user.c1
-rw-r--r--arch/um/drivers/random.c6
-rw-r--r--arch/um/drivers/slip_user.c1
-rw-r--r--arch/um/drivers/slirp_user.c1
-rw-r--r--arch/um/drivers/xterm.c1
-rw-r--r--arch/um/include/helper.h27
-rw-r--r--arch/um/include/mem_user.h2
-rw-r--r--arch/um/include/net_user.h2
-rw-r--r--arch/um/include/os.h16
-rw-r--r--arch/um/include/sysdep-i386/stub.h64
-rw-r--r--arch/um/include/sysdep-x86_64/stub.h61
-rw-r--r--arch/um/include/uml_uaccess.h4
-rw-r--r--arch/um/kernel/Makefile7
-rw-r--r--arch/um/kernel/ksyms.c1
-rw-r--r--arch/um/kernel/mem.c4
-rw-r--r--arch/um/kernel/physmem.c4
-rw-r--r--arch/um/kernel/ptrace.c50
-rw-r--r--arch/um/kernel/sigio_user.c3
-rw-r--r--arch/um/kernel/skas/include/mmu-skas.h2
-rw-r--r--arch/um/kernel/skas/include/skas.h3
-rw-r--r--arch/um/kernel/skas/mem.c2
-rw-r--r--arch/um/kernel/skas/mmu.c44
-rw-r--r--arch/um/kernel/skas/process.c17
-rw-r--r--arch/um/kernel/skas/process_kern.c2
-rw-r--r--arch/um/kernel/tt/uaccess_user.c1
-rw-r--r--arch/um/kernel/uaccess.c30
-rw-r--r--arch/um/kernel/uaccess_user.c64
-rw-r--r--arch/um/kernel/um_arch.c10
-rw-r--r--arch/um/kernel/user_util.c1
-rw-r--r--arch/um/os-Linux/Makefile9
-rw-r--r--arch/um/os-Linux/aio.c1
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c1
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c1
-rw-r--r--arch/um/os-Linux/helper.c (renamed from arch/um/kernel/helper.c)18
-rw-r--r--arch/um/os-Linux/main.c (renamed from arch/um/kernel/main.c)49
-rw-r--r--arch/um/os-Linux/mem.c6
-rw-r--r--arch/um/os-Linux/start_up.c77
-rw-r--r--arch/um/os-Linux/uaccess.c32
-rw-r--r--arch/um/scripts/Makefile.rules7
-rw-r--r--arch/um/sys-i386/ldt.c506
-rw-r--r--arch/um/sys-x86_64/Makefile5
-rw-r--r--arch/um/sys-x86_64/syscalls.c75
-rw-r--r--arch/v850/kernel/ptrace.c43
-rw-r--r--arch/x86_64/Kconfig13
-rw-r--r--arch/x86_64/Kconfig.debug10
-rw-r--r--arch/x86_64/kernel/kprobes.c183
-rw-r--r--arch/x86_64/kernel/ptrace.c43
-rw-r--r--arch/x86_64/kernel/smpboot.c2
-rw-r--r--arch/x86_64/oprofile/Kconfig6
-rw-r--r--arch/xtensa/kernel/ptrace.c55
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acpi/container.c6
-rw-r--r--drivers/acpi/osl.c6
-rw-r--r--drivers/acpi/scan.c6
-rw-r--r--drivers/acpi/video.c12
-rw-r--r--drivers/base/power/sysfs.c1
-rw-r--r--drivers/block/DAC960.c31
-rw-r--r--drivers/block/as-iosched.c310
-rw-r--r--drivers/block/cciss.c12
-rw-r--r--drivers/block/ll_rw_blk.c1
-rw-r--r--drivers/bluetooth/bcm203x.c4
-rw-r--r--drivers/bluetooth/bfusb.c4
-rw-r--r--drivers/bluetooth/bluecard_cs.c3
-rw-r--r--drivers/bluetooth/bpa10x.c4
-rw-r--r--drivers/bluetooth/bt3c_cs.c3
-rw-r--r--drivers/bluetooth/btuart_cs.c3
-rw-r--r--drivers/bluetooth/dtl1_cs.c3
-rw-r--r--drivers/bluetooth/hci_bcsp.c3
-rw-r--r--drivers/bluetooth/hci_h4.c4
-rw-r--r--drivers/bluetooth/hci_ldisc.c4
-rw-r--r--drivers/bluetooth/hci_usb.c4
-rw-r--r--drivers/bluetooth/hci_vhci.c4
-rw-r--r--drivers/cdrom/mcdx.c4
-rw-r--r--drivers/char/agp/amd64-agp.c1
-rw-r--r--drivers/char/consolemap.c12
-rw-r--r--drivers/char/drm/ffb_context.c6
-rw-r--r--drivers/char/drm/ffb_drv.c6
-rw-r--r--drivers/char/ip2/i2ellis.c4
-rw-r--r--drivers/char/ipmi/ipmi_bt_sm.c38
-rw-r--r--drivers/char/ipmi/ipmi_kcs_sm.c48
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c952
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c4
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c183
-rw-r--r--drivers/char/ipmi/ipmi_si_sm.h1
-rw-r--r--drivers/char/ipmi/ipmi_smic_sm.c15
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c259
-rw-r--r--drivers/char/istallion.c7
-rw-r--r--drivers/char/mxser.c47
-rw-r--r--drivers/char/n_hdlc.c3
-rw-r--r--drivers/char/pcmcia/synclink_cs.c3
-rw-r--r--drivers/char/rocket.c6
-rw-r--r--drivers/char/selection.c3
-rw-r--r--drivers/char/stallion.c6
-rw-r--r--drivers/char/synclink.c10
-rw-r--r--drivers/char/synclinkmp.c9
-rw-r--r--drivers/char/tpm/tpm_nsc.c48
-rw-r--r--drivers/char/tty_io.c9
-rw-r--r--drivers/char/vt_ioctl.c5
-rw-r--r--drivers/connector/Kconfig8
-rw-r--r--drivers/connector/Makefile1
-rw-r--r--drivers/connector/cn_proc.c222
-rw-r--r--drivers/dio/dio.c3
-rw-r--r--drivers/eisa/eisa-bus.c8
-rw-r--r--drivers/fc4/fc.c32
-rw-r--r--drivers/fc4/soc.c3
-rw-r--r--drivers/fc4/socal.c3
-rw-r--r--drivers/firmware/dell_rbu.c121
-rw-r--r--drivers/firmware/edd.c3
-rw-r--r--drivers/firmware/efivars.c10
-rw-r--r--drivers/hwmon/hwmon.c1
-rw-r--r--drivers/hwmon/max1619.c14
-rw-r--r--drivers/hwmon/w83781d.c6
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c6
-rw-r--r--drivers/ide/ide-cd.c22
-rw-r--r--drivers/ide/ide-disk.c4
-rw-r--r--drivers/ide/ide-floppy.c4
-rw-r--r--drivers/ide/ide-probe.c9
-rw-r--r--drivers/ide/ide-tape.c4
-rw-r--r--drivers/ide/ide-taskfile.c18
-rw-r--r--drivers/ide/ide.c6
-rw-r--r--drivers/ide/legacy/ide-cs.c6
-rw-r--r--drivers/ide/pci/hpt366.c3
-rw-r--r--drivers/ide/pci/it821x.c3
-rw-r--r--drivers/ieee1394/amdtp.c3
-rw-r--r--drivers/infiniband/core/agent.c3
-rw-r--r--drivers/infiniband/core/mad.c6
-rw-r--r--drivers/infiniband/core/packer.c2
-rw-r--r--drivers/infiniband/core/sysfs.c3
-rw-r--r--drivers/infiniband/core/ud_header.c1
-rw-r--r--drivers/infiniband/core/verbs.c1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_catas.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c3
-rw-r--r--drivers/input/misc/uinput.c10
-rw-r--r--drivers/isdn/hardware/avm/avm_cs.c5
-rw-r--r--drivers/isdn/hisax/avm_pci.c12
-rw-r--r--drivers/isdn/hisax/avma1_cs.c4
-rw-r--r--drivers/isdn/hisax/config.c9
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c18
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c12
-rw-r--r--drivers/isdn/hisax/hfc_usb.c292
-rw-r--r--drivers/isdn/hisax/hfc_usb.h6
-rw-r--r--drivers/isdn/hisax/hscx.c12
-rw-r--r--drivers/isdn/hisax/icc.c12
-rw-r--r--drivers/isdn/hisax/ipacx.c12
-rw-r--r--drivers/isdn/hisax/isac.c15
-rw-r--r--drivers/isdn/hisax/isar.c6
-rw-r--r--drivers/isdn/hisax/jade.c12
-rw-r--r--drivers/isdn/hisax/netjet.c32
-rw-r--r--drivers/isdn/hisax/st5481_usb.c12
-rw-r--r--drivers/isdn/hisax/w6692.c12
-rw-r--r--drivers/isdn/hysdn/hysdn_procconf.c3
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c21
-rw-r--r--drivers/isdn/i4l/isdn_tty.c27
-rw-r--r--drivers/isdn/icn/icn.c3
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c9
-rw-r--r--drivers/isdn/pcbit/drv.c6
-rw-r--r--drivers/isdn/sc/init.c3
-rw-r--r--drivers/isdn/sc/message.c3
-rw-r--r--drivers/macintosh/adbhid.c3
-rw-r--r--drivers/macintosh/therm_pm72.c3
-rw-r--r--drivers/md/raid5.c3
-rw-r--r--drivers/md/raid6main.c3
-rw-r--r--drivers/media/dvb/bt8xx/dst.c8
-rw-r--r--drivers/media/dvb/frontends/cx24110.c1
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c4
-rw-r--r--drivers/media/dvb/frontends/l64781.c3
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c3
-rw-r--r--drivers/media/dvb/frontends/mt312.c3
-rw-r--r--drivers/media/dvb/frontends/or51132.c3
-rw-r--r--drivers/media/video/arv.c12
-rw-r--r--drivers/media/video/bttv-driver.c6
-rw-r--r--drivers/media/video/msp3400.c4
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c4
-rw-r--r--drivers/media/video/v4l1-compat.c6
-rw-r--r--drivers/media/video/videocodec.c6
-rw-r--r--drivers/media/video/videodev.c3
-rw-r--r--drivers/media/video/zoran_card.c14
-rw-r--r--drivers/media/video/zoran_driver.c4
-rw-r--r--drivers/message/fusion/mptlan.c10
-rw-r--r--drivers/message/fusion/mptscsih.c6
-rw-r--r--drivers/message/i2o/exec-osm.c1
-rw-r--r--drivers/message/i2o/iop.c15
-rw-r--r--drivers/mfd/mcp-core.c2
-rw-r--r--drivers/mmc/wbsd.c3
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c3
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c4
-rw-r--r--drivers/mtd/devices/blkmtd.c7
-rw-r--r--drivers/mtd/inftlcore.c12
-rw-r--r--drivers/mtd/inftlmount.c6
-rw-r--r--drivers/mtd/maps/amd76xrom.c4
-rw-r--r--drivers/mtd/maps/bast-flash.c3
-rw-r--r--drivers/mtd/maps/ceiva.c3
-rw-r--r--drivers/mtd/maps/ichxrom.c5
-rw-r--r--drivers/mtd/maps/integrator-flash.c6
-rw-r--r--drivers/mtd/maps/ipaq-flash.c3
-rw-r--r--drivers/mtd/maps/iq80310.c3
-rw-r--r--drivers/mtd/maps/ixp2000.c3
-rw-r--r--drivers/mtd/maps/ixp4xx.c3
-rw-r--r--drivers/mtd/maps/lubbock-flash.c3
-rw-r--r--drivers/mtd/maps/omap-toto-flash.c3
-rw-r--r--drivers/mtd/maps/sa1100-flash.c3
-rw-r--r--drivers/mtd/maps/sun_uflash.c4
-rw-r--r--drivers/mtd/maps/tqm8xxl.c6
-rw-r--r--drivers/mtd/nand/nand_base.c5
-rw-r--r--drivers/mtd/nftlcore.c12
-rw-r--r--drivers/net/3c59x.c586
-rw-r--r--drivers/net/fec.c240
-rw-r--r--drivers/net/fec.h10
-rw-r--r--drivers/parport/probe.c21
-rw-r--r--drivers/parport/share.c19
-rw-r--r--drivers/pci/hotplug/cpqphp_pci.c15
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.c1
-rw-r--r--drivers/pci/pci-driver.c1
-rw-r--r--drivers/pcmcia/cistpl.c12
-rw-r--r--drivers/pcmcia/cs.c6
-rw-r--r--drivers/pnp/card.c4
-rw-r--r--drivers/pnp/core.c5
-rw-r--r--drivers/pnp/driver.c2
-rw-r--r--drivers/pnp/isapnp/core.c2
-rw-r--r--drivers/pnp/manager.c2
-rw-r--r--drivers/pnp/pnpacpi/core.c6
-rw-r--r--drivers/pnp/resource.c2
-rw-r--r--drivers/rapidio/Kconfig18
-rw-r--r--drivers/rapidio/Makefile6
-rw-r--r--drivers/rapidio/rio-access.c175
-rw-r--r--drivers/rapidio/rio-driver.c229
-rw-r--r--drivers/rapidio/rio-scan.c945
-rw-r--r--drivers/rapidio/rio-sysfs.c230
-rw-r--r--drivers/rapidio/rio.c510
-rw-r--r--drivers/rapidio/rio.h60
-rw-r--r--drivers/rapidio/switches/Makefile5
-rw-r--r--drivers/rapidio/switches/tsi500.c60
-rw-r--r--drivers/s390/block/dasd.c12
-rw-r--r--drivers/s390/block/dasd_devmap.c3
-rw-r--r--drivers/s390/block/dasd_diag.c64
-rw-r--r--drivers/s390/block/dasd_diag.h10
-rw-r--r--drivers/s390/char/con3215.c3
-rw-r--r--drivers/s390/char/keyboard.c15
-rw-r--r--drivers/s390/char/raw3270.c3
-rw-r--r--drivers/s390/char/tape_core.c9
-rw-r--r--drivers/s390/char/vmcp.c4
-rw-r--r--drivers/s390/cio/ccwgroup.c6
-rw-r--r--drivers/s390/cio/cmf.c3
-rw-r--r--drivers/s390/cio/device_ops.c6
-rw-r--r--drivers/s390/cio/qdio.c17
-rw-r--r--drivers/s390/crypto/z90main.c7
-rw-r--r--drivers/s390/net/claw.c36
-rw-r--r--drivers/s390/net/fsm.c3
-rw-r--r--drivers/s390/net/iucv.c12
-rw-r--r--drivers/s390/net/lcs.c3
-rw-r--r--drivers/s390/net/qeth_eddp.c3
-rw-r--r--drivers/s390/scsi/zfcp_aux.c3
-rw-r--r--drivers/sbus/char/envctrl.c13
-rw-r--r--drivers/scsi/3w-9xxx.c3
-rw-r--r--drivers/scsi/NCR5380.c5
-rw-r--r--drivers/scsi/aacraid/commsup.c14
-rw-r--r--drivers/scsi/aacraid/rkt.c6
-rw-r--r--drivers/scsi/aacraid/rx.c6
-rw-r--r--drivers/scsi/aacraid/sa.c6
-rw-r--r--drivers/scsi/advansys.c12
-rw-r--r--drivers/scsi/aha1542.c36
-rw-r--r--drivers/scsi/aic7xxx_old.c3
-rw-r--r--drivers/scsi/arm/queue.c3
-rw-r--r--drivers/scsi/atari_dma_emul.c2
-rw-r--r--drivers/scsi/dc395x.c3
-rw-r--r--drivers/scsi/dpt_i2o.c61
-rw-r--r--drivers/scsi/eata.c3
-rw-r--r--drivers/scsi/ide-scsi.c10
-rw-r--r--drivers/scsi/ips.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c9
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c12
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c7
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c5
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c11
-rw-r--r--drivers/scsi/osst.c9
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c16
-rw-r--r--drivers/scsi/raid_class.c2
-rw-r--r--drivers/scsi/scsi_transport_sas.c2
-rw-r--r--drivers/scsi/sg.c9
-rw-r--r--drivers/scsi/st.c3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c1
-rw-r--r--drivers/scsi/u14-34f.c9
-rw-r--r--drivers/serial/8250.c3
-rw-r--r--drivers/serial/crisv10.c9
-rw-r--r--drivers/serial/mcfserial.c37
-rw-r--r--drivers/sh/superhyway/superhyway-sysfs.c2
-rw-r--r--drivers/sh/superhyway/superhyway.c75
-rw-r--r--drivers/video/68328fb.c1
-rw-r--r--drivers/video/Kconfig214
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/acornfb.c1
-rw-r--r--drivers/video/amba-clcd.c1
-rw-r--r--drivers/video/amifb.c1
-rw-r--r--drivers/video/arcfb.c1
-rw-r--r--drivers/video/asiliantfb.c1
-rw-r--r--drivers/video/aty/ati_ids.h1
-rw-r--r--drivers/video/aty/aty128fb.c1
-rw-r--r--drivers/video/aty/atyfb_base.c59
-rw-r--r--drivers/video/aty/radeon_base.c3
-rw-r--r--drivers/video/aty/radeonfb.h3
-rw-r--r--drivers/video/bw2.c1
-rw-r--r--drivers/video/cfbcopyarea.c36
-rw-r--r--drivers/video/cfbfillrect.c24
-rw-r--r--drivers/video/cfbimgblt.c22
-rw-r--r--drivers/video/cg14.c1
-rw-r--r--drivers/video/cg3.c1
-rw-r--r--drivers/video/cg6.c1
-rw-r--r--drivers/video/chipsfb.c1
-rw-r--r--drivers/video/cirrusfb.c1
-rw-r--r--drivers/video/clps711xfb.c1
-rw-r--r--drivers/video/console/Kconfig9
-rw-r--r--drivers/video/console/Makefile3
-rw-r--r--drivers/video/console/bitblit.c7
-rw-r--r--drivers/video/console/fbcon.c114
-rw-r--r--drivers/video/console/fbcon.h2
-rw-r--r--drivers/video/console/font_rl.c4374
-rw-r--r--drivers/video/console/fonts.c4
-rw-r--r--drivers/video/console/softcursor.c (renamed from drivers/video/softcursor.c)8
-rw-r--r--drivers/video/controlfb.c1
-rw-r--r--drivers/video/cyber2000fb.c1
-rw-r--r--drivers/video/cyblafb.c1
-rw-r--r--drivers/video/dnfb.c1
-rw-r--r--drivers/video/epson1355fb.c1
-rw-r--r--drivers/video/fbmon.c48
-rw-r--r--drivers/video/ffb.c3
-rw-r--r--drivers/video/fm2fb.c1
-rw-r--r--drivers/video/gbefb.c1
-rw-r--r--drivers/video/geode/Kconfig1
-rw-r--r--drivers/video/geode/gx1fb_core.c1
-rw-r--r--drivers/video/hitfb.c1
-rw-r--r--drivers/video/hpfb.c1
-rw-r--r--drivers/video/i810/i810-i2c.c135
-rw-r--r--drivers/video/i810/i810.h3
-rw-r--r--drivers/video/i810/i810_main.c22
-rw-r--r--drivers/video/i810/i810_regs.h1
-rw-r--r--drivers/video/imsttfb.c1
-rw-r--r--drivers/video/imxfb.c1
-rw-r--r--drivers/video/intelfb/intelfb.h6
-rw-r--r--drivers/video/intelfb/intelfbdrv.c10
-rw-r--r--drivers/video/intelfb/intelfbhw.c5
-rw-r--r--drivers/video/kyro/fbdev.c1
-rw-r--r--drivers/video/leo.c1
-rw-r--r--drivers/video/logo/Kconfig2
-rw-r--r--drivers/video/macfb.c1
-rw-r--r--drivers/video/matrox/matroxfb_DAC1064.c4
-rw-r--r--drivers/video/matrox/matroxfb_accel.c2
-rw-r--r--drivers/video/matrox/matroxfb_base.c29
-rw-r--r--drivers/video/matrox/matroxfb_base.h5
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c1
-rw-r--r--drivers/video/maxinefb.c1
-rw-r--r--drivers/video/modedb.c84
-rw-r--r--drivers/video/neofb.c1
-rw-r--r--drivers/video/nvidia/nv_local.h2
-rw-r--r--drivers/video/nvidia/nv_of.c64
-rw-r--r--drivers/video/nvidia/nv_proto.h18
-rw-r--r--drivers/video/nvidia/nv_setup.c16
-rw-r--r--drivers/video/nvidia/nvidia.c128
-rw-r--r--drivers/video/offb.c1
-rw-r--r--drivers/video/p9100.c1
-rw-r--r--drivers/video/platinumfb.c1
-rw-r--r--drivers/video/pm2fb.c17
-rw-r--r--drivers/video/pmag-ba-fb.c1
-rw-r--r--drivers/video/pmagb-b-fb.c1
-rw-r--r--drivers/video/pvr2fb.c1
-rw-r--r--drivers/video/pxafb.c1
-rw-r--r--drivers/video/q40fb.c1
-rw-r--r--drivers/video/radeonfb.c1
-rw-r--r--drivers/video/s1d13xxxfb.c1
-rw-r--r--drivers/video/s3c2410fb.c2
-rw-r--r--drivers/video/sa1100fb.c1
-rw-r--r--drivers/video/savage/savagefb.h206
-rw-r--r--drivers/video/savage/savagefb_driver.c840
-rw-r--r--drivers/video/sgivwfb.c1
-rw-r--r--drivers/video/sis/sis_main.c2
-rw-r--r--drivers/video/skeletonfb.c9
-rw-r--r--drivers/video/sstfb.c1
-rw-r--r--drivers/video/stifb.c1
-rw-r--r--drivers/video/tcx.c1
-rw-r--r--drivers/video/tdfxfb.c1
-rw-r--r--drivers/video/tgafb.c1
-rw-r--r--drivers/video/tridentfb.c1
-rw-r--r--drivers/video/tx3912fb.c1
-rw-r--r--drivers/video/valkyriefb.c1
-rw-r--r--drivers/video/vesafb.c59
-rw-r--r--drivers/video/vfb.c1
-rw-r--r--drivers/video/vga16fb.c1
-rw-r--r--drivers/video/w100fb.c1
-rw-r--r--drivers/w1/w1_ds2433.c6
-rw-r--r--fs/9p/error.c1
-rw-r--r--fs/9p/trans_sock.c3
-rw-r--r--fs/9p/v9fs.c6
-rw-r--r--fs/9p/vfs_inode.c10
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/affs/file.c18
-rw-r--r--fs/affs/super.c16
-rw-r--r--fs/afs/file.c33
-rw-r--r--fs/afs/inode.c2
-rw-r--r--fs/afs/internal.h1
-rw-r--r--fs/aio.c31
-rw-r--r--fs/autofs/waitq.c6
-rw-r--r--fs/autofs4/inode.c6
-rw-r--r--fs/autofs4/waitq.c6
-rw-r--r--fs/befs/linuxvfs.c20
-rw-r--r--fs/binfmt_elf.c3
-rw-r--r--fs/binfmt_elf_fdpic.c15
-rw-r--r--fs/buffer.c6
-rw-r--r--fs/cifs/asn1.c3
-rw-r--r--fs/cifs/connect.c81
-rw-r--r--fs/cifs/link.c23
-rw-r--r--fs/cifs/misc.c15
-rw-r--r--fs/cifs/xattr.c15
-rw-r--r--fs/compat_ioctl.c3
-rw-r--r--fs/dcache.c10
-rw-r--r--fs/devfs/base.c6
-rw-r--r--fs/dquot.c1
-rw-r--r--fs/exec.c4
-rw-r--r--fs/ext2/acl.c6
-rw-r--r--fs/file_table.c4
-rw-r--r--fs/freevxfs/vxfs_extern.h4
-rw-r--r--fs/freevxfs/vxfs_inode.c11
-rw-r--r--fs/fs-writeback.c7
-rw-r--r--fs/fuse/dev.c7
-rw-r--r--fs/fuse/dir.c172
-rw-r--r--fs/fuse/file.c132
-rw-r--r--fs/fuse/fuse_i.h17
-rw-r--r--fs/hostfs/hostfs_kern.c3
-rw-r--r--fs/hpfs/dnode.c8
-rw-r--r--fs/hpfs/super.c10
-rw-r--r--fs/isofs/inode.c12
-rw-r--r--fs/jbd/commit.c6
-rw-r--r--fs/jbd/recovery.c4
-rw-r--r--fs/jbd/transaction.c9
-rw-r--r--fs/jffs/intrep.c18
-rw-r--r--fs/jffs2/readinode.c8
-rw-r--r--fs/jffs2/wbuf.c3
-rw-r--r--fs/lockd/clntproc.c3
-rw-r--r--fs/mbcache.c3
-rw-r--r--fs/namei.c2
-rw-r--r--fs/nfs/delegation.c3
-rw-r--r--fs/nfs/inode.c15
-rw-r--r--fs/nfs/nfs4state.c9
-rw-r--r--fs/nfs/unlink.c3
-rw-r--r--fs/nfsd/export.c6
-rw-r--r--fs/nfsd/nfs3xdr.c3
-rw-r--r--fs/nfsd/nfs4xdr.c9
-rw-r--r--fs/nfsd/nfscache.c3
-rw-r--r--fs/nfsd/nfsctl.c98
-rw-r--r--fs/nfsd/nfssvc.c80
-rw-r--r--fs/nfsd/vfs.c9
-rw-r--r--fs/open.c19
-rw-r--r--fs/openpromfs/inode.c3
-rw-r--r--fs/partitions/ibm.c15
-rw-r--r--fs/quota.c1
-rw-r--r--fs/smbfs/request.c3
-rw-r--r--fs/smbfs/symlink.c4
-rw-r--r--fs/super.c2
-rw-r--r--fs/udf/udf_sb.h3
-rw-r--r--fs/ufs/super.c14
-rw-r--r--fs/xattr.c9
-rw-r--r--fs/xfs/linux-2.6/kmem.h4
-rw-r--r--include/asm-alpha/pgtable.h3
-rw-r--r--include/asm-alpha/ptrace.h3
-rw-r--r--include/asm-cris/arch-v10/byteorder.h4
-rw-r--r--include/asm-cris/arch-v10/checksum.h2
-rw-r--r--include/asm-cris/arch-v10/delay.h2
-rw-r--r--include/asm-cris/arch-v10/ide.h8
-rw-r--r--include/asm-cris/arch-v10/system.h8
-rw-r--r--include/asm-cris/arch-v10/thread_info.h2
-rw-r--r--include/asm-cris/arch-v10/timex.h2
-rw-r--r--include/asm-cris/arch-v10/uaccess.h4
-rw-r--r--include/asm-cris/arch-v32/bitops.h10
-rw-r--r--include/asm-cris/arch-v32/byteorder.h4
-rw-r--r--include/asm-cris/arch-v32/checksum.h2
-rw-r--r--include/asm-cris/arch-v32/delay.h2
-rw-r--r--include/asm-cris/arch-v32/ide.h4
-rw-r--r--include/asm-cris/arch-v32/io.h6
-rw-r--r--include/asm-cris/arch-v32/system.h6
-rw-r--r--include/asm-cris/arch-v32/thread_info.h2
-rw-r--r--include/asm-cris/arch-v32/timex.h2
-rw-r--r--include/asm-cris/arch-v32/uaccess.h4
-rw-r--r--include/asm-cris/atomic.h22
-rw-r--r--include/asm-cris/bitops.h18
-rw-r--r--include/asm-cris/checksum.h8
-rw-r--r--include/asm-cris/current.h2
-rw-r--r--include/asm-cris/delay.h2
-rw-r--r--include/asm-cris/io.h6
-rw-r--r--include/asm-cris/irq.h2
-rw-r--r--include/asm-cris/pgalloc.h12
-rw-r--r--include/asm-cris/pgtable.h46
-rw-r--r--include/asm-cris/processor.h6
-rw-r--r--include/asm-cris/semaphore.h16
-rw-r--r--include/asm-cris/system.h2
-rw-r--r--include/asm-cris/timex.h2
-rw-r--r--include/asm-cris/tlbflush.h4
-rw-r--r--include/asm-cris/uaccess.h22
-rw-r--r--include/asm-cris/unistd.h20
-rw-r--r--include/asm-frv/pgtable.h2
-rw-r--r--include/asm-generic/pgtable.h1
-rw-r--r--include/asm-generic/vmlinux.lds.h7
-rw-r--r--include/asm-i386/elf.h2
-rw-r--r--include/asm-i386/kprobes.h17
-rw-r--r--include/asm-i386/pgtable.h3
-rw-r--r--include/asm-i386/processor.h6
-rw-r--r--include/asm-ia64/dma-mapping.h7
-rw-r--r--include/asm-ia64/kprobes.h13
-rw-r--r--include/asm-ia64/pgtable.h1
-rw-r--r--include/asm-ia64/ptrace.h3
-rw-r--r--include/asm-m32r/pgtable.h3
-rw-r--r--include/asm-m32r/ptrace.h3
-rw-r--r--include/asm-m68knommu/cacheflush.h4
-rw-r--r--include/asm-m68knommu/irq.h31
-rw-r--r--include/asm-m68knommu/irqnode.h36
-rw-r--r--include/asm-mips/elf.h2
-rw-r--r--include/asm-mips/pgtable.h3
-rw-r--r--include/asm-parisc/pgtable.h3
-rw-r--r--include/asm-powerpc/elf.h2
-rw-r--r--include/asm-powerpc/kprobes.h15
-rw-r--r--include/asm-ppc/ibm44x.h76
-rw-r--r--include/asm-ppc/ibm4xx.h4
-rw-r--r--include/asm-ppc/ibm_ocp.h19
-rw-r--r--include/asm-ppc/pgtable.h1
-rw-r--r--include/asm-ppc/ppcboot.h6
-rw-r--r--include/asm-ppc/rio.h18
-rw-r--r--include/asm-ppc64/pgtable-4k.h3
-rw-r--r--include/asm-ppc64/pgtable-64k.h3
-rw-r--r--include/asm-ppc64/pgtable.h1
-rw-r--r--include/asm-s390/bitops.h4
-rw-r--r--include/asm-s390/elf.h1
-rw-r--r--include/asm-s390/pgtable.h1
-rw-r--r--include/asm-s390/ptrace.h2
-rw-r--r--include/asm-s390/uaccess.h28
-rw-r--r--include/asm-s390/vtoc.h505
-rw-r--r--include/asm-sh/elf.h1
-rw-r--r--include/asm-sh/mmzone.h61
-rw-r--r--include/asm-sh/page.h7
-rw-r--r--include/asm-sh/pgtable.h4
-rw-r--r--include/asm-sh64/pgtable.h2
-rw-r--r--include/asm-sparc/ptrace.h3
-rw-r--r--include/asm-sparc64/kprobes.h20
-rw-r--r--include/asm-sparc64/ptrace.h3
-rw-r--r--include/asm-um/ldt-i386.h69
-rw-r--r--include/asm-um/ldt.h69
-rw-r--r--include/asm-um/mmu_context.h3
-rw-r--r--include/asm-v850/atomic.h2
-rw-r--r--include/asm-v850/bitops.h6
-rw-r--r--include/asm-v850/delay.h4
-rw-r--r--include/asm-v850/hw_irq.h2
-rw-r--r--include/asm-v850/processor.h4
-rw-r--r--include/asm-v850/semaphore.h10
-rw-r--r--include/asm-v850/system.h2
-rw-r--r--include/asm-v850/tlbflush.h4
-rw-r--r--include/asm-v850/uaccess.h2
-rw-r--r--include/asm-v850/unaligned.h6
-rw-r--r--include/asm-x86_64/elf.h2
-rw-r--r--include/asm-x86_64/kprobes.h19
-rw-r--r--include/asm-x86_64/pgtable.h2
-rw-r--r--include/asm-xtensa/elf.h2
-rw-r--r--include/asm-xtensa/pgtable.h3
-rw-r--r--include/asm-xtensa/semaphore.h1
-rw-r--r--include/linux/aio.h5
-rw-r--r--include/linux/cn_proc.h127
-rw-r--r--include/linux/connector.h6
-rw-r--r--include/linux/console_struct.h2
-rw-r--r--include/linux/fb.h5
-rw-r--r--include/linux/file.h6
-rw-r--r--include/linux/font.h2
-rw-r--r--include/linux/fs.h12
-rw-r--r--include/linux/fuse.h29
-rw-r--r--include/linux/ioport.h2
-rw-r--r--include/linux/ipmi.h5
-rw-r--r--include/linux/irq.h1
-rw-r--r--include/linux/jbd.h3
-rw-r--r--include/linux/kernel.h3
-rw-r--r--include/linux/kernel_stat.h8
-rw-r--r--include/linux/kprobes.h40
-rw-r--r--include/linux/list.h13
-rw-r--r--include/linux/memory.h3
-rw-r--r--include/linux/mm.h8
-rw-r--r--include/linux/net.h1
-rw-r--r--include/linux/nfsd/nfsd.h2
-rw-r--r--include/linux/nfsd/syscall.h17
-rw-r--r--include/linux/nfsd/xdr3.h2
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/linux/pnp.h2
-rw-r--r--include/linux/ptrace.h2
-rw-r--r--include/linux/quotaops.h12
-rw-r--r--include/linux/radix-tree.h1
-rw-r--r--include/linux/rio.h325
-rw-r--r--include/linux/rio_drv.h469
-rw-r--r--include/linux/rio_ids.h24
-rw-r--r--include/linux/rio_regs.h215
-rw-r--r--include/linux/sem.h2
-rw-r--r--include/linux/shm.h1
-rw-r--r--include/linux/slab.h2
-rw-r--r--include/linux/sunrpc/svc.h3
-rw-r--r--include/linux/superhyway.h38
-rw-r--r--include/linux/wait.h1
-rw-r--r--ipc/shm.c10
-rw-r--r--ipc/util.c9
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/futex.c5
-rw-r--r--kernel/irq/manage.c1
-rw-r--r--kernel/kprobes.c134
-rw-r--r--kernel/module.c1
-rw-r--r--kernel/posix-cpu-timers.c6
-rw-r--r--kernel/power/snapshot.c19
-rw-r--r--kernel/power/swsusp.c45
-rw-r--r--kernel/printk.c1
-rw-r--r--kernel/ptrace.c82
-rw-r--r--kernel/sched.c5
-rw-r--r--kernel/softirq.c3
-rw-r--r--kernel/softlockup.c3
-rw-r--r--kernel/sys.c26
-rw-r--r--kernel/sysctl.c5
-rw-r--r--kernel/workqueue.c2
-rw-r--r--lib/radix-tree.c51
-rw-r--r--mm/Kconfig2
-rw-r--r--mm/hugetlb.c1
-rw-r--r--mm/mmap.c4
-rw-r--r--mm/nommu.c4
-rw-r--r--mm/page-writeback.c1
-rw-r--r--mm/page_alloc.c1
-rw-r--r--mm/readahead.c31
-rw-r--r--mm/slab.c74
-rw-r--r--mm/swap.c1
-rw-r--r--mm/swap_state.c1
-rw-r--r--mm/swapfile.c2
-rw-r--r--mm/vmalloc.c4
-rw-r--r--net/sunrpc/svc.c12
-rw-r--r--scripts/kconfig/Makefile2
-rw-r--r--security/keys/key.c3
-rw-r--r--security/keys/keyring.c8
-rw-r--r--security/selinux/ss/policydb.c12
-rw-r--r--sound/oss/sequencer_syms.c1
813 files changed, 19553 insertions, 8415 deletions
diff --git a/Documentation/Changes b/Documentation/Changes
index 783ddc3ce4e8..86b86399d61d 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -139,9 +139,14 @@ You'll probably want to upgrade.
Ksymoops
--------
-If the unthinkable happens and your kernel oopses, you'll need a 2.4
-version of ksymoops to decode the report; see REPORTING-BUGS in the
-root of the Linux source for more information.
+If the unthinkable happens and your kernel oopses, you may need the
+ksymoops tool to decode it, but in most cases you don't.
+In the 2.6 kernel it is generally preferred to build the kernel with
+CONFIG_KALLSYMS so that it produces readable dumps that can be used as-is
+(this also produces better output than ksymoops).
+If for some reason your kernel is not build with CONFIG_KALLSYMS and
+you have no way to rebuild and reproduce the Oops with that option, then
+you can still decode that Oops with ksymoops.
Module-Init-Tools
-----------------
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index fa3e29ad8a46..7018f5c6a447 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -10,7 +10,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
procfs-guide.xml writing_usb_driver.xml \
sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
- gadget.xml libata.xml mtdnand.xml librs.xml
+ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml
###
# The build process is as follows (targets):
diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl
index 341aaa4ce481..2077f9a28c19 100644
--- a/Documentation/DocBook/journal-api.tmpl
+++ b/Documentation/DocBook/journal-api.tmpl
@@ -306,7 +306,7 @@ an example.
</para>
<sect1><title>Journal Level</title>
!Efs/jbd/journal.c
-!Efs/jbd/recovery.c
+!Ifs/jbd/recovery.c
</sect1>
<sect1><title>Transasction Level</title>
!Efs/jbd/transaction.c
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index ec474e5a25ed..a8316b1a3e3d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -118,7 +118,7 @@ X!Ilib/string.c
</sect1>
<sect1><title>User Space Memory Access</title>
!Iinclude/asm-i386/uaccess.h
-!Iarch/i386/lib/usercopy.c
+!Earch/i386/lib/usercopy.c
</sect1>
<sect1><title>More Memory Management Functions</title>
!Iinclude/linux/rmap.h
@@ -174,7 +174,6 @@ X!Ilib/string.c
<title>The Linux VFS</title>
<sect1><title>The Filesystem types</title>
!Iinclude/linux/fs.h
-!Einclude/linux/fs.h
</sect1>
<sect1><title>The Directory Cache</title>
!Efs/dcache.c
@@ -266,7 +265,7 @@ X!Ekernel/module.c
<chapter id="hardware">
<title>Hardware Interfaces</title>
<sect1><title>Interrupt Handling</title>
-!Ikernel/irq/manage.c
+!Ekernel/irq/manage.c
</sect1>
<sect1><title>Resources Management</title>
@@ -501,7 +500,7 @@ KAO -->
!Edrivers/video/modedb.c
</sect1>
<sect1><title>Frame Buffer Macintosh Video Mode Database</title>
-!Idrivers/video/macmodes.c
+!Edrivers/video/macmodes.c
</sect1>
<sect1><title>Frame Buffer Fonts</title>
<para>
diff --git a/Documentation/DocBook/rapidio.tmpl b/Documentation/DocBook/rapidio.tmpl
new file mode 100644
index 000000000000..1becf27ba27e
--- /dev/null
+++ b/Documentation/DocBook/rapidio.tmpl
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+ <!ENTITY rapidio SYSTEM "rapidio.xml">
+ ]>
+
+<book id="RapidIO-Guide">
+ <bookinfo>
+ <title>RapidIO Subsystem Guide</title>
+
+ <authorgroup>
+ <author>
+ <firstname>Matt</firstname>
+ <surname>Porter</surname>
+ <affiliation>
+ <address>
+ <email>mporter@kernel.crashing.org</email>
+ <email>mporter@mvista.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <copyright>
+ <year>2005</year>
+ <holder>MontaVista Software, Inc.</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>
+ This documentation 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ MA 02111-1307 USA
+ </para>
+
+ <para>
+ For more details see the file COPYING in the source
+ distribution of Linux.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+ <chapter id="intro">
+ <title>Introduction</title>
+ <para>
+ RapidIO is a high speed switched fabric interconnect with
+ features aimed at the embedded market. RapidIO provides
+ support for memory-mapped I/O as well as message-based
+ transactions over the switched fabric network. RapidIO has
+ a standardized discovery mechanism not unlike the PCI bus
+ standard that allows simple detection of devices in a
+ network.
+ </para>
+ <para>
+ This documentation is provided for developers intending
+ to support RapidIO on new architectures, write new drivers,
+ or to understand the subsystem internals.
+ </para>
+ </chapter>
+
+ <chapter id="bugs">
+ <title>Known Bugs and Limitations</title>
+
+ <sect1>
+ <title>Bugs</title>
+ <para>None. ;)</para>
+ </sect1>
+ <sect1>
+ <title>Limitations</title>
+ <para>
+ <orderedlist>
+ <listitem><para>Access/management of RapidIO memory regions is not supported</para></listitem>
+ <listitem><para>Multiple host enumeration is not supported</para></listitem>
+ </orderedlist>
+ </para>
+ </sect1>
+ </chapter>
+
+ <chapter id="drivers">
+ <title>RapidIO driver interface</title>
+ <para>
+ Drivers are provided a set of calls in order
+ to interface with the subsystem to gather info
+ on devices, request/map memory region resources,
+ and manage mailboxes/doorbells.
+ </para>
+ <sect1>
+ <title>Functions</title>
+!Iinclude/linux/rio_drv.h
+!Edrivers/rapidio/rio-driver.c
+!Edrivers/rapidio/rio.c
+ </sect1>
+ </chapter>
+
+ <chapter id="internals">
+ <title>Internals</title>
+
+ <para>
+ This chapter contains the autogenerated documentation of the RapidIO
+ subsystem.
+ </para>
+
+ <sect1><title>Structures</title>
+!Iinclude/linux/rio.h
+ </sect1>
+ <sect1><title>Enumeration and Discovery</title>
+!Idrivers/rapidio/rio-scan.c
+ </sect1>
+ <sect1><title>Driver functionality</title>
+!Idrivers/rapidio/rio.c
+!Idrivers/rapidio/rio-access.c
+ </sect1>
+ <sect1><title>Device model support</title>
+!Idrivers/rapidio/rio-driver.c
+ </sect1>
+ <sect1><title>Sysfs support</title>
+!Idrivers/rapidio/rio-sysfs.c
+ </sect1>
+ <sect1><title>PPC32 support</title>
+!Iarch/ppc/kernel/rio.c
+!Earch/ppc/syslib/ppc85xx_rio.c
+!Iarch/ppc/syslib/ppc85xx_rio.c
+ </sect1>
+ </chapter>
+
+ <chapter id="credits">
+ <title>Credits</title>
+ <para>
+ The following people have contributed to the RapidIO
+ subsystem directly or indirectly:
+ <orderedlist>
+ <listitem><para>Matt Porter<email>mporter@kernel.crashing.org</email></para></listitem>
+ <listitem><para>Randy Vinson<email>rvinson@mvista.com</email></para></listitem>
+ <listitem><para>Dan Malek<email>dan@embeddedalley.com</email></para></listitem>
+ </orderedlist>
+ </para>
+ <para>
+ The following people have contributed to this document:
+ <orderedlist>
+ <listitem><para>Matt Porter<email>mporter@kernel.crashing.org</email></para></listitem>
+ </orderedlist>
+ </para>
+ </chapter>
+</book>
diff --git a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt
index 63edc5f847c4..3ec6c720b016 100644
--- a/Documentation/MSI-HOWTO.txt
+++ b/Documentation/MSI-HOWTO.txt
@@ -10,14 +10,22 @@
This guide describes the basics of Message Signaled Interrupts (MSI),
the advantages of using MSI over traditional interrupt mechanisms,
and how to enable your driver to use MSI or MSI-X. Also included is
-a Frequently Asked Questions.
+a Frequently Asked Questions (FAQ) section.
+
+1.1 Terminology
+
+PCI devices can be single-function or multi-function. In either case,
+when this text talks about enabling or disabling MSI on a "device
+function," it is referring to one specific PCI device and function and
+not to all functions on a PCI device (unless the PCI device has only
+one function).
2. Copyright 2003 Intel Corporation
3. What is MSI/MSI-X?
Message Signaled Interrupt (MSI), as described in the PCI Local Bus
-Specification Revision 2.3 or latest, is an optional feature, and a
+Specification Revision 2.3 or later, is an optional feature, and a
required feature for PCI Express devices. MSI enables a device function
to request service by sending an Inbound Memory Write on its PCI bus to
the FSB as a Message Signal Interrupt transaction. Because MSI is
@@ -27,7 +35,7 @@ supported.
A PCI device that supports MSI must also support pin IRQ assertion
interrupt mechanism to provide backward compatibility for systems that
-do not support MSI. In Systems, which support MSI, the bus driver is
+do not support MSI. In systems which support MSI, the bus driver is
responsible for initializing the message address and message data of
the device function's MSI/MSI-X capability structure during device
initial configuration.
@@ -61,17 +69,17 @@ over the MSI capability structure as described below.
- MSI and MSI-X both support per-vector masking. Per-vector
masking is an optional extension of MSI but a required
- feature for MSI-X. Per-vector masking provides the kernel
- the ability to mask/unmask MSI when servicing its software
- interrupt service routing handler. If per-vector masking is
+ feature for MSI-X. Per-vector masking provides the kernel the
+ ability to mask/unmask a single MSI while running its
+ interrupt service routine. If per-vector masking is
not supported, then the device driver should provide the
hardware/software synchronization to ensure that the device
generates MSI when the driver wants it to do so.
4. Why use MSI?
-As a benefit the simplification of board design, MSI allows board
-designers to remove out of band interrupt routing. MSI is another
+As a benefit to the simplification of board design, MSI allows board
+designers to remove out-of-band interrupt routing. MSI is another
step towards a legacy-free environment.
Due to increasing pressure on chipset and processor packages to
@@ -87,7 +95,7 @@ support. As a result, the PCI Express technology requires MSI
support for better interrupt performance.
Using MSI enables the device functions to support two or more
-vectors, which can be configured to target different CPU's to
+vectors, which can be configured to target different CPUs to
increase scalability.
5. Configuring a driver to use MSI/MSI-X
@@ -119,13 +127,13 @@ pci_enable_msi() explicitly.
int pci_enable_msi(struct pci_dev *dev)
-With this new API, any existing device driver, which like to have
-MSI enabled on its device function, must call this API to enable MSI
+With this new API, a device driver that wants to have MSI
+enabled on its device function must call this API to enable MSI.
A successful call will initialize the MSI capability structure
with ONE vector, regardless of whether a device function is
capable of supporting multiple messages. This vector replaces the
-pre-assigned dev->irq with a new MSI vector. To avoid the conflict
-of new assigned vector with existing pre-assigned vector requires
+pre-assigned dev->irq with a new MSI vector. To avoid a conflict
+of the new assigned vector with existing pre-assigned vector requires
a device driver to call this API before calling request_irq().
5.2.2 API pci_disable_msi
@@ -137,14 +145,14 @@ when a device driver is unloading. This API restores dev->irq with
the pre-assigned IOAPIC vector and switches a device's interrupt
mode to PCI pin-irq assertion/INTx emulation mode.
-Note that a device driver should always call free_irq() on MSI vector
-it has done request_irq() on before calling this API. Failure to do
-so results a BUG_ON() and a device will be left with MSI enabled and
+Note that a device driver should always call free_irq() on the MSI vector
+that it has done request_irq() on before calling this API. Failure to do
+so results in a BUG_ON() and a device will be left with MSI enabled and
leaks its vector.
5.2.3 MSI mode vs. legacy mode diagram
-The below diagram shows the events, which switches the interrupt
+The below diagram shows the events which switch the interrupt
mode on the MSI-capable device function between MSI mode and
PIN-IRQ assertion mode.
@@ -155,9 +163,9 @@ PIN-IRQ assertion mode.
------------ pci_disable_msi ------------------------
-Figure 1.0 MSI Mode vs. Legacy Mode
+Figure 1. MSI Mode vs. Legacy Mode
-In Figure 1.0, a device operates by default in legacy mode. Legacy
+In Figure 1, a device operates by default in legacy mode. Legacy
in this context means PCI pin-irq assertion or PCI-Express INTx
emulation. A successful MSI request (using pci_enable_msi()) switches
a device's interrupt mode to MSI mode. A pre-assigned IOAPIC vector
@@ -166,11 +174,11 @@ assigned MSI vector will replace dev->irq.
To return back to its default mode, a device driver should always call
pci_disable_msi() to undo the effect of pci_enable_msi(). Note that a
-device driver should always call free_irq() on MSI vector it has done
-request_irq() on before calling pci_disable_msi(). Failure to do so
-results a BUG_ON() and a device will be left with MSI enabled and
+device driver should always call free_irq() on the MSI vector it has
+done request_irq() on before calling pci_disable_msi(). Failure to do
+so results in a BUG_ON() and a device will be left with MSI enabled and
leaks its vector. Otherwise, the PCI subsystem restores a device's
-dev->irq with a pre-assigned IOAPIC vector and marks released
+dev->irq with a pre-assigned IOAPIC vector and marks the released
MSI vector as unused.
Once being marked as unused, there is no guarantee that the PCI
@@ -178,8 +186,8 @@ subsystem will reserve this MSI vector for a device. Depending on
the availability of current PCI vector resources and the number of
MSI/MSI-X requests from other drivers, this MSI may be re-assigned.
-For the case where the PCI subsystem re-assigned this MSI vector
-another driver, a request to switching back to MSI mode may result
+For the case where the PCI subsystem re-assigns this MSI vector to
+another driver, a request to switch back to MSI mode may result
in being assigned a different MSI vector or a failure if no more
vectors are available.
@@ -208,12 +216,12 @@ Unlike the function pci_enable_msi(), the function pci_enable_msix()
does not replace the pre-assigned IOAPIC dev->irq with a new MSI
vector because the PCI subsystem writes the 1:1 vector-to-entry mapping
into the field vector of each element contained in a second argument.
-Note that the pre-assigned IO-APIC dev->irq is valid only if the device
-operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt of
+Note that the pre-assigned IOAPIC dev->irq is valid only if the device
+operates in PIN-IRQ assertion mode. In MSI-X mode, any attempt at
using dev->irq by the device driver to request for interrupt service
may result unpredictabe behavior.
-For each MSI-X vector granted, a device driver is responsible to call
+For each MSI-X vector granted, a device driver is responsible for calling
other functions like request_irq(), enable_irq(), etc. to enable
this vector with its corresponding interrupt service handler. It is
a device driver's choice to assign all vectors with the same
@@ -224,13 +232,13 @@ service handler.
The PCI 3.0 specification has implementation notes that MMIO address
space for a device's MSI-X structure should be isolated so that the
-software system can set different page for controlling accesses to
-the MSI-X structure. The implementation of MSI patch requires the PCI
+software system can set different pages for controlling accesses to the
+MSI-X structure. The implementation of MSI support requires the PCI
subsystem, not a device driver, to maintain full control of the MSI-X
-table/MSI-X PBA and MMIO address space of the MSI-X table/MSI-X PBA.
-A device driver is prohibited from requesting the MMIO address space
-of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem will fail
-enabling MSI-X on its hardware device when it calls the function
+table/MSI-X PBA (Pending Bit Array) and MMIO address space of the MSI-X
+table/MSI-X PBA. A device driver is prohibited from requesting the MMIO
+address space of the MSI-X table/MSI-X PBA. Otherwise, the PCI subsystem
+will fail enabling MSI-X on its hardware device when it calls the function
pci_enable_msix().
5.3.2 Handling MSI-X allocation
@@ -274,9 +282,9 @@ For the case where fewer MSI-X vectors are allocated to a function
than requested, the function pci_enable_msix() will return the
maximum number of MSI-X vectors available to the caller. A device
driver may re-send its request with fewer or equal vectors indicated
-in a return. For example, if a device driver requests 5 vectors, but
-the number of available vectors is 3 vectors, a value of 3 will be a
-return as a result of pci_enable_msix() call. A function could be
+in the return. For example, if a device driver requests 5 vectors, but
+the number of available vectors is 3 vectors, a value of 3 will be
+returned as a result of pci_enable_msix() call. A function could be
designed for its driver to use only 3 MSI-X table entries as
different combinations as ABC--, A-B-C, A--CB, etc. Note that this
patch does not support multiple entries with the same vector. Such
@@ -285,49 +293,46 @@ as ABBCC, AABCC, BCCBA, etc will result as a failure by the function
pci_enable_msix(). Below are the reasons why supporting multiple
entries with the same vector is an undesirable solution.
- - The PCI subsystem can not determine which entry, which
- generated the message, to mask/unmask MSI while handling
+ - The PCI subsystem cannot determine the entry that
+ generated the message to mask/unmask MSI while handling
software driver ISR. Attempting to walk through all MSI-X
table entries (2048 max) to mask/unmask any match vector
is an undesirable solution.
- - Walk through all MSI-X table entries (2048 max) to handle
+ - Walking through all MSI-X table entries (2048 max) to handle
SMP affinity of any match vector is an undesirable solution.
5.3.4 API pci_enable_msix
-int pci_enable_msix(struct pci_dev *dev, u32 *entries, int nvec)
+int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
This API enables a device driver to request the PCI subsystem
-for enabling MSI-X messages on its hardware device. Depending on
+to enable MSI-X messages on its hardware device. Depending on
the availability of PCI vectors resources, the PCI subsystem enables
-either all or nothing.
+either all or none of the requested vectors.
-Argument dev points to the device (pci_dev) structure.
+Argument 'dev' points to the device (pci_dev) structure.
-Argument entries is a pointer of unsigned integer type. The number of
-elements is indicated in argument nvec. The content of each element
-will be mapped to the following struct defined in /driver/pci/msi.h.
+Argument 'entries' is a pointer to an array of msix_entry structs.
+The number of entries is indicated in argument 'nvec'.
+struct msix_entry is defined in /driver/pci/msi.h:
struct msix_entry {
u16 vector; /* kernel uses to write alloc vector */
u16 entry; /* driver uses to specify entry */
};
-A device driver is responsible for initializing the field entry of
-each element with unique entry supported by MSI-X table. Otherwise,
+A device driver is responsible for initializing the field 'entry' of
+each element with a unique entry supported by MSI-X table. Otherwise,
-EINVAL will be returned as a result. A successful return of zero
-indicates the PCI subsystem completes initializing each of requested
+indicates the PCI subsystem completed initializing each of the requested
entries of the MSI-X table with message address and message data.
Last but not least, the PCI subsystem will write the 1:1
-vector-to-entry mapping into the field vector of each element. A
-device driver is responsible of keeping track of allocated MSI-X
+vector-to-entry mapping into the field 'vector' of each element. A
+device driver is responsible for keeping track of allocated MSI-X
vectors in its internal data structure.
-Argument nvec is an integer indicating the number of messages
-requested.
-
-A return of zero indicates that the number of MSI-X vectors is
+A return of zero indicates that the number of MSI-X vectors was
successfully allocated. A return of greater than zero indicates
MSI-X vector shortage. Or a return of less than zero indicates
a failure. This failure may be a result of duplicate entries
@@ -341,12 +346,12 @@ void pci_disable_msix(struct pci_dev *dev)
This API should always be used to undo the effect of pci_enable_msix()
when a device driver is unloading. Note that a device driver should
always call free_irq() on all MSI-X vectors it has done request_irq()
-on before calling this API. Failure to do so results a BUG_ON() and
+on before calling this API. Failure to do so results in a BUG_ON() and
a device will be left with MSI-X enabled and leaks its vectors.
5.3.6 MSI-X mode vs. legacy mode diagram
-The below diagram shows the events, which switches the interrupt
+The below diagram shows the events which switch the interrupt
mode on the MSI-X capable device function between MSI-X mode and
PIN-IRQ assertion mode (legacy).
@@ -356,22 +361,22 @@ PIN-IRQ assertion mode (legacy).
| | ===============> | |
------------ pci_disable_msix ------------------------
-Figure 2.0 MSI-X Mode vs. Legacy Mode
+Figure 2. MSI-X Mode vs. Legacy Mode
-In Figure 2.0, a device operates by default in legacy mode. A
+In Figure 2, a device operates by default in legacy mode. A
successful MSI-X request (using pci_enable_msix()) switches a
device's interrupt mode to MSI-X mode. A pre-assigned IOAPIC vector
stored in dev->irq will be saved by the PCI subsystem; however,
unlike MSI mode, the PCI subsystem will not replace dev->irq with
assigned MSI-X vector because the PCI subsystem already writes the 1:1
-vector-to-entry mapping into the field vector of each element
+vector-to-entry mapping into the field 'vector' of each element
specified in second argument.
To return back to its default mode, a device driver should always call
pci_disable_msix() to undo the effect of pci_enable_msix(). Note that
a device driver should always call free_irq() on all MSI-X vectors it
has done request_irq() on before calling pci_disable_msix(). Failure
-to do so results a BUG_ON() and a device will be left with MSI-X
+to do so results in a BUG_ON() and a device will be left with MSI-X
enabled and leaks its vectors. Otherwise, the PCI subsystem switches a
device function's interrupt mode from MSI-X mode to legacy mode and
marks all allocated MSI-X vectors as unused.
@@ -383,53 +388,56 @@ MSI/MSI-X requests from other drivers, these MSI-X vectors may be
re-assigned.
For the case where the PCI subsystem re-assigned these MSI-X vectors
-to other driver, a request to switching back to MSI-X mode may result
+to other drivers, a request to switch back to MSI-X mode may result
being assigned with another set of MSI-X vectors or a failure if no
more vectors are available.
-5.4 Handling function implementng both MSI and MSI-X capabilities
+5.4 Handling function implementing both MSI and MSI-X capabilities
For the case where a function implements both MSI and MSI-X
capabilities, the PCI subsystem enables a device to run either in MSI
mode or MSI-X mode but not both. A device driver determines whether it
wants MSI or MSI-X enabled on its hardware device. Once a device
-driver requests for MSI, for example, it is prohibited to request for
+driver requests for MSI, for example, it is prohibited from requesting
MSI-X; in other words, a device driver is not permitted to ping-pong
between MSI mod MSI-X mode during a run-time.
5.5 Hardware requirements for MSI/MSI-X support
+
MSI/MSI-X support requires support from both system hardware and
individual hardware device functions.
5.5.1 System hardware support
+
Since the target of MSI address is the local APIC CPU, enabling
-MSI/MSI-X support in Linux kernel is dependent on whether existing
-system hardware supports local APIC. Users should verify their
-system whether it runs when CONFIG_X86_LOCAL_APIC=y.
+MSI/MSI-X support in the Linux kernel is dependent on whether existing
+system hardware supports local APIC. Users should verify that their
+system supports local APIC operation by testing that it runs when
+CONFIG_X86_LOCAL_APIC=y.
In SMP environment, CONFIG_X86_LOCAL_APIC is automatically set;
however, in UP environment, users must manually set
CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting
-CONFIG_PCI_MSI enables the VECTOR based scheme and
-the option for MSI-capable device drivers to selectively enable
-MSI/MSI-X.
+CONFIG_PCI_MSI enables the VECTOR based scheme and the option for
+MSI-capable device drivers to selectively enable MSI/MSI-X.
Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI/MSI-X
vector is allocated new during runtime and MSI/MSI-X support does not
depend on BIOS support. This key independency enables MSI/MSI-X
-support on future IOxAPIC free platform.
+support on future IOxAPIC free platforms.
5.5.2 Device hardware support
+
The hardware device function supports MSI by indicating the
MSI/MSI-X capability structure on its PCI capability list. By
default, this capability structure will not be initialized by
the kernel to enable MSI during the system boot. In other words,
the device function is running on its default pin assertion mode.
Note that in many cases the hardware supporting MSI have bugs,
-which may result in system hang. The software driver of specific
-MSI-capable hardware is responsible for whether calling
+which may result in system hangs. The software driver of specific
+MSI-capable hardware is responsible for deciding whether to call
pci_enable_msi or not. A return of zero indicates the kernel
-successfully initializes the MSI/MSI-X capability structure of the
+successfully initialized the MSI/MSI-X capability structure of the
device function. The device function is now running on MSI/MSI-X mode.
5.6 How to tell whether MSI/MSI-X is enabled on device function
@@ -439,10 +447,10 @@ pci_enable_msi()/pci_enable_msix() indicates to a device driver that
its device function is initialized successfully and ready to run in
MSI/MSI-X mode.
-At the user level, users can use command 'cat /proc/interrupts'
-to display the vector allocated for a device and its interrupt
-MSI/MSI-X mode ("PCI MSI"/"PCI MSIX"). Below shows below MSI mode is
-enabled on a SCSI Adaptec 39320D Ultra320.
+At the user level, users can use the command 'cat /proc/interrupts'
+to display the vectors allocated for devices and their interrupt
+MSI/MSI-X modes ("PCI-MSI"/"PCI-MSI-X"). Below shows MSI mode is
+enabled on a SCSI Adaptec 39320D Ultra320 controller.
CPU0 CPU1
0: 324639 0 IO-APIC-edge timer
@@ -453,8 +461,8 @@ enabled on a SCSI Adaptec 39320D Ultra320.
15: 1 0 IO-APIC-edge ide1
169: 0 0 IO-APIC-level uhci-hcd
185: 0 0 IO-APIC-level uhci-hcd
-193: 138 10 PCI MSI aic79xx
-201: 30 0 PCI MSI aic79xx
+193: 138 10 PCI-MSI aic79xx
+201: 30 0 PCI-MSI aic79xx
225: 30 0 IO-APIC-level aic7xxx
233: 30 0 IO-APIC-level aic7xxx
NMI: 0 0
@@ -490,8 +498,8 @@ target address set as 0xfeexxxxx, as conformed to PCI
specification 2.3 or latest, then it should work.
Q4. From the driver point of view, if the MSI is lost because
-of the errors occur during inbound memory write, then it may
-wait for ever. Is there a mechanism for it to recover?
+of errors occurring during inbound memory write, then it may
+wait forever. Is there a mechanism for it to recover?
A4. Since the target of the transaction is an inbound memory
write, all transaction termination conditions (Retry,
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 354d89c78377..15da16861fa3 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -772,8 +772,6 @@ RCU pointer/list traversal:
list_for_each_entry_rcu
list_for_each_continue_rcu (to be deprecated in favor of new
list_for_each_entry_continue_rcu)
- hlist_for_each_rcu (to be deprecated in favor of
- hlist_for_each_entry_rcu)
hlist_for_each_entry_rcu
RCU pointer update:
diff --git a/Documentation/device-mapper/snapshot.txt b/Documentation/device-mapper/snapshot.txt
index dca274ff4005..a5009c8300f3 100644
--- a/Documentation/device-mapper/snapshot.txt
+++ b/Documentation/device-mapper/snapshot.txt
@@ -19,7 +19,6 @@ There are two dm targets available: snapshot and snapshot-origin.
*) snapshot-origin <origin>
which will normally have one or more snapshots based on it.
-You must create the snapshot-origin device before you can create snapshots.
Reads will be mapped directly to the backing device. For each write, the
original data will be saved in the <COW device> of each snapshot to keep
its visible content unchanged, at least until the <COW device> fills up.
@@ -27,7 +26,7 @@ its visible content unchanged, at least until the <COW device> fills up.
*) snapshot <origin> <COW device> <persistent?> <chunksize>
-A snapshot is created of the <origin> block device. Changed chunks of
+A snapshot of the <origin> block device is created. Changed chunks of
<chunksize> sectors will be stored on the <COW device>. Writes will
only go to the <COW device>. Reads will come from the <COW device> or
from <origin> for unchanged data. <COW device> will often be
@@ -37,6 +36,8 @@ the amount of free space and expand the <COW device> before it fills up.
<persistent?> is P (Persistent) or N (Not persistent - will not survive
after reboot).
+The difference is that for transient snapshots less metadata must be
+saved on disk - they can be kept in memory by the kernel.
How this is used by LVM2
diff --git a/Documentation/fb/vesafb.txt b/Documentation/fb/vesafb.txt
index 62db6758d1c1..ee277dd204b0 100644
--- a/Documentation/fb/vesafb.txt
+++ b/Documentation/fb/vesafb.txt
@@ -146,10 +146,10 @@ pmipal Use the protected mode interface for palette changes.
mtrr:n setup memory type range registers for the vesafb framebuffer
where n:
- 0 - disabled (equivalent to nomtrr)
+ 0 - disabled (equivalent to nomtrr) (default)
1 - uncachable
2 - write-back
- 3 - write-combining (default)
+ 3 - write-combining
4 - write-through
If you see the following in dmesg, choose the type that matches the
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index b67189a8d8d4..decdf9917e0d 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -69,6 +69,22 @@ Who: Grant Coady <gcoady@gmail.com>
---------------------------
+What: remove EXPORT_SYMBOL(panic_timeout)
+When: April 2006
+Files: kernel/panic.c
+Why: No modular usage in the kernel.
+Who: Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
+What: remove EXPORT_SYMBOL(insert_resource)
+When: April 2006
+Files: kernel/resource.c
+Why: No modular usage in the kernel.
+Who: Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
When: November 2005
Files: drivers/pcmcia/: pcmcia_ioctl.c
diff --git a/Documentation/filesystems/dentry-locking.txt b/Documentation/filesystems/dentry-locking.txt
new file mode 100644
index 000000000000..4c0c575a4012
--- /dev/null
+++ b/Documentation/filesystems/dentry-locking.txt
@@ -0,0 +1,173 @@
+RCU-based dcache locking model
+==============================
+
+On many workloads, the most common operation on dcache is to look up a
+dentry, given a parent dentry and the name of the child. Typically,
+for every open(), stat() etc., the dentry corresponding to the
+pathname will be looked up by walking the tree starting with the first
+component of the pathname and using that dentry along with the next
+component to look up the next level and so on. Since it is a frequent
+operation for workloads like multiuser environments and web servers,
+it is important to optimize this path.
+
+Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus in
+every component during path look-up. Since 2.5.10 onwards, fast-walk
+algorithm changed this by holding the dcache_lock at the beginning and
+walking as many cached path component dentries as possible. This
+significantly decreases the number of acquisition of
+dcache_lock. However it also increases the lock hold time
+significantly and affects performance in large SMP machines. Since
+2.5.62 kernel, dcache has been using a new locking model that uses RCU
+to make dcache look-up lock-free.
+
+The current dcache locking model is not very different from the
+existing dcache locking model. Prior to 2.5.62 kernel, dcache_lock
+protected the hash chain, d_child, d_alias, d_lru lists as well as
+d_inode and several other things like mount look-up. RCU-based changes
+affect only the way the hash chain is protected. For everything else
+the dcache_lock must be taken for both traversing as well as
+updating. The hash chain updates too take the dcache_lock. The
+significant change is the way d_lookup traverses the hash chain, it
+doesn't acquire the dcache_lock for this and rely on RCU to ensure
+that the dentry has not been *freed*.
+
+
+Dcache locking details
+======================
+
+For many multi-user workloads, open() and stat() on files are very
+frequently occurring operations. Both involve walking of path names to
+find the dentry corresponding to the concerned file. In 2.4 kernel,
+dcache_lock was held during look-up of each path component. Contention
+and cache-line bouncing of this global lock caused significant
+scalability problems. With the introduction of RCU in Linux kernel,
+this was worked around by making the look-up of path components during
+path walking lock-free.
+
+
+Safe lock-free look-up of dcache hash table
+===========================================
+
+Dcache is a complex data structure with the hash table entries also
+linked together in other lists. In 2.4 kernel, dcache_lock protected
+all the lists. We applied RCU only on hash chain walking. The rest of
+the lists are still protected by dcache_lock. Some of the important
+changes are :
+
+1. The deletion from hash chain is done using hlist_del_rcu() macro
+ which doesn't initialize next pointer of the deleted dentry and
+ this allows us to walk safely lock-free while a deletion is
+ happening.
+
+2. Insertion of a dentry into the hash table is done using
+ hlist_add_head_rcu() which take care of ordering the writes - the
+ writes to the dentry must be visible before the dentry is
+ inserted. This works in conjunction with hlist_for_each_rcu() while
+ walking the hash chain. The only requirement is that all
+ initialization to the dentry must be done before
+ hlist_add_head_rcu() since we don't have dcache_lock protection
+ while traversing the hash chain. This isn't different from the
+ existing code.
+
+3. The dentry looked up without holding dcache_lock by cannot be
+ returned for walking if it is unhashed. It then may have a NULL
+ d_inode or other bogosity since RCU doesn't protect the other
+ fields in the dentry. We therefore use a flag DCACHE_UNHASHED to
+ indicate unhashed dentries and use this in conjunction with a
+ per-dentry lock (d_lock). Once looked up without the dcache_lock,
+ we acquire the per-dentry lock (d_lock) and check if the dentry is
+ unhashed. If so, the look-up is failed. If not, the reference count
+ of the dentry is increased and the dentry is returned.
+
+4. Once a dentry is looked up, it must be ensured during the path walk
+ for that component it doesn't go away. In pre-2.5.10 code, this was
+ done holding a reference to the dentry. dcache_rcu does the same.
+ In some sense, dcache_rcu path walking looks like the pre-2.5.10
+ version.
+
+5. All dentry hash chain updates must take the dcache_lock as well as
+ the per-dentry lock in that order. dput() does this to ensure that
+ a dentry that has just been looked up in another CPU doesn't get
+ deleted before dget() can be done on it.
+
+6. There are several ways to do reference counting of RCU protected
+ objects. One such example is in ipv4 route cache where deferred
+ freeing (using call_rcu()) is done as soon as the reference count
+ goes to zero. This cannot be done in the case of dentries because
+ tearing down of dentries require blocking (dentry_iput()) which
+ isn't supported from RCU callbacks. Instead, tearing down of
+ dentries happen synchronously in dput(), but actual freeing happens
+ later when RCU grace period is over. This allows safe lock-free
+ walking of the hash chains, but a matched dentry may have been
+ partially torn down. The checking of DCACHE_UNHASHED flag with
+ d_lock held detects such dentries and prevents them from being
+ returned from look-up.
+
+
+Maintaining POSIX rename semantics
+==================================
+
+Since look-up of dentries is lock-free, it can race against a
+concurrent rename operation. For example, during rename of file A to
+B, look-up of either A or B must succeed. So, if look-up of B happens
+after A has been removed from the hash chain but not added to the new
+hash chain, it may fail. Also, a comparison while the name is being
+written concurrently by a rename may result in false positive matches
+violating rename semantics. Issues related to race with rename are
+handled as described below :
+
+1. Look-up can be done in two ways - d_lookup() which is safe from
+ simultaneous renames and __d_lookup() which is not. If
+ __d_lookup() fails, it must be followed up by a d_lookup() to
+ correctly determine whether a dentry is in the hash table or
+ not. d_lookup() protects look-ups using a sequence lock
+ (rename_lock).
+
+2. The name associated with a dentry (d_name) may be changed if a
+ rename is allowed to happen simultaneously. To avoid memcmp() in
+ __d_lookup() go out of bounds due to a rename and false positive
+ comparison, the name comparison is done while holding the
+ per-dentry lock. This prevents concurrent renames during this
+ operation.
+
+3. Hash table walking during look-up may move to a different bucket as
+ the current dentry is moved to a different bucket due to rename.
+ But we use hlists in dcache hash table and they are
+ null-terminated. So, even if a dentry moves to a different bucket,
+ hash chain walk will terminate. [with a list_head list, it may not
+ since termination is when the list_head in the original bucket is
+ reached]. Since we redo the d_parent check and compare name while
+ holding d_lock, lock-free look-up will not race against d_move().
+
+4. There can be a theoretical race when a dentry keeps coming back to
+ original bucket due to double moves. Due to this look-up may
+ consider that it has never moved and can end up in a infinite loop.
+ But this is not any worse that theoretical livelocks we already
+ have in the kernel.
+
+
+Important guidelines for filesystem developers related to dcache_rcu
+====================================================================
+
+1. Existing dcache interfaces (pre-2.5.62) exported to filesystem
+ don't change. Only dcache internal implementation changes. However
+ filesystems *must not* delete from the dentry hash chains directly
+ using the list macros like allowed earlier. They must use dcache
+ APIs like d_drop() or __d_drop() depending on the situation.
+
+2. d_flags is now protected by a per-dentry lock (d_lock). All access
+ to d_flags must be protected by it.
+
+3. For a hashed dentry, checking of d_count needs to be protected by
+ d_lock.
+
+
+Papers and other documentation on dcache locking
+================================================
+
+1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124).
+
+2. http://lse.sourceforge.net/locking/dcache/dcache.html
+
+
+
diff --git a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README
index 54366ecc241f..aabfba24bc2e 100644
--- a/Documentation/filesystems/devfs/README
+++ b/Documentation/filesystems/devfs/README
@@ -1812,11 +1812,6 @@ it may overflow the messages buffer, but try to get as much of it as
you can
-if you get an Oops, run ksymoops to decode it so that the
-names of the offending functions are provided. A non-decoded Oops is
-pretty useless
-
-
send a copy of your devfsd configuration file(s)
send the bug report to me first.
diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
new file mode 100644
index 000000000000..b3404a032596
--- /dev/null
+++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
@@ -0,0 +1,195 @@
+ramfs, rootfs and initramfs
+October 17, 2005
+Rob Landley <rob@landley.net>
+=============================
+
+What is ramfs?
+--------------
+
+Ramfs is a very simple filesystem that exports Linux's disk caching
+mechanisms (the page cache and dentry cache) as a dynamically resizable
+ram-based filesystem.
+
+Normally all files are cached in memory by Linux. Pages of data read from
+backing store (usually the block device the filesystem is mounted on) are kept
+around in case it's needed again, but marked as clean (freeable) in case the
+Virtual Memory system needs the memory for something else. Similarly, data
+written to files is marked clean as soon as it has been written to backing
+store, but kept around for caching purposes until the VM reallocates the
+memory. A similar mechanism (the dentry cache) greatly speeds up access to
+directories.
+
+With ramfs, there is no backing store. Files written into ramfs allocate
+dentries and page cache as usual, but there's nowhere to write them to.
+This means the pages are never marked clean, so they can't be freed by the
+VM when it's looking to recycle memory.
+
+The amount of code required to implement ramfs is tiny, because all the
+work is done by the existing Linux caching infrastructure. Basically,
+you're mounting the disk cache as a filesystem. Because of this, ramfs is not
+an optional component removable via menuconfig, since there would be negligible
+space savings.
+
+ramfs and ramdisk:
+------------------
+
+The older "ram disk" mechanism created a synthetic block device out of
+an area of ram and used it as backing store for a filesystem. This block
+device was of fixed size, so the filesystem mounted on it was of fixed
+size. Using a ram disk also required unnecessarily copying memory from the
+fake block device into the page cache (and copying changes back out), as well
+as creating and destroying dentries. Plus it needed a filesystem driver
+(such as ext2) to format and interpret this data.
+
+Compared to ramfs, this wastes memory (and memory bus bandwidth), creates
+unnecessary work for the CPU, and pollutes the CPU caches. (There are tricks
+to avoid this copying by playing with the page tables, but they're unpleasantly
+complicated and turn out to be about as expensive as the copying anyway.)
+More to the point, all the work ramfs is doing has to happen _anyway_,
+since all file access goes through the page and dentry caches. The ram
+disk is simply unnecessary, ramfs is internally much simpler.
+
+Another reason ramdisks are semi-obsolete is that the introduction of
+loopback devices offered a more flexible and convenient way to create
+synthetic block devices, now from files instead of from chunks of memory.
+See losetup (8) for details.
+
+ramfs and tmpfs:
+----------------
+
+One downside of ramfs is you can keep writing data into it until you fill
+up all memory, and the VM can't free it because the VM thinks that files
+should get written to backing store (rather than swap space), but ramfs hasn't
+got any backing store. Because of this, only root (or a trusted user) should
+be allowed write access to a ramfs mount.
+
+A ramfs derivative called tmpfs was created to add size limits, and the ability
+to write the data to swap space. Normal users can be allowed write access to
+tmpfs mounts. See Documentation/filesystems/tmpfs.txt for more information.
+
+What is rootfs?
+---------------
+
+Rootfs is a special instance of ramfs, which is always present in 2.6 systems.
+(It's used internally as the starting and stopping point for searches of the
+kernel's doubly-linked list of mount points.)
+
+Most systems just mount another filesystem over it and ignore it. The
+amount of space an empty instance of ramfs takes up is tiny.
+
+What is initramfs?
+------------------
+
+All 2.6 Linux kernels contain a gzipped "cpio" format archive, which is
+extracted into rootfs when the kernel boots up. After extracting, the kernel
+checks to see if rootfs contains a file "init", and if so it executes it as PID
+1. If found, this init process is responsible for bringing the system the
+rest of the way up, including locating and mounting the real root device (if
+any). If rootfs does not contain an init program after the embedded cpio
+archive is extracted into it, the kernel will fall through to the older code
+to locate and mount a root partition, then exec some variant of /sbin/init
+out of that.
+
+All this differs from the old initrd in several ways:
+
+ - The old initrd was a separate file, while the initramfs archive is linked
+ into the linux kernel image. (The directory linux-*/usr is devoted to
+ generating this archive during the build.)
+
+ - The old initrd file was a gzipped filesystem image (in some file format,
+ such as ext2, that had to be built into the kernel), while the new
+ initramfs archive is a gzipped cpio archive (like tar only simpler,
+ see cpio(1) and Documentation/early-userspace/buffer-format.txt).
+
+ - The program run by the old initrd (which was called /initrd, not /init) did
+ some setup and then returned to the kernel, while the init program from
+ initramfs is not expected to return to the kernel. (If /init needs to hand
+ off control it can overmount / with a new root device and exec another init
+ program. See the switch_root utility, below.)
+
+ - When switching another root device, initrd would pivot_root and then
+ umount the ramdisk. But initramfs is rootfs: you can neither pivot_root
+ rootfs, nor unmount it. Instead delete everything out of rootfs to
+ free up the space (find -xdev / -exec rm '{}' ';'), overmount rootfs
+ with the new root (cd /newmount; mount --move . /; chroot .), attach
+ stdin/stdout/stderr to the new /dev/console, and exec the new init.
+
+ Since this is a remarkably persnickity process (and involves deleting
+ commands before you can run them), the klibc package introduced a helper
+ program (utils/run_init.c) to do all this for you. Most other packages
+ (such as busybox) have named this command "switch_root".
+
+Populating initramfs:
+---------------------
+
+The 2.6 kernel build process always creates a gzipped cpio format initramfs
+archive and links it into the resulting kernel binary. By default, this
+archive is empty (consuming 134 bytes on x86). The config option
+CONFIG_INITRAMFS_SOURCE (for some reason buried under devices->block devices
+in menuconfig, and living in usr/Kconfig) can be used to specify a source for
+the initramfs archive, which will automatically be incorporated into the
+resulting binary. This option can point to an existing gzipped cpio archive, a
+directory containing files to be archived, or a text file specification such
+as the following example:
+
+ dir /dev 755 0 0
+ nod /dev/console 644 0 0 c 5 1
+ nod /dev/loop0 644 0 0 b 7 0
+ dir /bin 755 1000 1000
+ slink /bin/sh busybox 777 0 0
+ file /bin/busybox initramfs/busybox 755 0 0
+ dir /proc 755 0 0
+ dir /sys 755 0 0
+ dir /mnt 755 0 0
+ file /init initramfs/init.sh 755 0 0
+
+One advantage of the text file is that root access is not required to
+set permissions or create device nodes in the new archive. (Note that those
+two example "file" entries expect to find files named "init.sh" and "busybox" in
+a directory called "initramfs", under the linux-2.6.* directory. See
+Documentation/early-userspace/README for more details.)
+
+If you don't already understand what shared libraries, devices, and paths
+you need to get a minimal root filesystem up and running, here are some
+references:
+http://www.tldp.org/HOWTO/Bootdisk-HOWTO/
+http://www.tldp.org/HOWTO/From-PowerUp-To-Bash-Prompt-HOWTO.html
+http://www.linuxfromscratch.org/lfs/view/stable/
+
+The "klibc" package (http://www.kernel.org/pub/linux/libs/klibc) is
+designed to be a tiny C library to statically link early userspace
+code against, along with some related utilities. It is BSD licensed.
+
+I use uClibc (http://www.uclibc.org) and busybox (http://www.busybox.net)
+myself. These are LGPL and GPL, respectively.
+
+In theory you could use glibc, but that's not well suited for small embedded
+uses like this. (A "hello world" program statically linked against glibc is
+over 400k. With uClibc it's 7k. Also note that glibc dlopens libnss to do
+name lookups, even when otherwise statically linked.)
+
+Future directions:
+------------------
+
+Today (2.6.14), initramfs is always compiled in, but not always used. The
+kernel falls back to legacy boot code that is reached only if initramfs does
+not contain an /init program. The fallback is legacy code, there to ensure a
+smooth transition and allowing early boot functionality to gradually move to
+"early userspace" (I.E. initramfs).
+
+The move to early userspace is necessary because finding and mounting the real
+root device is complex. Root partitions can span multiple devices (raid or
+separate journal). They can be out on the network (requiring dhcp, setting a
+specific mac address, logging into a server, etc). They can live on removable
+media, with dynamically allocated major/minor numbers and persistent naming
+issues requiring a full udev implementation to sort out. They can be
+compressed, encrypted, copy-on-write, loopback mounted, strangely partitioned,
+and so on.
+
+This kind of complexity (which inevitably includes policy) is rightly handled
+in userspace. Both klibc and busybox/uClibc are working on simple initramfs
+packages to drop into a kernel build, and when standard solutions are ready
+and widely deployed, the kernel's legacy early boot code will become obsolete
+and a candidate for the feature removal schedule.
+
+But that's a while off yet.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index f042c12e0ed2..ee4c0a8b8db7 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -3,7 +3,7 @@
Original author: Richard Gooch <rgooch@atnf.csiro.au>
- Last updated on August 25, 2005
+ Last updated on October 28, 2005
Copyright (C) 1999 Richard Gooch
Copyright (C) 2005 Pekka Enberg
@@ -11,62 +11,61 @@
This file is released under the GPLv2.
-What is it?
-===========
+Introduction
+============
-The Virtual File System (otherwise known as the Virtual Filesystem
-Switch) is the software layer in the kernel that provides the
-filesystem interface to userspace programs. It also provides an
-abstraction within the kernel which allows different filesystem
-implementations to coexist.
+The Virtual File System (also known as the Virtual Filesystem Switch)
+is the software layer in the kernel that provides the filesystem
+interface to userspace programs. It also provides an abstraction
+within the kernel which allows different filesystem implementations to
+coexist.
+VFS system calls open(2), stat(2), read(2), write(2), chmod(2) and so
+on are called from a process context. Filesystem locking is described
+in the document Documentation/filesystems/Locking.
-A Quick Look At How It Works
-============================
-In this section I'll briefly describe how things work, before
-launching into the details. I'll start with describing what happens
-when user programs open and manipulate files, and then look from the
-other view which is how a filesystem is supported and subsequently
-mounted.
-
-
-Opening a File
---------------
-
-The VFS implements the open(2), stat(2), chmod(2) and similar system
-calls. The pathname argument is used by the VFS to search through the
-directory entry cache (dentry cache or "dcache"). This provides a very
-fast look-up mechanism to translate a pathname (filename) into a
-specific dentry.
-
-An individual dentry usually has a pointer to an inode. Inodes are the
-things that live on disc drives, and can be regular files (you know:
-those things that you write data into), directories, FIFOs and other
-beasts. Dentries live in RAM and are never saved to disc: they exist
-only for performance. Inodes live on disc and are copied into memory
-when required. Later any changes are written back to disc. The inode
-that lives in RAM is a VFS inode, and it is this which the dentry
-points to. A single inode can be pointed to by multiple dentries
-(think about hardlinks).
-
-The dcache is meant to be a view into your entire filespace. Unlike
-Linus, most of us losers can't fit enough dentries into RAM to cover
-all of our filespace, so the dcache has bits missing. In order to
-resolve your pathname into a dentry, the VFS may have to resort to
-creating dentries along the way, and then loading the inode. This is
-done by looking up the inode.
-
-To look up an inode (usually read from disc) requires that the VFS
-calls the lookup() method of the parent directory inode. This method
-is installed by the specific filesystem implementation that the inode
-lives in. There will be more on this later.
+Directory Entry Cache (dcache)
+------------------------------
-Once the VFS has the required dentry (and hence the inode), we can do
-all those boring things like open(2) the file, or stat(2) it to peek
-at the inode data. The stat(2) operation is fairly simple: once the
-VFS has the dentry, it peeks at the inode data and passes some of it
-back to userspace.
+The VFS implements the open(2), stat(2), chmod(2), and similar system
+calls. The pathname argument that is passed to them is used by the VFS
+to search through the directory entry cache (also known as the dentry
+cache or dcache). This provides a very fast look-up mechanism to
+translate a pathname (filename) into a specific dentry. Dentries live
+in RAM and are never saved to disc: they exist only for performance.
+
+The dentry cache is meant to be a view into your entire filespace. As
+most computers cannot fit all dentries in the RAM at the same time,
+some bits of the cache are missing. In order to resolve your pathname
+into a dentry, the VFS may have to resort to creating dentries along
+the way, and then loading the inode. This is done by looking up the
+inode.
+
+
+The Inode Object
+----------------
+
+An individual dentry usually has a pointer to an inode. Inodes are
+filesystem objects such as regular files, directories, FIFOs and other
+beasts. They live either on the disc (for block device filesystems)
+or in the memory (for pseudo filesystems). Inodes that live on the
+disc are copied into the memory when required and changes to the inode
+are written back to disc. A single inode can be pointed to by multiple
+dentries (hard links, for example, do this).
+
+To look up an inode requires that the VFS calls the lookup() method of
+the parent directory inode. This method is installed by the specific
+filesystem implementation that the inode lives in. Once the VFS has
+the required dentry (and hence the inode), we can do all those boring
+things like open(2) the file, or stat(2) it to peek at the inode
+data. The stat(2) operation is fairly simple: once the VFS has the
+dentry, it peeks at the inode data and passes some of it back to
+userspace.
+
+
+The File Object
+---------------
Opening a file requires another operation: allocation of a file
structure (this is the kernel-side implementation of file
@@ -74,51 +73,39 @@ descriptors). The freshly allocated file structure is initialized with
a pointer to the dentry and a set of file operation member functions.
These are taken from the inode data. The open() file method is then
called so the specific filesystem implementation can do it's work. You
-can see that this is another switch performed by the VFS.
-
-The file structure is placed into the file descriptor table for the
-process.
+can see that this is another switch performed by the VFS. The file
+structure is placed into the file descriptor table for the process.
Reading, writing and closing files (and other assorted VFS operations)
is done by using the userspace file descriptor to grab the appropriate
-file structure, and then calling the required file structure method
-function to do whatever is required.
-
-For as long as the file is open, it keeps the dentry "open" (in use),
-which in turn means that the VFS inode is still in use.
-
-All VFS system calls (i.e. open(2), stat(2), read(2), write(2),
-chmod(2) and so on) are called from a process context. You should
-assume that these calls are made without any kernel locks being
-held. This means that the processes may be executing the same piece of
-filesystem or driver code at the same time, on different
-processors. You should ensure that access to shared resources is
-protected by appropriate locks.
+file structure, and then calling the required file structure method to
+do whatever is required. For as long as the file is open, it keeps the
+dentry in use, which in turn means that the VFS inode is still in use.
Registering and Mounting a Filesystem
--------------------------------------
+=====================================
-If you want to support a new kind of filesystem in the kernel, all you
-need to do is call register_filesystem(). You pass a structure
-describing the filesystem implementation (struct file_system_type)
-which is then added to an internal table of supported filesystems. You
-can do:
+To register and unregister a filesystem, use the following API
+functions:
-% cat /proc/filesystems
+ #include <linux/fs.h>
-to see what filesystems are currently available on your system.
+ extern int register_filesystem(struct file_system_type *);
+ extern int unregister_filesystem(struct file_system_type *);
-When a request is made to mount a block device onto a directory in
-your filespace the VFS will call the appropriate method for the
-specific filesystem. The dentry for the mount point will then be
-updated to point to the root inode for the new filesystem.
+The passed struct file_system_type describes your filesystem. When a
+request is made to mount a device onto a directory in your filespace,
+the VFS will call the appropriate get_sb() method for the specific
+filesystem. The dentry for the mount point will then be updated to
+point to the root inode for the new filesystem.
-It's now time to look at things in more detail.
+You can see all filesystems that are registered to the kernel in the
+file /proc/filesystems.
struct file_system_type
-=======================
+-----------------------
This describes the filesystem. As of kernel 2.6.13, the following
members are defined:
@@ -197,8 +184,14 @@ A fill_super() method implementation has the following arguments:
int silent: whether or not to be silent on error
+The Superblock Object
+=====================
+
+A superblock object represents a mounted filesystem.
+
+
struct super_operations
-=======================
+-----------------------
This describes how the VFS can manipulate the superblock of your
filesystem. As of kernel 2.6.13, the following members are defined:
@@ -286,9 +279,9 @@ or bottom half).
a superblock. The second parameter indicates whether the method
should wait until the write out has been completed. Optional.
- write_super_lockfs: called when VFS is locking a filesystem and forcing
- it into a consistent state. This function is currently used by the
- Logical Volume Manager (LVM).
+ write_super_lockfs: called when VFS is locking a filesystem and
+ forcing it into a consistent state. This method is currently
+ used by the Logical Volume Manager (LVM).
unlockfs: called when VFS is unlocking a filesystem and making it writable
again.
@@ -317,8 +310,14 @@ field. This is a pointer to a "struct inode_operations" which
describes the methods that can be performed on individual inodes.
+The Inode Object
+================
+
+An inode object represents an object within the filesystem.
+
+
struct inode_operations
-=======================
+-----------------------
This describes how the VFS can manipulate an inode in your
filesystem. As of kernel 2.6.13, the following members are defined:
@@ -394,51 +393,62 @@ otherwise noted.
will probably need to call d_instantiate() just as you would
in the create() method
+ rename: called by the rename(2) system call to rename the object to
+ have the parent and name given by the second inode and dentry.
+
readlink: called by the readlink(2) system call. Only required if
you want to support reading symbolic links
follow_link: called by the VFS to follow a symbolic link to the
inode it points to. Only required if you want to support
- symbolic links. This function returns a void pointer cookie
+ symbolic links. This method returns a void pointer cookie
that is passed to put_link().
put_link: called by the VFS to release resources allocated by
- follow_link(). The cookie returned by follow_link() is passed to
- to this function as the last parameter. It is used by filesystems
- such as NFS where page cache is not stable (i.e. page that was
- installed when the symbolic link walk started might not be in the
- page cache at the end of the walk).
-
- truncate: called by the VFS to change the size of a file. The i_size
- field of the inode is set to the desired size by the VFS before
- this function is called. This function is called by the truncate(2)
- system call and related functionality.
+ follow_link(). The cookie returned by follow_link() is passed
+ to to this method as the last parameter. It is used by
+ filesystems such as NFS where page cache is not stable
+ (i.e. page that was installed when the symbolic link walk
+ started might not be in the page cache at the end of the
+ walk).
+
+ truncate: called by the VFS to change the size of a file. The
+ i_size field of the inode is set to the desired size by the
+ VFS before this method is called. This method is called by
+ the truncate(2) system call and related functionality.
permission: called by the VFS to check for access rights on a POSIX-like
filesystem.
- setattr: called by the VFS to set attributes for a file. This function is
- called by chmod(2) and related system calls.
+ setattr: called by the VFS to set attributes for a file. This method
+ is called by chmod(2) and related system calls.
- getattr: called by the VFS to get attributes of a file. This function is
- called by stat(2) and related system calls.
+ getattr: called by the VFS to get attributes of a file. This method
+ is called by stat(2) and related system calls.
setxattr: called by the VFS to set an extended attribute for a file.
- Extended attribute is a name:value pair associated with an inode. This
- function is called by setxattr(2) system call.
+ Extended attribute is a name:value pair associated with an
+ inode. This method is called by setxattr(2) system call.
+
+ getxattr: called by the VFS to retrieve the value of an extended
+ attribute name. This method is called by getxattr(2) function
+ call.
- getxattr: called by the VFS to retrieve the value of an extended attribute
- name. This function is called by getxattr(2) function call.
+ listxattr: called by the VFS to list all extended attributes for a
+ given file. This method is called by listxattr(2) system call.
- listxattr: called by the VFS to list all extended attributes for a given
- file. This function is called by listxattr(2) system call.
+ removexattr: called by the VFS to remove an extended attribute from
+ a file. This method is called by removexattr(2) system call.
- removexattr: called by the VFS to remove an extended attribute from a file.
- This function is called by removexattr(2) system call.
+
+The Address Space Object
+========================
+
+The address space object is used to identify pages in the page cache.
struct address_space_operations
-===============================
+-------------------------------
This describes how the VFS can manipulate mapping of a file to page cache in
your filesystem. As of kernel 2.6.13, the following members are defined:
@@ -502,8 +512,14 @@ struct address_space_operations {
it. An example implementation can be found in fs/ext2/xip.c.
+The File Object
+===============
+
+A file object represents a file opened by a process.
+
+
struct file_operations
-======================
+----------------------
This describes how the VFS can manipulate an open file. As of kernel
2.6.13, the following members are defined:
@@ -661,7 +677,7 @@ of child dentries. Child dentries are basically like files in a
directory.
-Directory Entry Cache APIs
+Directory Entry Cache API
--------------------------
There are a number of functions defined which permit a filesystem to
@@ -705,178 +721,24 @@ manipulate dentries:
and the dentry is returned. The caller must use d_put()
to free the dentry when it finishes using it.
+For further information on dentry locking, please refer to the document
+Documentation/filesystems/dentry-locking.txt.
-RCU-based dcache locking model
-------------------------------
-On many workloads, the most common operation on dcache is
-to look up a dentry, given a parent dentry and the name
-of the child. Typically, for every open(), stat() etc.,
-the dentry corresponding to the pathname will be looked
-up by walking the tree starting with the first component
-of the pathname and using that dentry along with the next
-component to look up the next level and so on. Since it
-is a frequent operation for workloads like multiuser
-environments and web servers, it is important to optimize
-this path.
-
-Prior to 2.5.10, dcache_lock was acquired in d_lookup and thus
-in every component during path look-up. Since 2.5.10 onwards,
-fast-walk algorithm changed this by holding the dcache_lock
-at the beginning and walking as many cached path component
-dentries as possible. This significantly decreases the number
-of acquisition of dcache_lock. However it also increases the
-lock hold time significantly and affects performance in large
-SMP machines. Since 2.5.62 kernel, dcache has been using
-a new locking model that uses RCU to make dcache look-up
-lock-free.
-
-The current dcache locking model is not very different from the existing
-dcache locking model. Prior to 2.5.62 kernel, dcache_lock
-protected the hash chain, d_child, d_alias, d_lru lists as well
-as d_inode and several other things like mount look-up. RCU-based
-changes affect only the way the hash chain is protected. For everything
-else the dcache_lock must be taken for both traversing as well as
-updating. The hash chain updates too take the dcache_lock.
-The significant change is the way d_lookup traverses the hash chain,
-it doesn't acquire the dcache_lock for this and rely on RCU to
-ensure that the dentry has not been *freed*.
-
-
-Dcache locking details
-----------------------
+Resources
+=========
+
+(Note some of these resources are not up-to-date with the latest kernel
+ version.)
+
+Creating Linux virtual filesystems. 2002
+ <http://lwn.net/Articles/13325/>
+
+The Linux Virtual File-system Layer by Neil Brown. 1999
+ <http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/vfs.html>
+
+A tour of the Linux VFS by Michael K. Johnson. 1996
+ <http://www.tldp.org/LDP/khg/HyperNews/get/fs/vfstour.html>
-For many multi-user workloads, open() and stat() on files are
-very frequently occurring operations. Both involve walking
-of path names to find the dentry corresponding to the
-concerned file. In 2.4 kernel, dcache_lock was held
-during look-up of each path component. Contention and
-cache-line bouncing of this global lock caused significant
-scalability problems. With the introduction of RCU
-in Linux kernel, this was worked around by making
-the look-up of path components during path walking lock-free.
-
-
-Safe lock-free look-up of dcache hash table
-===========================================
-
-Dcache is a complex data structure with the hash table entries
-also linked together in other lists. In 2.4 kernel, dcache_lock
-protected all the lists. We applied RCU only on hash chain
-walking. The rest of the lists are still protected by dcache_lock.
-Some of the important changes are :
-
-1. The deletion from hash chain is done using hlist_del_rcu() macro which
- doesn't initialize next pointer of the deleted dentry and this
- allows us to walk safely lock-free while a deletion is happening.
-
-2. Insertion of a dentry into the hash table is done using
- hlist_add_head_rcu() which take care of ordering the writes -
- the writes to the dentry must be visible before the dentry
- is inserted. This works in conjunction with hlist_for_each_rcu()
- while walking the hash chain. The only requirement is that
- all initialization to the dentry must be done before hlist_add_head_rcu()
- since we don't have dcache_lock protection while traversing
- the hash chain. This isn't different from the existing code.
-
-3. The dentry looked up without holding dcache_lock by cannot be
- returned for walking if it is unhashed. It then may have a NULL
- d_inode or other bogosity since RCU doesn't protect the other
- fields in the dentry. We therefore use a flag DCACHE_UNHASHED to
- indicate unhashed dentries and use this in conjunction with a
- per-dentry lock (d_lock). Once looked up without the dcache_lock,
- we acquire the per-dentry lock (d_lock) and check if the
- dentry is unhashed. If so, the look-up is failed. If not, the
- reference count of the dentry is increased and the dentry is returned.
-
-4. Once a dentry is looked up, it must be ensured during the path
- walk for that component it doesn't go away. In pre-2.5.10 code,
- this was done holding a reference to the dentry. dcache_rcu does
- the same. In some sense, dcache_rcu path walking looks like
- the pre-2.5.10 version.
-
-5. All dentry hash chain updates must take the dcache_lock as well as
- the per-dentry lock in that order. dput() does this to ensure
- that a dentry that has just been looked up in another CPU
- doesn't get deleted before dget() can be done on it.
-
-6. There are several ways to do reference counting of RCU protected
- objects. One such example is in ipv4 route cache where
- deferred freeing (using call_rcu()) is done as soon as
- the reference count goes to zero. This cannot be done in
- the case of dentries because tearing down of dentries
- require blocking (dentry_iput()) which isn't supported from
- RCU callbacks. Instead, tearing down of dentries happen
- synchronously in dput(), but actual freeing happens later
- when RCU grace period is over. This allows safe lock-free
- walking of the hash chains, but a matched dentry may have
- been partially torn down. The checking of DCACHE_UNHASHED
- flag with d_lock held detects such dentries and prevents
- them from being returned from look-up.
-
-
-Maintaining POSIX rename semantics
-==================================
-
-Since look-up of dentries is lock-free, it can race against
-a concurrent rename operation. For example, during rename
-of file A to B, look-up of either A or B must succeed.
-So, if look-up of B happens after A has been removed from the
-hash chain but not added to the new hash chain, it may fail.
-Also, a comparison while the name is being written concurrently
-by a rename may result in false positive matches violating
-rename semantics. Issues related to race with rename are
-handled as described below :
-
-1. Look-up can be done in two ways - d_lookup() which is safe
- from simultaneous renames and __d_lookup() which is not.
- If __d_lookup() fails, it must be followed up by a d_lookup()
- to correctly determine whether a dentry is in the hash table
- or not. d_lookup() protects look-ups using a sequence
- lock (rename_lock).
-
-2. The name associated with a dentry (d_name) may be changed if
- a rename is allowed to happen simultaneously. To avoid memcmp()
- in __d_lookup() go out of bounds due to a rename and false
- positive comparison, the name comparison is done while holding the
- per-dentry lock. This prevents concurrent renames during this
- operation.
-
-3. Hash table walking during look-up may move to a different bucket as
- the current dentry is moved to a different bucket due to rename.
- But we use hlists in dcache hash table and they are null-terminated.
- So, even if a dentry moves to a different bucket, hash chain
- walk will terminate. [with a list_head list, it may not since
- termination is when the list_head in the original bucket is reached].
- Since we redo the d_parent check and compare name while holding
- d_lock, lock-free look-up will not race against d_move().
-
-4. There can be a theoretical race when a dentry keeps coming back
- to original bucket due to double moves. Due to this look-up may
- consider that it has never moved and can end up in a infinite loop.
- But this is not any worse that theoretical livelocks we already
- have in the kernel.
-
-
-Important guidelines for filesystem developers related to dcache_rcu
-====================================================================
-
-1. Existing dcache interfaces (pre-2.5.62) exported to filesystem
- don't change. Only dcache internal implementation changes. However
- filesystems *must not* delete from the dentry hash chains directly
- using the list macros like allowed earlier. They must use dcache
- APIs like d_drop() or __d_drop() depending on the situation.
-
-2. d_flags is now protected by a per-dentry lock (d_lock). All
- access to d_flags must be protected by it.
-
-3. For a hashed dentry, checking of d_count needs to be protected
- by d_lock.
-
-
-Papers and other documentation on dcache locking
-================================================
-
-1. Scaling dcache with RCU (http://linuxjournal.com/article.php?sid=7124).
-
-2. http://lse.sourceforge.net/locking/dcache/dcache.html
+A small trail through the Linux kernel by Andries Brouwer. 2001
+ <http://www.win.tue.nl/~aeb/linux/vfs/trail.html>
diff --git a/Documentation/hpet.txt b/Documentation/hpet.txt
index 4e7cc8d3359b..e52457581f47 100644
--- a/Documentation/hpet.txt
+++ b/Documentation/hpet.txt
@@ -1,18 +1,21 @@
High Precision Event Timer Driver for Linux
-The High Precision Event Timer (HPET) hardware is the future replacement for the 8254 and Real
-Time Clock (RTC) periodic timer functionality. Each HPET can have up two 32 timers. It is possible
-to configure the first two timers as legacy replacements for 8254 and RTC periodic. A specification
-done by INTEL and Microsoft can be found at http://www.intel.com/labs/platcomp/hpet/hpetspec.htm.
-
-The driver supports detection of HPET driver allocation and initialization of the HPET before the
-driver module_init routine is called. This enables platform code which uses timer 0 or 1 as the
-main timer to intercept HPET initialization. An example of this initialization can be found in
+The High Precision Event Timer (HPET) hardware is the future replacement
+for the 8254 and Real Time Clock (RTC) periodic timer functionality.
+Each HPET can have up two 32 timers. It is possible to configure the
+first two timers as legacy replacements for 8254 and RTC periodic timers.
+A specification done by Intel and Microsoft can be found at
+<http://www.intel.com/hardwaredesign/hpetspec.htm>.
+
+The driver supports detection of HPET driver allocation and initialization
+of the HPET before the driver module_init routine is called. This enables
+platform code which uses timer 0 or 1 as the main timer to intercept HPET
+initialization. An example of this initialization can be found in
arch/i386/kernel/time_hpet.c.
-The driver provides two APIs which are very similar to the API found in the rtc.c driver.
-There is a user space API and a kernel space API. An example user space program is provided
-below.
+The driver provides two APIs which are very similar to the API found in
+the rtc.c driver. There is a user space API and a kernel space API.
+An example user space program is provided below.
#include <stdio.h>
#include <stdlib.h>
@@ -290,9 +293,8 @@ The kernel API has three interfaces exported from the driver:
hpet_unregister(struct hpet_task *tp)
hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
-The kernel module using this interface fills in the ht_func and ht_data members of the
-hpet_task structure before calling hpet_register. hpet_control simply vectors to the hpet_ioctl
-routine and has the same commands and respective arguments as the user API. hpet_unregister
+The kernel module using this interface fills in the ht_func and ht_data
+members of the hpet_task structure before calling hpet_register.
+hpet_control simply vectors to the hpet_ioctl routine and has the same
+commands and respective arguments as the user API. hpet_unregister
is used to terminate usage of the HPET timer reserved by hpet_register.
-
-
diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt
index bd8eefa17587..af67faccf4de 100644
--- a/Documentation/magic-number.txt
+++ b/Documentation/magic-number.txt
@@ -120,7 +120,7 @@ ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_li
SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c
STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h
CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c
-SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c
+SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c
COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c
I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c
TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c
diff --git a/Documentation/networking/decnet.txt b/Documentation/networking/decnet.txt
index c6bd25f5d61d..e6c39c5831f5 100644
--- a/Documentation/networking/decnet.txt
+++ b/Documentation/networking/decnet.txt
@@ -176,8 +176,6 @@ information (_most_ of which _is_ _essential_) includes:
- Which client caused the problem ?
- How much data was being transferred ?
- Was the network congested ?
- - If there was a kernel panic, please run the output through ksymoops
- before sending it to me, otherwise its _useless_.
- How can the problem be reproduced ?
- Can you use tcpdump to get a trace ? (N.B. Most (all?) versions of
tcpdump don't understand how to dump DECnet properly, so including
diff --git a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
index 66eaaab7773d..c563842ed805 100644
--- a/Documentation/oops-tracing.txt
+++ b/Documentation/oops-tracing.txt
@@ -1,6 +1,6 @@
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
+the Oops" or "running it through ksymoops". If you post an Oops from 2.6 that
has been run through ksymoops, people will just tell you to repost it.
Quick Summary
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index 526d6dd267ea..912bed87c758 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -11,9 +11,9 @@ boot video card. (Kernel usually does not even contain video card
driver -- vesafb and vgacon are widely used).
This is not problem for swsusp, because during swsusp resume, BIOS is
-run normally so video card is normally initialized. S3 has absolutely
-no chance of working with SMP/HT. Be sure it to turn it off before
-testing (swsusp should work ok, OTOH).
+run normally so video card is normally initialized. It should not be
+problem for S1 standby, because hardware should retain its state over
+that.
There are a few types of systems where video works after S3 resume:
@@ -64,7 +64,7 @@ your video card (good luck getting docs :-(). Maybe suspending from X
(proper X, knowing your hardware, not XF68_FBcon) might have better
chance of working.
-Table of known working systems:
+Table of known working notebooks:
Model hack (or "how to do it")
------------------------------------------------------------------------------
@@ -73,7 +73,7 @@ Acer TM 242FX vbetool (6)
Acer TM C110 video_post (8)
Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6) or video_post (8)
Acer TM 4052LCi s3_bios (2)
-Acer TM 636Lci s3_bios vga=normal (2)
+Acer TM 636Lci s3_bios,s3_mode (4)
Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
Acer TM 660 ??? (*)
Acer TM 800 vga=normal, X patches, see webpage (5) or vbetool (6)
@@ -137,6 +137,13 @@ Toshiba Satellite P10-554 s3_bios,s3_mode (4)(****)
Toshiba M30 (2) xor X with nvidia driver using internal AGP
Uniwill 244IIO ??? (*)
+Known working desktop systems
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Mainboard Graphics card hack (or "how to do it")
+------------------------------------------------------------------------------
+Asus A7V8X nVidia RIVA TNT2 model 64 s3_bios,s3_mode (4)
+
(*) from http://www.ubuntulinux.org/wiki/HoaryPMResults, not sure
which options to use. If you know, please tell me.
diff --git a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt
index 19461958e2bd..df09758bf3fe 100644
--- a/Documentation/s390/driver-model.txt
+++ b/Documentation/s390/driver-model.txt
@@ -8,11 +8,10 @@ All devices which can be addressed by means of ccws are called 'CCW devices' -
even if they aren't actually driven by ccws.
All ccw devices are accessed via a subchannel, this is reflected in the
-structures under root/:
+structures under devices/:
-root/
- - sys
- - legacy
+devices/
+ - system/
- css0/
- 0.0.0000/0.0.0815/
- 0.0.0001/0.0.4711/
@@ -36,7 +35,7 @@ availability: Can be 'good' or 'boxed'; 'no path' or 'no device' for
online: An interface to set the device online and offline.
In the special case of the device being disconnected (see the
- notify function under 1.2), piping 0 to online will focibly delete
+ notify function under 1.2), piping 0 to online will forcibly delete
the device.
The device drivers can add entries to export per-device data and interfaces.
@@ -222,7 +221,7 @@ and are called 'chp0.<chpid>'. They have no driver and do not belong to any bus.
Please note, that unlike /proc/chpids in 2.4, the channel path objects reflect
only the logical state and not the physical state, since we cannot track the
latter consistently due to lacking machine support (we don't need to be aware
-of anyway).
+of it anyway).
status - Can be 'online' or 'offline'.
Piping 'on' or 'off' sets the chpid logically online/offline.
@@ -235,12 +234,16 @@ status - Can be 'online' or 'offline'.
3. System devices
-----------------
-Note: cpus may yet be added here.
-
3.1 xpram
---------
-xpram shows up under sys/ as 'xpram'.
+xpram shows up under devices/system/ as 'xpram'.
+
+3.2 cpus
+--------
+
+For each cpu, a directory is created under devices/system/cpu/. Each cpu has an
+attribute 'online' which can be 0 or 1.
4. Other devices
diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt
index 1829009db771..3f1c5464b1c9 100644
--- a/Documentation/sparse.txt
+++ b/Documentation/sparse.txt
@@ -41,9 +41,9 @@ sure that bitwise types don't get mixed up (little-endian vs big-endian
vs cpu-endian vs whatever), and there the constant "0" really _is_
special.
-Modify top-level Makefile to say
+Use
-CHECK = sparse -Wbitwise
+ make C=[12] CF=-Wbitwise
or you don't get any checking at all.
diff --git a/Documentation/video4linux/bttv/README.freeze b/Documentation/video4linux/bttv/README.freeze
index 51f8d4379a94..4259dccc8287 100644
--- a/Documentation/video4linux/bttv/README.freeze
+++ b/Documentation/video4linux/bttv/README.freeze
@@ -27,9 +27,9 @@ information out of a register+stack dump printed by the kernel on
protection faults (so-called "kernel oops").
If you run into some kind of deadlock, you can try to dump a call trace
-for each process using sysrq-t (see Documentation/sysrq.txt). ksymoops
-will translate these dumps into kernel symbols too. This way it is
-possible to figure where *exactly* some process in "D" state is stuck.
+for each process using sysrq-t (see Documentation/sysrq.txt).
+This way it is possible to figure where *exactly* some process in "D"
+state is stuck.
I've seen reports that bttv 0.7.x crashes whereas 0.8.x works rock solid
for some people. Thus probably a small buglet left somewhere in bttv
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 1b9bcd1fe98b..1ad9af1ca4d0 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -13,12 +13,13 @@ This optimization is more critical now as bigger and bigger physical memories
Users can use the huge page support in Linux kernel by either using the mmap
system call or standard SYSv shared memory system calls (shmget, shmat).
-First the Linux kernel needs to be built with CONFIG_HUGETLB_PAGE (present
-under Processor types and feature) and CONFIG_HUGETLBFS (present under file
-system option on config menu) config options.
+First the Linux kernel needs to be built with the CONFIG_HUGETLBFS
+(present under "File systems") and CONFIG_HUGETLB_PAGE (selected
+automatically when CONFIG_HUGETLBFS is selected) configuration
+options.
The kernel built with hugepage support should show the number of configured
-hugepages in the system by running the "cat /proc/meminfo" command.
+hugepages in the system by running the "cat /proc/meminfo" command.
/proc/meminfo also provides information about the total number of hugetlb
pages configured in the kernel. It also displays information about the
@@ -38,19 +39,19 @@ in the kernel.
/proc/sys/vm/nr_hugepages indicates the current number of configured hugetlb
pages in the kernel. Super user can dynamically request more (or free some
-pre-configured) hugepages.
-The allocation( or deallocation) of hugetlb pages is posible only if there are
+pre-configured) hugepages.
+The allocation (or deallocation) of hugetlb pages is possible only if there are
enough physically contiguous free pages in system (freeing of hugepages is
-possible only if there are enough hugetlb pages free that can be transfered
+possible only if there are enough hugetlb pages free that can be transfered
back to regular memory pool).
Pages that are used as hugetlb pages are reserved inside the kernel and can
-not be used for other purposes.
+not be used for other purposes.
Once the kernel with Hugetlb page support is built and running, a user can
use either the mmap system call or shared memory system calls to start using
the huge pages. It is required that the system administrator preallocate
-enough memory for huge page purposes.
+enough memory for huge page purposes.
Use the following command to dynamically allocate/deallocate hugepages:
@@ -80,9 +81,9 @@ memory (huge pages) allowed for that filesystem (/mnt/huge). The size is
rounded down to HPAGE_SIZE. The option nr_inode sets the maximum number of
inodes that /mnt/huge can use. If the size or nr_inode options are not
provided on command line then no limits are set. For size and nr_inodes
-options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
-example, size=2K has the same meaning as size=2048. An example is given at
-the end of this document.
+options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
+example, size=2K has the same meaning as size=2048. An example is given at
+the end of this document.
read and write system calls are not supported on files that reside on hugetlb
file systems.
diff --git a/MAINTAINERS b/MAINTAINERS
index d57c491212b1..3ccbfa96eeec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1077,6 +1077,26 @@ P: Jaroslav Kysela
M: perex@suse.cz
S: Maintained
+HPET: High Precision Event Timers driver (hpet.c)
+P: Clemens Ladisch
+M: clemens@ladisch.de
+S: Maintained
+
+HPET: i386
+P: Venkatesh Pallipadi (Venki)
+M: venkatesh.pallipadi@intel.com
+S: Maintained
+
+HPET: x86_64
+P: Andi Kleen and Vojtech Pavlik
+M: ak@muc.de and vojtech@suse.cz
+S: Maintained
+
+HPET: ACPI hpet.c
+P: Bob Picco
+M: bob.picco@hp.com
+S: Maintained
+
HPFS FILESYSTEM
P: Mikulas Patocka
M: mikulas@artax.karlin.mff.cuni.cz
@@ -2051,6 +2071,12 @@ P: Matt Mackall
M: mpm@selenic.com
S: Maintained
+RAPIDIO SUBSYSTEM
+P: Matt Porter
+M: mporter@kernel.crashing.org
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
REAL TIME CLOCK DRIVER
P: Paul Gortmaker
M: p_gortmaker@yahoo.com
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9bd8609a2926..9a340e790da5 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
#endif
-static int do_ptrace(int request, struct task_struct *child, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
unsigned long tmp;
int ret;
@@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
return ret;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
-{
- struct task_struct *child;
- int ret;
-
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret == 0)
- ret = do_ptrace(request, child, addr, data);
-
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
- return ret;
-}
-
asmlinkage void syscall_trace(int why, struct pt_regs *regs)
{
unsigned long ip;
diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c
index 99e019169dda..0340ddc4824e 100644
--- a/arch/arm/mach-aaec2000/clock.c
+++ b/arch/arm/mach-aaec2000/clock.c
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/string.h>
#include <asm/semaphore.h>
#include <asm/hardware/clock.h>
diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c
index e8832d0910ee..cfd0d2182d44 100644
--- a/arch/arm/mach-epxa10db/mm.c
+++ b/arch/arm/mach-epxa10db/mm.c
@@ -25,6 +25,7 @@
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/sizes.h>
+#include <asm/page.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index a1b153d1626c..a4bafee77a06 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -420,8 +420,7 @@ static int impd1_probe(struct lm_device *dev)
free_impd1:
if (impd1 && impd1->base)
iounmap(impd1->base);
- if (impd1)
- kfree(impd1);
+ kfree(impd1);
release_lm:
release_mem_region(dev->resource.start, SZ_4K);
return ret;
diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c
index 54162ba95414..698eb06545c4 100644
--- a/arch/arm/mach-pxa/corgi_lcd.c
+++ b/arch/arm/mach-pxa/corgi_lcd.c
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/module.h>
+#include <linux/string.h>
#include <asm/arch/akita.h>
#include <asm/arch/corgi.h>
#include <asm/arch/hardware.h>
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index cf7e977d18c8..4e6b7356a722 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
sizeof(struct user_fp)) ? -EFAULT : 0;
}
-static int do_ptrace(int request, struct task_struct *child, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
unsigned long tmp;
int ret;
@@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
return ret;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
-{
- struct task_struct *child;
- int ret;
-
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret == 0)
- ret = do_ptrace(request, child, addr, data);
-
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
- return ret;
-}
-
asmlinkage void syscall_trace(int why, struct pt_regs *regs)
{
unsigned long ip;
diff --git a/arch/cris/arch-v10/README.mm b/arch/cris/arch-v10/README.mm
index 6f08903f3139..517d1f027fe8 100644
--- a/arch/cris/arch-v10/README.mm
+++ b/arch/cris/arch-v10/README.mm
@@ -177,7 +177,7 @@ The example address is 0xd004000c; in binary this is:
Given the top-level Page Directory, the offset in that directory is calculated
using the upper 8 bits:
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
{
return mm->pgd + (address >> PGDIR_SHIFT);
}
@@ -190,14 +190,14 @@ The pgd_t from our example will therefore be the 208'th (0xd0) entry in mm->pgd.
Since the Middle Directory does not exist, it is a unity mapping:
-extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
{
return (pmd_t *) dir;
}
The Page Table provides the final lookup by using bits 13 to 23 as index:
-extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+static inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
{
return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) &
(PTRS_PER_PTE - 1));
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index 130dd214e41d..6cbd34a27b90 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child)
* (in user space) where the result of the ptrace call is written (instead of
* being returned).
*/
-asmlinkage int
-sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret;
unsigned long __user *datap = (unsigned long __user *)data;
- lock_kernel();
- ret = -EPERM;
-
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
-
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
-
- if (child)
- get_task_struct(child);
-
- read_unlock(&tasklist_lock);
-
- if (!child)
- goto out;
-
- ret = -EPERM;
-
- if (pid == 1) /* Leave the init process alone! */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* Read word at location address. */
case PTRACE_PEEKTEXT:
@@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+
return ret;
}
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 693771961f85..19bcad05716f 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -476,7 +476,7 @@ give_sigsegv:
* OK, we're invoking a handler
*/
-extern inline void
+static inline void
handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs * regs)
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index ca72076c630a..501fa52d8d3a 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -277,7 +277,7 @@ struct file_operations cryptocop_fops = {
static void free_cdesc(struct cryptocop_dma_desc *cdesc)
{
DEBUG(printk("free_cdesc: cdesc 0x%p, from_pool=%d\n", cdesc, cdesc->from_pool));
- if (cdesc->free_buf) kfree(cdesc->free_buf);
+ kfree(cdesc->free_buf);
if (cdesc->from_pool) {
unsigned long int flags;
@@ -2950,15 +2950,15 @@ static int cryptocop_ioctl_process(struct inode *inode, struct file *filp, unsig
put_page(outpages[i]);
}
- if (digest_result) kfree(digest_result);
- if (inpages) kfree(inpages);
- if (outpages) kfree(outpages);
+ kfree(digest_result);
+ kfree(inpages);
+ kfree(outpages);
if (cop){
- if (cop->tfrm_op.indata) kfree(cop->tfrm_op.indata);
- if (cop->tfrm_op.outdata) kfree(cop->tfrm_op.outdata);
+ kfree(cop->tfrm_op.indata);
+ kfree(cop->tfrm_op.outdata);
kfree(cop);
}
- if (jc) kfree(jc);
+ kfree(jc);
DEBUG(print_lock_status());
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index 208489da2a87..5528b83a622b 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child)
}
-asmlinkage int
-sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret;
unsigned long __user *datap = (unsigned long __user *)data;
- lock_kernel();
- ret = -EPERM;
-
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
-
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
-
- if (child)
- get_task_struct(child);
-
- read_unlock(&tasklist_lock);
-
- if (!child)
- goto out;
-
- ret = -EPERM;
-
- if (pid == 1) /* Leave the init process alone! */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* Read word at location address. */
case PTRACE_PEEKTEXT:
@@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+
return ret;
}
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c
index 0a3614dab887..99e59b3eacf8 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -513,7 +513,7 @@ give_sigsegv:
}
/* Invoke a singal handler to, well, handle the signal. */
-extern inline void
+static inline void
handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs * regs)
diff --git a/arch/cris/mm/ioremap.c b/arch/cris/mm/ioremap.c
index a92ac9877582..1780df3ed9e5 100644
--- a/arch/cris/mm/ioremap.c
+++ b/arch/cris/mm/ioremap.c
@@ -16,7 +16,7 @@
#include <asm/tlbflush.h>
#include <asm/arch/memmap.h>
-extern inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, pgprot_t prot)
{
unsigned long end;
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c
index cb335a14a315..f953484e7d59 100644
--- a/arch/frv/kernel/ptrace.c
+++ b/arch/frv/kernel/ptrace.c
@@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child)
child->thread.frame0->__status |= REG__STATUS_STEP;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
unsigned long tmp;
int ret;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
return ret;
}
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index a569fe4aa284..0ff6f79b0fed 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child)
h8300_disable_trace(child);
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
@@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
return ret;
}
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index bac0da731ee3..dbf90ad6eac3 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -997,8 +997,21 @@ source "drivers/Kconfig"
source "fs/Kconfig"
+menu "Instrumentation Support"
+ depends on EXPERIMENTAL
+
source "arch/i386/oprofile/Kconfig"
+config KPROBES
+ bool "Kprobes (EXPERIMENTAL)"
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+endmenu
+
source "arch/i386/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
index 5228c40a6fb2..c48b424dd640 100644
--- a/arch/i386/Kconfig.debug
+++ b/arch/i386/Kconfig.debug
@@ -22,16 +22,6 @@ config DEBUG_STACKOVERFLOW
This option will cause messages to be printed if free stack space
drops below a certain limit.
-config KPROBES
- bool "Kprobes"
- depends on DEBUG_KERNEL
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
config DEBUG_STACK_USAGE
bool "Stack utilization instrumentation"
depends on DEBUG_KERNEL
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 7c724ffa08bb..496a2c9909fe 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -559,14 +559,20 @@ void __devinit setup_local_APIC(void)
* If Linux enabled the LAPIC against the BIOS default
* disable it down before re-entering the BIOS on shutdown.
* Otherwise the BIOS may get confused and not power-off.
+ * Additionally clear all LVT entries before disable_local_APIC
+ * for the case where Linux didn't enable the LAPIC.
*/
void lapic_shutdown(void)
{
- if (!cpu_has_apic || !enabled_via_apicbase)
+ if (!cpu_has_apic)
return;
local_irq_disable();
- disable_local_APIC();
+ clear_local_APIC();
+
+ if (enabled_via_apicbase)
+ disable_local_APIC();
+
local_irq_enable();
}
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index d2ef0c2aa93e..86e80c551478 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -447,8 +447,7 @@ static char * apm_event_name[] = {
"system standby resume",
"capabilities change"
};
-#define NR_APM_EVENT_NAME \
- (sizeof(apm_event_name) / sizeof(apm_event_name[0]))
+#define NR_APM_EVENT_NAME ARRAY_SIZE(apm_event_name)
typedef struct lookup_t {
int key;
@@ -479,7 +478,7 @@ static const lookup_t error_table[] = {
{ APM_NO_ERROR, "BIOS did not set a return code" },
{ APM_NOT_PRESENT, "No APM present" }
};
-#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
+#define ERROR_COUNT ARRAY_SIZE(error_table)
/**
* apm_error - display an APM error
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 74145a33cb0f..c145fb30002e 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -30,8 +30,6 @@ static int disable_x86_serial_nr __devinitdata = 1;
struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
-extern void mcheck_init(struct cpuinfo_x86 *c);
-
extern int disable_pse;
static void default_init(struct cpuinfo_x86 * c)
@@ -429,9 +427,8 @@ void __devinit identify_cpu(struct cpuinfo_x86 *c)
}
/* Init Machine Check Exception if available. */
-#ifdef CONFIG_X86_MCE
mcheck_init(c);
-#endif
+
if (c == &boot_cpu_data)
sysenter_setup();
enable_sep_cpu();
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 1465974256c9..0ea010a7afb1 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -67,7 +67,7 @@ static const struct cpu_id cpu_ids[] = {
[CPU_MP4HT_D0] = {15, 3, 4 },
[CPU_MP4HT_E0] = {15, 4, 1 },
};
-#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
+#define N_IDS ARRAY_SIZE(cpu_ids)
struct cpu_model
{
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c
index 7c6b9c73522f..fc5d5215e23d 100644
--- a/arch/i386/kernel/cpu/mcheck/k7.c
+++ b/arch/i386/kernel/cpu/mcheck/k7.c
@@ -68,7 +68,7 @@ static fastcall void k7_machine_check(struct pt_regs * regs, long error_code)
/* AMD K7 machine check is Intel like */
-void __devinit amd_mcheck_init(struct cpuinfo_x86 *c)
+void amd_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c
index 2cf25d2ba0f1..6170af3c271a 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.c
+++ b/arch/i386/kernel/cpu/mcheck/mce.c
@@ -16,7 +16,7 @@
#include "mce.h"
-int mce_disabled __devinitdata = 0;
+int mce_disabled = 0;
int nr_mce_banks;
EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */
@@ -31,7 +31,7 @@ static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_
void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
/* This has to be run for each processor */
-void __devinit mcheck_init(struct cpuinfo_x86 *c)
+void mcheck_init(struct cpuinfo_x86 *c)
{
if (mce_disabled==1)
return;
diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c
index 1d1e885f500a..fd2c459a31ef 100644
--- a/arch/i386/kernel/cpu/mcheck/p4.c
+++ b/arch/i386/kernel/cpu/mcheck/p4.c
@@ -77,7 +77,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs)
}
/* P4/Xeon Thermal regulation detect and init */
-static void __devinit intel_init_thermal(struct cpuinfo_x86 *c)
+static void intel_init_thermal(struct cpuinfo_x86 *c)
{
u32 l, h;
unsigned int cpu = smp_processor_id();
@@ -231,7 +231,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
}
-void __devinit intel_p4_mcheck_init(struct cpuinfo_x86 *c)
+void intel_p4_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c
index 3a2e24baddc7..94bc43d950cf 100644
--- a/arch/i386/kernel/cpu/mcheck/p5.c
+++ b/arch/i386/kernel/cpu/mcheck/p5.c
@@ -28,7 +28,7 @@ static fastcall void pentium_machine_check(struct pt_regs * regs, long error_cod
}
/* Set up machine check reporting for processors with Intel style MCE */
-void __devinit intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+void intel_p5_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c
index 979b18bc95c1..deeae42ce199 100644
--- a/arch/i386/kernel/cpu/mcheck/p6.c
+++ b/arch/i386/kernel/cpu/mcheck/p6.c
@@ -79,7 +79,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
}
/* Set up machine check reporting for processors with Intel style MCE */
-void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+void intel_p6_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c
index 5b9d2dd411d3..9e424b6c293d 100644
--- a/arch/i386/kernel/cpu/mcheck/winchip.c
+++ b/arch/i386/kernel/cpu/mcheck/winchip.c
@@ -22,7 +22,7 @@ static fastcall void winchip_machine_check(struct pt_regs * regs, long error_cod
}
/* Set up machine check reporting on the Winchip C6 series */
-void __devinit winchip_mcheck_init(struct cpuinfo_x86 *c)
+void winchip_mcheck_init(struct cpuinfo_x86 *c)
{
u32 lo, hi;
machine_check_vector = winchip_machine_check;
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 6345b430b105..32b0c24ab9a6 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -31,22 +31,16 @@
#include <linux/config.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
-#include <linux/spinlock.h>
#include <linux/preempt.h>
#include <asm/cacheflush.h>
#include <asm/kdebug.h>
#include <asm/desc.h>
-static struct kprobe *current_kprobe;
-static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev;
-static struct pt_regs jprobe_saved_regs;
-static long *jprobe_saved_esp;
-/* copy of the kernel stack at the probe fire time */
-static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
void jprobe_return_end(void);
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
/*
* returns non-zero if opcode modifies the interrupt flag.
*/
@@ -91,29 +85,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
{
}
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- kprobe_prev = current_kprobe;
- kprobe_status_prev = kprobe_status;
- kprobe_old_eflags_prev = kprobe_old_eflags;
- kprobe_saved_eflags_prev = kprobe_saved_eflags;
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
+ kcb->prev_kprobe.old_eflags = kcb->kprobe_old_eflags;
+ kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
}
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- current_kprobe = kprobe_prev;
- kprobe_status = kprobe_status_prev;
- kprobe_old_eflags = kprobe_old_eflags_prev;
- kprobe_saved_eflags = kprobe_saved_eflags_prev;
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+ kcb->kprobe_status = kcb->prev_kprobe.status;
+ kcb->kprobe_old_eflags = kcb->prev_kprobe.old_eflags;
+ kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
{
- current_kprobe = p;
- kprobe_saved_eflags = kprobe_old_eflags
+ __get_cpu_var(current_kprobe) = p;
+ kcb->kprobe_saved_eflags = kcb->kprobe_old_eflags
= (regs->eflags & (TF_MASK | IF_MASK));
if (is_IF_modifier(p->opcode))
- kprobe_saved_eflags &= ~IF_MASK;
+ kcb->kprobe_saved_eflags &= ~IF_MASK;
}
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -127,6 +122,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->eip = (unsigned long)&p->ainsn.insn;
}
+/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
struct pt_regs *regs)
{
@@ -157,9 +153,15 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
int ret = 0;
kprobe_opcode_t *addr = NULL;
unsigned long *lp;
+ struct kprobe_ctlblk *kcb;
- /* We're in an interrupt, but this is clear and BUG()-safe. */
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
preempt_disable();
+ kcb = get_kprobe_ctlblk();
+
/* Check if the application is using LDT entry for its code segment and
* calculate the address by reading the base address from the LDT entry.
*/
@@ -173,15 +175,12 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
}
/* Check we're not actually recursing */
if (kprobe_running()) {
- /* We *are* holding lock here, so this is safe.
- Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
- if (kprobe_status == KPROBE_HIT_SS &&
+ if (kcb->kprobe_status == KPROBE_HIT_SS &&
*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
regs->eflags &= ~TF_MASK;
- regs->eflags |= kprobe_saved_eflags;
- unlock_kprobes();
+ regs->eflags |= kcb->kprobe_saved_eflags;
goto no_kprobe;
}
/* We have reentered the kprobe_handler(), since
@@ -190,26 +189,23 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
* just single step on the instruction of the new probe
* without calling any user handlers.
*/
- save_previous_kprobe();
- set_current_kprobe(p, regs);
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p, regs, kcb);
p->nmissed++;
prepare_singlestep(p, regs);
- kprobe_status = KPROBE_REENTER;
+ kcb->kprobe_status = KPROBE_REENTER;
return 1;
} else {
- p = current_kprobe;
+ p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
}
}
- /* If it's not ours, can't be delete race, (we hold lock). */
goto no_kprobe;
}
- lock_kprobes();
p = get_kprobe(addr);
if (!p) {
- unlock_kprobes();
if (regs->eflags & VM_MASK) {
/* We are in virtual-8086 mode. Return 0 */
goto no_kprobe;
@@ -232,8 +228,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
goto no_kprobe;
}
- kprobe_status = KPROBE_HIT_ACTIVE;
- set_current_kprobe(p, regs);
+ set_current_kprobe(p, regs, kcb);
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
@@ -241,7 +237,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
ss_probe:
prepare_singlestep(p, regs);
- kprobe_status = KPROBE_HIT_SS;
+ kcb->kprobe_status = KPROBE_HIT_SS;
return 1;
no_kprobe:
@@ -269,9 +265,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
+ unsigned long flags, orig_ret_address = 0;
unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+ spin_lock_irqsave(&kretprobe_lock, flags);
head = kretprobe_inst_table_head(current);
/*
@@ -310,14 +307,15 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
regs->eip = orig_ret_address;
- unlock_kprobes();
+ reset_current_kprobe();
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
preempt_enable_no_resched();
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
- */
+ /*
+ * By returning a non-zero value, we are telling
+ * kprobe_handler() that we don't want the post_handler
+ * to run (and have re-enabled preemption)
+ */
return 1;
}
@@ -343,7 +341,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
* that is atop the stack is the address following the copied instruction.
* We need to make it the address following the original instruction.
*/
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p,
+ struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
unsigned long *tos = (unsigned long *)&regs->esp;
unsigned long next_eip = 0;
@@ -353,7 +352,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
switch (p->ainsn.insn[0]) {
case 0x9c: /* pushfl */
*tos &= ~(TF_MASK | IF_MASK);
- *tos |= kprobe_old_eflags;
+ *tos |= kcb->kprobe_old_eflags;
break;
case 0xc3: /* ret/lret */
case 0xcb:
@@ -394,27 +393,30 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
/*
* Interrupts are disabled on entry as trap1 is an interrupt gate and they
- * remain disabled thoroughout this function. And we hold kprobe lock.
+ * remain disabled thoroughout this function.
*/
static inline int post_kprobe_handler(struct pt_regs *regs)
{
- if (!kprobe_running())
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (!cur)
return 0;
- if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
- kprobe_status = KPROBE_HIT_SSDONE;
- current_kprobe->post_handler(current_kprobe, regs, 0);
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
}
- resume_execution(current_kprobe, regs);
- regs->eflags |= kprobe_saved_eflags;
+ resume_execution(cur, regs, kcb);
+ regs->eflags |= kcb->kprobe_saved_eflags;
/*Restore back the original saved kprobes variables and continue. */
- if (kprobe_status == KPROBE_REENTER) {
- restore_previous_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
goto out;
}
- unlock_kprobes();
+ reset_current_kprobe();
out:
preempt_enable_no_resched();
@@ -429,18 +431,19 @@ out:
return 1;
}
-/* Interrupts disabled, kprobe_lock held. */
static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
- if (current_kprobe->fault_handler
- && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;
- if (kprobe_status & KPROBE_HIT_SS) {
- resume_execution(current_kprobe, regs);
- regs->eflags |= kprobe_old_eflags;
+ if (kcb->kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs, kcb);
+ regs->eflags |= kcb->kprobe_old_eflags;
- unlock_kprobes();
+ reset_current_kprobe();
preempt_enable_no_resched();
}
return 0;
@@ -453,39 +456,41 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
switch (val) {
case DIE_INT3:
if (kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_DEBUG:
if (post_kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_GPF:
- if (kprobe_running() &&
- kprobe_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
- break;
case DIE_PAGE_FAULT:
+ /* kprobe_running() needs smp_processor_id() */
+ preempt_disable();
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
+ preempt_enable();
break;
default:
break;
}
- return NOTIFY_DONE;
+ return ret;
}
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr;
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- jprobe_saved_regs = *regs;
- jprobe_saved_esp = &regs->esp;
- addr = (unsigned long)jprobe_saved_esp;
+ kcb->jprobe_saved_regs = *regs;
+ kcb->jprobe_saved_esp = &regs->esp;
+ addr = (unsigned long)(kcb->jprobe_saved_esp);
/*
* TBD: As Linus pointed out, gcc assumes that the callee
@@ -494,7 +499,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
* we also save and restore enough stack bytes to cover
* the argument area.
*/
- memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr));
+ memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
+ MIN_STACK_SIZE(addr));
regs->eflags &= ~IF_MASK;
regs->eip = (unsigned long)(jp->entry);
return 1;
@@ -502,36 +508,40 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
void __kprobes jprobe_return(void)
{
- preempt_enable_no_resched();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
asm volatile (" xchgl %%ebx,%%esp \n"
" int3 \n"
" .globl jprobe_return_end \n"
" jprobe_return_end: \n"
" nop \n"::"b"
- (jprobe_saved_esp):"memory");
+ (kcb->jprobe_saved_esp):"memory");
}
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
u8 *addr = (u8 *) (regs->eip - 1);
- unsigned long stack_addr = (unsigned long)jprobe_saved_esp;
+ unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_esp);
struct jprobe *jp = container_of(p, struct jprobe, kp);
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
- if (&regs->esp != jprobe_saved_esp) {
+ if (&regs->esp != kcb->jprobe_saved_esp) {
struct pt_regs *saved_regs =
- container_of(jprobe_saved_esp, struct pt_regs, esp);
+ container_of(kcb->jprobe_saved_esp,
+ struct pt_regs, esp);
printk("current esp %p does not match saved esp %p\n",
- &regs->esp, jprobe_saved_esp);
+ &regs->esp, kcb->jprobe_saved_esp);
printk("Saved registers for jprobe %p\n", jp);
show_registers(saved_regs);
printk("Current registers\n");
show_registers(regs);
BUG();
}
- *regs = jprobe_saved_regs;
- memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack,
+ *regs = kcb->jprobe_saved_regs;
+ memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
MIN_STACK_SIZE(stack_addr));
+ preempt_enable_no_resched();
return 1;
}
return 0;
diff --git a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c
index fe1ffa55587d..983f95707e11 100644
--- a/arch/i386/kernel/ldt.c
+++ b/arch/i386/kernel/ldt.c
@@ -18,6 +18,7 @@
#include <asm/system.h>
#include <asm/ldt.h>
#include <asm/desc.h>
+#include <asm/mmu_context.h>
#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
static void flush_ldt(void *null)
diff --git a/arch/i386/kernel/mca.c b/arch/i386/kernel/mca.c
index 8600faeea29d..558bb207720f 100644
--- a/arch/i386/kernel/mca.c
+++ b/arch/i386/kernel/mca.c
@@ -132,7 +132,7 @@ static struct resource mca_standard_resources[] = {
{ .start = 0x100, .end = 0x107, .name = "POS (MCA)" }
};
-#define MCA_STANDARD_RESOURCES (sizeof(mca_standard_resources)/sizeof(struct resource))
+#define MCA_STANDARD_RESOURCES ARRAY_SIZE(mca_standard_resources)
/**
* mca_read_and_store_pos - read the POS registers into a memory buffer
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index efd11f09c996..5ffbb4b7ad05 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child,
return 0;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
struct user * dummy = NULL;
int i, ret;
unsigned long __user *datap = (unsigned long __user *)data;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+ out_tsk:
return ret;
}
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index c9b87330aeea..10e21a4773dd 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -10,6 +10,7 @@
#include <asm/delay.h>
#include <linux/pci.h>
+#include <linux/reboot_fixups.h>
static void cs5530a_warm_reset(struct pci_dev *dev)
{
@@ -42,7 +43,7 @@ void mach_reboot_fixups(void)
struct pci_dev *dev;
int i;
- for (i=0; i < (sizeof(fixups_table)/sizeof(fixups_table[0])); i++) {
+ for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
cur = &(fixups_table[i]);
dev = pci_get_device(cur->vendor, cur->device, NULL);
if (!dev)
diff --git a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c
index 69e203a0d330..9c968ae67c43 100644
--- a/arch/i386/kernel/scx200.c
+++ b/arch/i386/kernel/scx200.c
@@ -12,6 +12,7 @@
#include <linux/pci.h>
#include <linux/scx200.h>
+#include <linux/scx200_gpio.h>
/* Verify that the configuration block really is there */
#define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 01b618e73ecd..47ec76794d02 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -68,11 +68,9 @@ EXPORT_SYMBOL(smp_num_siblings);
/* Package ID of each logical CPU */
int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
-EXPORT_SYMBOL(phys_proc_id);
/* Core ID of each logical CPU */
int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
-EXPORT_SYMBOL(cpu_core_id);
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_sibling_map);
@@ -612,7 +610,7 @@ static inline void __inquire_remote_apic(int apicid)
printk("Inquiring remote APIC #%d...\n", apicid);
- for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
+ for (i = 0; i < ARRAY_SIZE(regs); i++) {
printk("... APIC #%d %s: ", apicid, names[i]);
/*
diff --git a/arch/i386/oprofile/Kconfig b/arch/i386/oprofile/Kconfig
index 5ade19801b97..d8a84088471a 100644
--- a/arch/i386/oprofile/Kconfig
+++ b/arch/i386/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
config PROFILING
bool "Profiling support (EXPERIMENTAL)"
help
@@ -19,5 +15,3 @@ config OPROFILE
If unsure, say N.
-endmenu
-
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index 1f1572692e0b..50a0bef8c85f 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -118,6 +118,7 @@ void __restore_processor_state(struct saved_context *ctxt)
fix_processor_context();
do_fpu_end();
mtrr_ap_init();
+ mcheck_init(&boot_cpu_data);
}
void restore_processor_state(void)
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 3b4248cff9a7..9f2093c1f44b 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -426,8 +426,21 @@ config GENERIC_PENDING_IRQ
source "arch/ia64/hp/sim/Kconfig"
+menu "Instrumentation Support"
+ depends on EXPERIMENTAL
+
source "arch/ia64/oprofile/Kconfig"
+config KPROBES
+ bool "Kprobes (EXPERIMENTAL)"
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+endmenu
+
source "arch/ia64/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
index fda67ac993d7..de9d507ba0fd 100644
--- a/arch/ia64/Kconfig.debug
+++ b/arch/ia64/Kconfig.debug
@@ -2,17 +2,6 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
-config KPROBES
- bool "Kprobes"
- depends on DEBUG_KERNEL
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
-
choice
prompt "Physical memory granularity"
default IA64_GRANULE_64MB
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index b42ec37be51c..19ee635eeb70 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -642,10 +642,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info->event = 0;
info->tty = 0;
if (info->blocked_open) {
- if (info->close_delay) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(info->close_delay);
- }
+ if (info->close_delay)
+ schedule_timeout_interruptible(info->close_delay);
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 471086b808a4..96736a119c91 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -26,7 +26,6 @@
#include <linux/config.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
-#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/preempt.h>
@@ -38,13 +37,8 @@
extern void jprobe_inst_return(void);
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE 0x00000001
-#define KPROBE_HIT_SS 0x00000002
-
-static struct kprobe *current_kprobe, *kprobe_prev;
-static unsigned long kprobe_status, kprobe_status_prev;
-static struct pt_regs jprobe_saved_regs;
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
enum instruction_type {A, I, M, F, B, L, X, u};
static enum instruction_type bundle_encoding[32][3] = {
@@ -313,21 +307,22 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
return 0;
}
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- kprobe_prev = current_kprobe;
- kprobe_status_prev = kprobe_status;
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
}
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- current_kprobe = kprobe_prev;
- kprobe_status = kprobe_status_prev;
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+ kcb->kprobe_status = kcb->prev_kprobe.status;
}
-static inline void set_current_kprobe(struct kprobe *p)
+static inline void set_current_kprobe(struct kprobe *p,
+ struct kprobe_ctlblk *kcb)
{
- current_kprobe = p;
+ __get_cpu_var(current_kprobe) = p;
}
static void kretprobe_trampoline(void)
@@ -347,10 +342,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
+ unsigned long flags, orig_ret_address = 0;
unsigned long trampoline_address =
((struct fnptr *)kretprobe_trampoline)->ip;
+ spin_lock_irqsave(&kretprobe_lock, flags);
head = kretprobe_inst_table_head(current);
/*
@@ -389,17 +385,19 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
regs->cr_iip = orig_ret_address;
- unlock_kprobes();
+ reset_current_kprobe();
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
preempt_enable_no_resched();
- /*
- * By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
- */
+ /*
+ * By returning a non-zero value, we are telling
+ * kprobe_handler() that we don't want the post_handler
+ * to run (and have re-enabled preemption)
+ */
return 1;
}
+/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
struct pt_regs *regs)
{
@@ -606,17 +604,22 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
int ret = 0;
struct pt_regs *regs = args->regs;
kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
+ struct kprobe_ctlblk *kcb;
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
preempt_disable();
+ kcb = get_kprobe_ctlblk();
/* Handle recursion cases */
if (kprobe_running()) {
p = get_kprobe(addr);
if (p) {
- if ( (kprobe_status == KPROBE_HIT_SS) &&
+ if ((kcb->kprobe_status == KPROBE_HIT_SS) &&
(p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) {
ia64_psr(regs)->ss = 0;
- unlock_kprobes();
goto no_kprobe;
}
/* We have reentered the pre_kprobe_handler(), since
@@ -625,17 +628,17 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
* just single step on the instruction of the new probe
* without calling any user handlers.
*/
- save_previous_kprobe();
- set_current_kprobe(p);
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p, kcb);
p->nmissed++;
prepare_ss(p, regs);
- kprobe_status = KPROBE_REENTER;
+ kcb->kprobe_status = KPROBE_REENTER;
return 1;
} else if (args->err == __IA64_BREAK_JPROBE) {
/*
* jprobe instrumented function just completed
*/
- p = current_kprobe;
+ p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
}
@@ -645,10 +648,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
}
}
- lock_kprobes();
p = get_kprobe(addr);
if (!p) {
- unlock_kprobes();
if (!is_ia64_break_inst(regs)) {
/*
* The breakpoint instruction was removed right
@@ -665,8 +666,8 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
goto no_kprobe;
}
- kprobe_status = KPROBE_HIT_ACTIVE;
- set_current_kprobe(p);
+ set_current_kprobe(p, kcb);
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
if (p->pre_handler && p->pre_handler(p, regs))
/*
@@ -678,7 +679,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
ss_probe:
prepare_ss(p, regs);
- kprobe_status = KPROBE_HIT_SS;
+ kcb->kprobe_status = KPROBE_HIT_SS;
return 1;
no_kprobe:
@@ -688,23 +689,25 @@ no_kprobe:
static int __kprobes post_kprobes_handler(struct pt_regs *regs)
{
- if (!kprobe_running())
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (!cur)
return 0;
- if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
- kprobe_status = KPROBE_HIT_SSDONE;
- current_kprobe->post_handler(current_kprobe, regs, 0);
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
}
- resume_execution(current_kprobe, regs);
+ resume_execution(cur, regs);
/*Restore back the original saved kprobes variables and continue. */
- if (kprobe_status == KPROBE_REENTER) {
- restore_previous_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
goto out;
}
-
- unlock_kprobes();
+ reset_current_kprobe();
out:
preempt_enable_no_resched();
@@ -713,16 +716,15 @@ out:
static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
{
- if (!kprobe_running())
- return 0;
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- if (current_kprobe->fault_handler &&
- current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;
- if (kprobe_status & KPROBE_HIT_SS) {
- resume_execution(current_kprobe, regs);
- unlock_kprobes();
+ if (kcb->kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs);
+ reset_current_kprobe();
preempt_enable_no_resched();
}
@@ -733,31 +735,38 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
switch(val) {
case DIE_BREAK:
if (pre_kprobes_handler(args))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_SS:
if (post_kprobes_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_PAGE_FAULT:
- if (kprobes_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
+ /* kprobe_running() needs smp_processor_id() */
+ preempt_disable();
+ if (kprobe_running() &&
+ kprobes_fault_handler(args->regs, args->trapnr))
+ ret = NOTIFY_STOP;
+ preempt_enable();
default:
break;
}
- return NOTIFY_DONE;
+ return ret;
}
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
/* save architectural state */
- jprobe_saved_regs = *regs;
+ kcb->jprobe_saved_regs = *regs;
/* after rfi, execute the jprobe instrumented function */
regs->cr_iip = addr & ~0xFULL;
@@ -775,7 +784,10 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
- *regs = jprobe_saved_regs;
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ *regs = kcb->jprobe_saved_regs;
+ preempt_enable_no_resched();
return 1;
}
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index f7dfc107cb7b..410d4804fa6e 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -4940,7 +4940,7 @@ abort_locked:
if (call_made && PFM_CMD_RW_ARG(cmd) && copy_to_user(arg, args_k, base_sz*count)) ret = -EFAULT;
error_args:
- if (args_k) kfree(args_k);
+ kfree(args_k);
DPRINT(("cmd=%s ret=%ld\n", PFM_CMD_NAME(cmd), ret));
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index fc56ca2da358..3af6de36a482 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -92,6 +92,13 @@ extern void efi_initialize_iomem_resources(struct resource *,
extern char _text[], _end[], _etext[];
unsigned long ia64_max_cacheline_size;
+
+int dma_get_cache_alignment(void)
+{
+ return ia64_max_cacheline_size;
+}
+EXPORT_SYMBOL(dma_get_cache_alignment);
+
unsigned long ia64_iobase; /* virtual address for I/O accesses */
EXPORT_SYMBOL(ia64_iobase);
struct io_space io_space[MAX_IO_SPACES];
diff --git a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig
index 56e6f614b04a..97271ab484dc 100644
--- a/arch/ia64/oprofile/Kconfig
+++ b/arch/ia64/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
config PROFILING
bool "Profiling support (EXPERIMENTAL)"
help
@@ -22,5 +18,3 @@ config OPROFILE
If unsure, say N.
-endmenu
-
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index 6df7fb60dfea..e79bbc94216d 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -212,10 +212,8 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
* additionally the RTC_SET bit is set to prevent an update cycle.
*/
- while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HWCLK_POLL_INTERVAL);
- }
+ while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP )
+ schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
local_irq_save(flags);
RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index f7f1d2e5b90b..7e54422685cf 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child)
child->thread.work.syscall_trace = 0;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
unsigned long tmp;
int i, ret = 0;
- lock_kernel();
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED) {
- ret = -EPERM;
- goto out;
- }
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- goto out;
- }
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (unlikely(!child)) {
- ret = -ESRCH;
- goto out;
- }
-
- /* you may not mess with init */
- if (unlikely(pid == 1)) {
- ret = -EPERM;
- goto out_tsk;
- }
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+
return ret;
out_eio:
- ret = -EIO;
- goto out_tsk;
+ return -EIO;
}
asmlinkage void syscall_trace(void)
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 8520df9cee6d..b96498120fe9 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -71,6 +71,11 @@ config M5206e
help
Motorola ColdFire 5206e processor support.
+config M520x
+ bool "MCF520x"
+ help
+ Freescale Coldfire 5207/5208 processor support.
+
config M523x
bool "MCF523x"
help
@@ -120,7 +125,7 @@ config M527x
config COLDFIRE
bool
- depends on (M5206 || M5206e || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407)
+ depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407)
default y
choice
@@ -322,6 +327,12 @@ config ELITE
help
Support for the Motorola M5206eLITE board.
+config M5208EVB
+ bool "Freescale M5208EVB board support"
+ depends on M520x
+ help
+ Support for the Freescale Coldfire M5208EVB.
+
config M5235EVB
bool "Freescale M5235EVB support"
depends on M523x
@@ -465,10 +476,10 @@ config ARNEWSH
default y
depends on (ARN5206 || ARN5307)
-config MOTOROLA
+config FREESCALE
bool
default y
- depends on (M5206eC3 || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
+ depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
config HW_FEITH
bool
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index b8fdf191b8f6..b6b5c14e55fd 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -14,6 +14,7 @@ platform-$(CONFIG_M68VZ328) := 68VZ328
platform-$(CONFIG_M68360) := 68360
platform-$(CONFIG_M5206) := 5206
platform-$(CONFIG_M5206e) := 5206e
+platform-$(CONFIG_M520x) := 520x
platform-$(CONFIG_M523x) := 523x
platform-$(CONFIG_M5249) := 5249
platform-$(CONFIG_M527x) := 527x
@@ -29,7 +30,7 @@ board-$(CONFIG_UCDIMM) := ucdimm
board-$(CONFIG_UCQUICC) := uCquicc
board-$(CONFIG_DRAGEN2) := de2
board-$(CONFIG_ARNEWSH) := ARNEWSH
-board-$(CONFIG_MOTOROLA) := MOTOROLA
+board-$(CONFIG_FREESCALE) := FREESCALE
board-$(CONFIG_M5235EVB) := M5235EVB
board-$(CONFIG_M5271EVB) := M5271EVB
board-$(CONFIG_M5275EVB) := M5275EVB
@@ -41,6 +42,7 @@ board-$(CONFIG_SECUREEDGEMP3) := MP3
board-$(CONFIG_CLEOPATRA) := CLEOPATRA
board-$(CONFIG_senTec) := senTec
board-$(CONFIG_SNEHA) := SNEHA
+board-$(CONFIG_M5208EVB) := M5208EVB
board-$(CONFIG_MOD5272) := MOD5272
BOARD := $(board-y)
@@ -56,6 +58,7 @@ MODEL := $(model-y)
#
cpuclass-$(CONFIG_M5206) := 5307
cpuclass-$(CONFIG_M5206e) := 5307
+cpuclass-$(CONFIG_M520x) := 5307
cpuclass-$(CONFIG_M523x) := 5307
cpuclass-$(CONFIG_M5249) := 5307
cpuclass-$(CONFIG_M527x) := 5307
@@ -80,6 +83,7 @@ export PLATFORM BOARD MODEL CPUCLASS
#
cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200
cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200
+cflags-$(CONFIG_M520x) := -m5307 -Wa,-S -Wa,-m5307
cflags-$(CONFIG_M523x) := -m5307 -Wa,-S -Wa,-m5307
cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200
cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307
@@ -95,7 +99,6 @@ cflags-$(CONFIG_M68360) := -m68332
AFLAGS += $(cflags-y)
CFLAGS += $(cflags-y)
-CFLAGS += -fno-builtin
CFLAGS += -O1 -g
CFLAGS += -D__linux__
CFLAGS += -DUTS_SYSNAME=\"uClinux\"
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index cd3ffe12653e..b988c7bdc6e4 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -15,6 +15,7 @@
#include <linux/hardirq.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
+#include <asm/irqnode.h>
#include <asm/thread_info.h>
#define DEFINE(sym, val) \
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 621d7b91ccfe..262ab8c72e5f 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child)
put_reg(child, PT_SR, tmp);
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(truct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -357,10 +324,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
return ret;
}
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index a220345e9746..abb80fa2b940 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -107,6 +107,9 @@ void (*mach_power_off)( void ) = NULL;
#if defined(CONFIG_M5206e)
#define CPU "COLDFIRE(m5206e)"
#endif
+#if defined(CONFIG_M520x)
+ #define CPU "COLDFIRE(m520x)"
+#endif
#if defined(CONFIG_M523x)
#define CPU "COLDFIRE(m523x)"
#endif
@@ -132,7 +135,7 @@ void (*mach_power_off)( void ) = NULL;
#define CPU "COLDFIRE(m5407)"
#endif
#ifndef CPU
- #define CPU "UNKOWN"
+ #define CPU "UNKNOWN"
#endif
/* (es) */
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 47f06787190d..0eab92ca4b97 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -125,6 +125,14 @@
#endif
/*
+ * The Freescale 5208EVB board has 32MB of RAM.
+ */
+#if defined(CONFIG_M5208EVB)
+#define RAM_START 0x40020000
+#define RAM_LENGTH 0x01e00000
+#endif
+
+/*
* The senTec COBRA5272 board has nearly the same memory layout as
* the M5272C3. We assume 16MiB ram.
*/
@@ -275,6 +283,7 @@ SECTIONS {
*(__ksymtab_strings)
/* Built-in module parameters */
+ . = ALIGN(4) ;
__start___param = .;
*(__param)
__stop___param = .;
diff --git a/arch/m68knommu/platform/520x/Makefile b/arch/m68knommu/platform/520x/Makefile
new file mode 100644
index 000000000000..e861b05106bc
--- /dev/null
+++ b/arch/m68knommu/platform/520x/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the M5208 specific file.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this, which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+obj-y := config.o
diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c
new file mode 100644
index 000000000000..71dea2e0f452
--- /dev/null
+++ b/arch/m68knommu/platform/520x/config.c
@@ -0,0 +1,65 @@
+/***************************************************************************/
+
+/*
+ * linux/arch/m68knommu/platform/520x/config.c
+ *
+ * Copyright (C) 2005, Freescale (www.freescale.com)
+ * Copyright (C) 2005, Intec Automation (mike@steroidmicros.com)
+ * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ * Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <asm/machdep.h>
+#include <asm/dma.h>
+
+/***************************************************************************/
+
+/*
+ * DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS];
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
+
+void coldfire_pit_tick(void);
+void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_pit_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+/***************************************************************************/
+
+/*
+ * Program the vector to be an auto-vectored.
+ */
+
+void mcf_autovector(unsigned int vec)
+{
+ /* Everything is auto-vectored on the 520x devices */
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+#ifdef CONFIG_BOOTPARAM
+ strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+ commandp[size-1] = 0;
+#else
+ memset(commandp, 0, size);
+#endif
+
+ mach_sched_init = coldfire_pit_init;
+ mach_tick = coldfire_pit_tick;
+ mach_gettimeoffset = coldfire_pit_offset;
+ mach_trap_init = coldfire_trap_init;
+ mach_reset = coldfire_reset;
+}
+
+/***************************************************************************/
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 6fe5a2b8fb08..8d1619dc1ea6 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -19,6 +19,7 @@ endif
obj-$(CONFIG_COLDFIRE) += entry.o vectors.o ints.o
obj-$(CONFIG_M5206) += timers.o
obj-$(CONFIG_M5206e) += timers.o
+obj-$(CONFIG_M520x) += pit.o
obj-$(CONFIG_M523x) += pit.o
obj-$(CONFIG_M5249) += timers.o
obj-$(CONFIG_M527x) += pit.o
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S
index 7f4ba837901f..c30c462b99b1 100644
--- a/arch/m68knommu/platform/5307/head.S
+++ b/arch/m68knommu/platform/5307/head.S
@@ -113,6 +113,9 @@
#define MEM_BASE 0x02000000
#define VBR_BASE 0x20000000 /* vectors in SRAM */
#endif
+#if defined(CONFIG_M5208EVB)
+#define MEM_BASE 0x40000000
+#endif
#ifndef MEM_BASE
#define MEM_BASE 0x00000000 /* memory base at address 0 */
diff --git a/arch/m68knommu/platform/5307/ints.c b/arch/m68knommu/platform/5307/ints.c
index 0117754d44f3..a134fb2f0566 100644
--- a/arch/m68knommu/platform/5307/ints.c
+++ b/arch/m68knommu/platform/5307/ints.c
@@ -26,6 +26,7 @@
#include <asm/system.h>
#include <asm/irq.h>
+#include <asm/irqnode.h>
#include <asm/traps.h>
#include <asm/page.h>
#include <asm/machdep.h>
diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c
index a9b2c2e7e280..323f2677e49d 100644
--- a/arch/m68knommu/platform/5307/pit.c
+++ b/arch/m68knommu/platform/5307/pit.c
@@ -3,7 +3,7 @@
/*
* pit.c -- Motorola ColdFire PIT timer. Currently this type of
* hardware timer only exists in the Motorola ColdFire
- * 5270/5271 and 5282 CPUs.
+ * 5270/5271, 5282 and other CPUs.
*
* Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
* Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
@@ -47,10 +47,10 @@ void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
MCFINTC_ICR0 + MCFINT_PIT1);
- *icrp = 0x2b; /* PIT1 with level 5, priority 3 */
+ *icrp = ICR_INTRCONF;
- imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH);
- *imrp &= ~(1 << (MCFINT_PIT1 - 32));
+ imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
+ *imrp &= ~MCFPIT_IMR_IBIT;
/* Set up PIT timer 1 as poll clock */
tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
@@ -70,7 +70,7 @@ unsigned long coldfire_pit_offset(void)
unsigned long pmr, pcntr, offset;
tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
- ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IPRH);
+ ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
pmr = *(&tp->pmr);
pcntr = *(&tp->pcntr);
@@ -80,7 +80,7 @@ unsigned long coldfire_pit_offset(void)
* timer interupt is pending, then add on a ticks worth of time.
*/
offset = ((pmr - pcntr) * (1000000 / HZ)) / pmr;
- if ((offset < (1000000 / HZ / 2)) && (*ipr & (1 << (MCFINT_PIT1 - 32))))
+ if ((offset < (1000000 / HZ / 2)) && (*ipr & MCFPIT_IMR_IBIT))
offset += 1000000 / HZ;
return offset;
}
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f1b0f3e1f95b..510da5fda567 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -174,51 +174,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data)
return 0;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret;
-#if 0
- printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
- (int) request, (int) pid, (unsigned long) addr,
- (unsigned long) data);
-#endif
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- if ((ret = security_ptrace(current->parent, current)))
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -319,7 +278,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
if (!cpu_has_dsp) {
tmp = 0;
ret = -EIO;
- goto out_tsk;
+ goto out;
}
if (child->thread.dsp.used_dsp) {
dregs = __get_dsp_regs(child);
@@ -333,14 +292,14 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
if (!cpu_has_dsp) {
tmp = 0;
ret = -EIO;
- goto out_tsk;
+ goto out;
}
tmp = child->thread.dsp.dspcontrol;
break;
default:
tmp = 0;
ret = -EIO;
- goto out_tsk;
+ goto out;
}
ret = put_user(tmp, (unsigned long __user *) data);
break;
@@ -495,11 +454,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+ out:
return ret;
}
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 18130c3748f3..b6fe202a620d 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -78,52 +78,13 @@ void ptrace_disable(struct task_struct *child)
pa_psw(child)->l = 0;
}
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
long ret;
#ifdef DEBUG_PTRACE
long oaddr=addr, odata=data;
#endif
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
-
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
-
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
-
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
- ret = -EPERM;
- if (pid == 1) /* no messing around with init! */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
@@ -383,11 +344,11 @@ long sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_GETEVENTMSG:
ret = put_user(child->ptrace_message, (unsigned int __user *) data);
- goto out_tsk;
+ goto out;
default:
ret = ptrace_request(child, request, addr, data);
- goto out_tsk;
+ goto out;
}
out_wake_notrap:
@@ -396,10 +357,7 @@ out_wake:
wake_up_process(child);
ret = 0;
out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
- DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
+ DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
request, pid, oaddr, odata, ret);
return ret;
}
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ca7acb0c79f0..6ffae2d2b3fa 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -605,6 +605,7 @@ config NODES_SPAN_OTHER_NODES
config PPC_64K_PAGES
bool "64k page size"
+ depends on PPC64
help
This option changes the kernel logical page size to 64k. On machines
without processor support for 64k pages, the kernel will simulate
@@ -916,8 +917,21 @@ source "arch/powerpc/platforms/iseries/Kconfig"
source "lib/Kconfig"
+menu "Instrumentation Support"
+ depends on EXPERIMENTAL
+
source "arch/powerpc/oprofile/Kconfig"
+config KPROBES
+ bool "Kprobes (EXPERIMENTAL)"
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+endmenu
+
source "arch/powerpc/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 0baf64ec80d0..30a30bf559ea 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -9,16 +9,6 @@ config DEBUG_STACKOVERFLOW
This option will cause messages to be printed if free stack space
drops below a certain limit.
-config KPROBES
- bool "Kprobes"
- depends on DEBUG_KERNEL && PPC64
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
config DEBUG_STACK_USAGE
bool "Stack utilization instrumentation"
depends on DEBUG_KERNEL && PPC64
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 33c63bcf69f8..cc4e9eb1c13f 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -929,6 +929,16 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
},
+ { /* 440SPe Rev. A */
+ .pvr_mask = 0xff000fff,
+ .pvr_value = 0x53000890,
+ .cpu_name = "440SPe Rev. A",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
#endif /* CONFIG_44x */
#ifdef CONFIG_FSL_BOOKE
{ /* e200z5 */
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 568ea335d616..3d2abd95c7ae 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -248,46 +248,10 @@ void ptrace_disable(struct task_struct *child)
clear_single_step(child);
}
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret = -EPERM;
- lock_kernel();
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -540,10 +504,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+
return ret;
}
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 6996a593dcb3..b1c89bc4bf90 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -69,6 +69,7 @@
#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/hv_call_xm.h>
#endif
+#include <asm/smp.h>
/* keep track of when we need to update the rtc */
time_t last_rtc_update;
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index b2f3dbca6952..f15dfb92dec0 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -329,12 +329,14 @@ static void __init htab_init_page_sizes(void)
*/
if (mmu_psize_defs[MMU_PAGE_16M].shift)
mmu_huge_psize = MMU_PAGE_16M;
+ /* With 4k/4level pagetables, we can't (for now) cope with a
+ * huge page size < PMD_SIZE */
else if (mmu_psize_defs[MMU_PAGE_1M].shift)
mmu_huge_psize = MMU_PAGE_1M;
/* Calculate HPAGE_SHIFT and sanity check it */
- if (mmu_psize_defs[mmu_huge_psize].shift > 16 &&
- mmu_psize_defs[mmu_huge_psize].shift < 28)
+ if (mmu_psize_defs[mmu_huge_psize].shift > MIN_HUGEPTE_SHIFT &&
+ mmu_psize_defs[mmu_huge_psize].shift < SID_SHIFT)
HPAGE_SHIFT = mmu_psize_defs[mmu_huge_psize].shift;
else
HPAGE_SHIFT = 0; /* No huge pages dude ! */
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0073a04047e4..426c269e552e 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -212,6 +212,12 @@ static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
BUG_ON(area >= NUM_HIGH_AREAS);
+ /* Hack, so that each addresses is controlled by exactly one
+ * of the high or low area bitmaps, the first high area starts
+ * at 4GB, not 0 */
+ if (start == 0)
+ start = 0x100000000UL;
+
/* Check no VMAs are in the region */
vma = find_vma(mm, start);
if (vma && (vma->vm_start < end))
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index d137abd241ff..ed7fcfe5fd37 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -188,9 +188,9 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
if (Hash == 0)
return;
- pmd = pmd_offset(pgd_offset(vma->vm_mm, address), address);
+ pmd = pmd_offset(pgd_offset(mm, ea), ea);
if (!pmd_none(*pmd))
- add_hash_page(vma->vm_mm->context, address, pmd_val(*pmd));
+ add_hash_page(mm->context, ea, pmd_val(*pmd));
}
/*
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index 3e18241b6f35..950ffc5848c7 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -80,12 +80,17 @@ _GLOBAL(slb_miss_kernel_load_virtual)
BEGIN_FTR_SECTION
b 1f
END_FTR_SECTION_IFCLR(CPU_FTR_16M_PAGE)
+ cmpldi r10,16
+
+ lhz r9,PACALOWHTLBAREAS(r13)
+ mr r11,r10
+ blt 5f
+
lhz r9,PACAHIGHHTLBAREAS(r13)
srdi r11,r10,(HTLB_AREA_SHIFT-SID_SHIFT)
- srd r9,r9,r11
- lhz r11,PACALOWHTLBAREAS(r13)
- srd r11,r11,r10
- or. r9,r9,r11
+
+5: srd r9,r9,r11
+ andi. r9,r9,1
beq 1f
_GLOBAL(slb_miss_user_load_huge)
li r11,0
diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig
index 19d37730b664..eb2dece76a54 100644
--- a/arch/powerpc/oprofile/Kconfig
+++ b/arch/powerpc/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
config PROFILING
bool "Profiling support (EXPERIMENTAL)"
help
@@ -19,5 +15,3 @@ config OPROFILE
If unsure, say N.
-endmenu
-
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 58c61219d08e..d7d400339458 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -286,10 +286,8 @@ static struct property *new_property(const char *name, const int length,
return new;
cleanup:
- if (new->name)
- kfree(new->name);
- if (new->value)
- kfree(new->value);
+ kfree(new->name);
+ kfree(new->value);
kfree(new);
return NULL;
}
diff --git a/arch/ppc/4xx_io/serial_sicc.c b/arch/ppc/4xx_io/serial_sicc.c
index e95c48d57571..84d96b857e4a 100644
--- a/arch/ppc/4xx_io/serial_sicc.c
+++ b/arch/ppc/4xx_io/serial_sicc.c
@@ -1145,8 +1145,8 @@ static int set_serial_info(struct SICC_info *info,
info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
(info->flags & ASYNC_INTERNAL_FLAGS));
state->custom_divisor = new_serial.custom_divisor;
- state->close_delay = new_serial.close_delay * HZ / 100;
- state->closing_wait = new_serial.closing_wait * HZ / 100;
+ state->close_delay = msecs_to_jiffies(10 * new_serial.close_delay);
+ state->closing_wait = msecs_to_jiffies(10 * new_serial.closing_wait);
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
port->fifosize = new_serial.xmit_fifo_size;
@@ -1465,10 +1465,8 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
info->event = 0;
info->tty = NULL;
if (info->blocked_open) {
- if (info->state->close_delay) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->state->close_delay);
- }
+ if (info->state->close_delay)
+ schedule_timeout_interruptible(info->state->close_delay);
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -1496,7 +1494,7 @@ static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
* Note: we have to use pretty tight timings here to satisfy
* the NIST-PCTS.
*/
- char_time = (info->timeout - HZ/50) / info->port->fifosize;
+ char_time = (info->timeout - msecs_to_jiffies(20)) / info->port->fifosize;
char_time = char_time / 5;
if (char_time == 0)
char_time = 1;
@@ -1521,8 +1519,7 @@ static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
tty->index, jiffies,
expire, char_time);
while ((readb(info->port->uart_base + BL_SICC_LSR) & _LSR_TX_ALL) != _LSR_TX_ALL) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
+ schedule_timeout_interruptible(char_time);
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, expire))
@@ -1773,7 +1770,7 @@ int __init siccuart_init(void)
for (i = 0; i < SERIAL_SICC_NR; i++) {
struct SICC_state *state = sicc_state + i;
state->line = i;
- state->close_delay = 5 * HZ / 10;
+ state->close_delay = msecs_to_jiffies(500);
state->closing_wait = 30 * HZ;
spin_lock_init(&state->sicc_lock);
}
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index 2086c6ad1147..4edeede9ccfd 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -1309,8 +1309,7 @@ static void mii_dm9161_wait(uint mii_reg, struct net_device *dev)
/* Davicom takes a bit to come up after a reset,
* so wait here for a bit */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(timeout);
+ schedule_timeout_uninterruptible(timeout);
}
static phy_info_t phy_info_dm9161 = {
diff --git a/arch/ppc/8xx_io/cs4218_tdm.c b/arch/ppc/8xx_io/cs4218_tdm.c
index 532caa388dc2..49eb2a7e65c0 100644
--- a/arch/ppc/8xx_io/cs4218_tdm.c
+++ b/arch/ppc/8xx_io/cs4218_tdm.c
@@ -1013,8 +1013,7 @@ static void CS_IrqCleanup(void)
*/
cpm_free_handler(CPMVEC_SMC2);
- if (beep_buf)
- kfree(beep_buf);
+ kfree(beep_buf);
kd_mksound = orig_mksound;
}
#endif /* MODULE */
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 114b90fdea24..8fa51b0a32d2 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -746,6 +746,16 @@ config MPC834x
bool
default y if MPC834x_SYS
+config CPM1
+ bool
+ depends on 8xx
+ default y
+ help
+ The CPM1 (Communications Processor Module) is a coprocessor on
+ embedded CPUs made by Motorola. Selecting this option means that
+ you wish to build a kernel for a machine with a CPM1 coprocessor
+ on it (8xx, 827x, 8560).
+
config CPM2
bool
depends on 8260 || MPC8560 || MPC8555
@@ -1247,6 +1257,14 @@ source "drivers/pci/Kconfig"
source "drivers/pcmcia/Kconfig"
+config RAPIDIO
+ bool "RapidIO support" if MPC8540 || MPC8560
+ help
+ If you say Y here, the kernel will include drivers and
+ infrastructure code to support RapidIO interconnect devices.
+
+source "drivers/rapidio/Kconfig"
+
endmenu
menu "Advanced setup"
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index b7bd8f61a4ad..82df88b01bbe 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -67,6 +67,12 @@ zimageinitrd-$(CONFIG_BAMBOO) := zImage.initrd-TREE
entrypoint-$(CONFIG_BAMBOO) := 0x01000000
extra.o-$(CONFIG_BAMBOO) := pibs.o
+ zimage-$(CONFIG_BUBINGA) := zImage-TREE
+zimageinitrd-$(CONFIG_BUBINGA) := zImage.initrd-TREE
+ end-$(CONFIG_BUBINGA) := bubinga
+ entrypoint-$(CONFIG_BUBINGA) := 0x01000000
+ extra.o-$(CONFIG_BUBINGA) := openbios.o
+
zimage-$(CONFIG_EBONY) := zImage-TREE
zimageinitrd-$(CONFIG_EBONY) := zImage.initrd-TREE
end-$(CONFIG_EBONY) := ebony
@@ -79,12 +85,30 @@ zimageinitrd-$(CONFIG_LUAN) := zImage.initrd-TREE
entrypoint-$(CONFIG_LUAN) := 0x01000000
extra.o-$(CONFIG_LUAN) := pibs.o
+ zimage-$(CONFIG_YUCCA) := zImage-TREE
+zimageinitrd-$(CONFIG_YUCCA) := zImage.initrd-TREE
+ end-$(CONFIG_YUCCA) := yucca
+ entrypoint-$(CONFIG_YUCCA) := 0x01000000
+ extra.o-$(CONFIG_YUCCA) := pibs.o
+
zimage-$(CONFIG_OCOTEA) := zImage-TREE
zimageinitrd-$(CONFIG_OCOTEA) := zImage.initrd-TREE
end-$(CONFIG_OCOTEA) := ocotea
entrypoint-$(CONFIG_OCOTEA) := 0x01000000
extra.o-$(CONFIG_OCOTEA) := pibs.o
+ zimage-$(CONFIG_SYCAMORE) := zImage-TREE
+zimageinitrd-$(CONFIG_SYCAMORE) := zImage.initrd-TREE
+ end-$(CONFIG_SYCAMORE) := sycamore
+ entrypoint-$(CONFIG_SYCAMORE) := 0x01000000
+ extra.o-$(CONFIG_SYCAMORE) := openbios.o
+
+ zimage-$(CONFIG_WALNUT) := zImage-TREE
+zimageinitrd-$(CONFIG_WALNUT) := zImage.initrd-TREE
+ end-$(CONFIG_WALNUT) := walnut
+ entrypoint-$(CONFIG_WALNUT) := 0x01000000
+ extra.o-$(CONFIG_WALNUT) := openbios.o
+
extra.o-$(CONFIG_EV64260) := misc-ev64260.o
end-$(CONFIG_EV64260) := ev64260
cacheflag-$(CONFIG_EV64260) := -include $(clear_L2_L3)
@@ -162,7 +186,8 @@ OBJCOPY_ARGS := -O elf32-powerpc
# head.o and relocate.o must be at the start.
boot-y := head.o relocate.o $(extra.o-y) $(misc-y)
-boot-$(CONFIG_40x) += embed_config.o
+boot-$(CONFIG_REDWOOD_5) += embed_config.o
+boot-$(CONFIG_REDWOOD_6) += embed_config.o
boot-$(CONFIG_8xx) += embed_config.o
boot-$(CONFIG_8260) += embed_config.o
boot-$(CONFIG_BSEIP) += iic.o
diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
index e02de5b467a4..f415d6c62362 100644
--- a/arch/ppc/boot/simple/misc.c
+++ b/arch/ppc/boot/simple/misc.c
@@ -23,7 +23,7 @@
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/bootinfo.h>
-#ifdef CONFIG_44x
+#ifdef CONFIG_4xx
#include <asm/ibm4xx.h>
#endif
#include <asm/reg.h>
@@ -88,6 +88,14 @@ get_mem_size(void)
return 0;
}
+#if defined(CONFIG_40x)
+#define PPC4xx_EMAC0_MR0 EMAC0_BASE
+#endif
+
+#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0)
+#define PPC4xx_EMAC0_MR0 PPC44x_EMAC0_MR0
+#endif
+
struct bi_record *
decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
{
@@ -103,13 +111,13 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
com_port = serial_init(0, NULL);
#endif
-#if defined(CONFIG_44x) && defined(PPC44x_EMAC0_MR0)
+#if defined(PPC4xx_EMAC0_MR0)
/* Reset MAL */
mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR);
/* Wait for reset */
while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {};
/* Reset EMAC */
- *(volatile unsigned long *)PPC44x_EMAC0_MR0 = 0x20000000;
+ *(volatile unsigned long *)PPC4xx_EMAC0_MR0 = 0x20000000;
__asm__ __volatile__("eieio");
#endif
@@ -164,7 +172,9 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n");
}
+#ifndef CONFIG_40x /* don't overwrite the 40x image located at 0x00400000! */
avail_ram = (char *)0x00400000;
+#endif
end_avail = (char *)0x00800000;
puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
puthex((unsigned long)end_avail); puts("\n");
diff --git a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c
index c732b6d70cfb..81f11d8b30a7 100644
--- a/arch/ppc/boot/simple/openbios.c
+++ b/arch/ppc/boot/simple/openbios.c
@@ -1,19 +1,43 @@
/*
* arch/ppc/boot/simple/openbios.c
*
- * 2005 (c) SYSGO AG - g.jaeger@sysgo.com
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ * 2005 (c) SYSGO AG - g.jaeger@sysgo.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.
*
- * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista)
*/
#include <linux/types.h>
#include <linux/config.h>
#include <linux/string.h>
#include <asm/ppcboot.h>
-#include <platforms/4xx/ebony.h>
+#include <asm/ibm4xx.h>
+#include <asm/reg.h>
+#ifdef CONFIG_40x
+#include <asm/io.h>
+#endif
+
+#if defined(CONFIG_BUBINGA)
+#define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */
+#else
+#define BOARD_INFO_VECTOR 0xFFFE0B50
+#endif
+
+#ifdef CONFIG_40x
+/* Supply a default Ethernet address for those eval boards that don't
+ * ship with one. This is an address from the MBX board I have, so
+ * it is unlikely you will find it on your network.
+ */
+static ushort def_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+extern unsigned long timebase_period_ns;
+#endif /* CONFIG_40x */
extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
unsigned long cksum);
@@ -23,15 +47,85 @@ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
bd_t *hold_residual = &hold_resid_buf;
+typedef struct openbios_board_info {
+ unsigned char bi_s_version[4]; /* Version of this structure */
+ unsigned char bi_r_version[30]; /* Version of the IBM ROM */
+ unsigned int bi_memsize; /* DRAM installed, in bytes */
+#ifdef CONFIG_405EP
+ unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */
+#else /* CONFIG_405EP */
+ unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
+#endif /* CONFIG_405EP */
+ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
+ unsigned int bi_intfreq; /* Processor speed, in Hz */
+ unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
+ unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
+#ifdef CONFIG_405EP
+ unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */
+ unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */
+#endif /* CONFIG_405EP */
+} openbios_bd_t;
+
void *
load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
void *ign1, void *ign2)
{
- decompress_kernel(load_addr, num_words, cksum);
+#ifdef CONFIG_40x
+ openbios_bd_t *openbios_bd = NULL;
+ openbios_bd_t *(*get_board_info)(void) =
+ (openbios_bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
+
+ /*
+ * On 40x platforms we not only need the MAC-addresses, but also the
+ * clocks and memsize. Now try to get all values using the OpenBIOS
+ * "get_board_info()" callback.
+ */
+ if ((openbios_bd = get_board_info()) != NULL) {
+ /*
+ * Copy bd_info from OpenBIOS struct into U-Boot struct
+ * used by kernel
+ */
+ hold_residual->bi_memsize = openbios_bd->bi_memsize;
+ hold_residual->bi_intfreq = openbios_bd->bi_intfreq;
+ hold_residual->bi_busfreq = openbios_bd->bi_busfreq;
+ hold_residual->bi_pci_busfreq = openbios_bd->bi_pci_busfreq;
+ memcpy(hold_residual->bi_pci_enetaddr, openbios_bd->bi_pci_enetaddr, 6);
+#ifdef CONFIG_405EP
+ memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr[0], 6);
+ memcpy(hold_residual->bi_enet1addr, openbios_bd->bi_enetaddr[1], 6);
+ hold_residual->bi_opbfreq = openbios_bd->bi_opb_busfreq;
+ hold_residual->bi_procfreq = openbios_bd->bi_pllouta_freq;
+#else /* CONFIG_405EP */
+ memcpy(hold_residual->bi_enetaddr, openbios_bd->bi_enetaddr, 6);
+#endif /* CONFIG_405EP */
+ } else {
+ /* Hmmm...better try to stuff some defaults.
+ */
+ hold_residual->bi_memsize = 16 * 1024 * 1024;
+ hold_residual->bi_intfreq = 200000000;
+ hold_residual->bi_busfreq = 100000000;
+ hold_residual->bi_pci_busfreq = 66666666;
+
+ /*
+ * Only supply one mac-address in this fallback
+ */
+ memcpy(hold_residual->bi_enetaddr, (void *)def_enet_addr, 6);
+#ifdef CONFIG_405EP
+ hold_residual->bi_opbfreq = 50000000;
+ hold_residual->bi_procfreq = 200000000;
+#endif /* CONFIG_405EP */
+ }
+ timebase_period_ns = 1000000000 / hold_residual->bi_intfreq;
+#endif /* CONFIG_40x */
+
+#ifdef CONFIG_440GP
/* simply copy the MAC addresses */
- memcpy(hold_residual->bi_enetaddr, (char *)EBONY_OPENBIOS_MAC_BASE, 6);
- memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6);
+ memcpy(hold_residual->bi_enetaddr, (char *)OPENBIOS_MAC_BASE, 6);
+ memcpy(hold_residual->bi_enet1addr, (char *)(OPENBIOS_MAC_BASE+OPENBIOS_MAC_OFFSET), 6);
+#endif /* CONFIG_440GP */
+
+ decompress_kernel(load_addr, num_words, cksum);
return (void *)hold_residual;
}
diff --git a/arch/ppc/configs/ev64360_defconfig b/arch/ppc/configs/ev64360_defconfig
index de9bbb791db9..d471e578dcb5 100644
--- a/arch/ppc/configs/ev64360_defconfig
+++ b/arch/ppc/configs/ev64360_defconfig
@@ -1,17 +1,17 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc5
-# Fri Aug 5 15:18:23 2005
+# Linux kernel version: 2.6.14
+# Fri Oct 28 19:15:34 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_HAVE_DEC_LOCK=y
CONFIG_PPC=y
CONFIG_PPC32=y
CONFIG_GENERIC_NVRAM=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
#
# Code maturity level options
@@ -26,6 +26,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
# General setup
#
CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
@@ -35,6 +36,7 @@ CONFIG_SYSCTL=y
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -74,7 +76,7 @@ CONFIG_TAU=y
# CONFIG_TAU_AVERAGE is not set
# CONFIG_KEXEC is not set
# CONFIG_CPU_FREQ is not set
-# CONFIG_PM is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
CONFIG_PPC_STD_MMU=y
CONFIG_NOT_COHERENT_CACHE=y
@@ -86,22 +88,18 @@ CONFIG_NOT_COHERENT_CACHE=y
# CONFIG_KATANA is not set
# CONFIG_WILLOW is not set
# CONFIG_CPCI690 is not set
-# CONFIG_PCORE is not set
# CONFIG_POWERPMC250 is not set
# CONFIG_CHESTNUT is not set
# CONFIG_SPRUCE is not set
# CONFIG_HDPU is not set
# CONFIG_EV64260 is not set
# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
# CONFIG_PPLUS is not set
# CONFIG_PRPMC750 is not set
# CONFIG_PRPMC800 is not set
# CONFIG_SANDPOINT is not set
# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
# CONFIG_EST8260 is not set
@@ -138,10 +136,13 @@ CONFIG_FLATMEM_MANUAL=y
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="console=ttyMM0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2"
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
CONFIG_SECCOMP=y
CONFIG_ISA_DMA_API=y
@@ -152,7 +153,6 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_LEGACY_PROC is not set
-# CONFIG_PCI_NAMES is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -206,14 +206,19 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_BIC=y
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
# SCTP Configuration (EXPERIMENTAL)
#
# CONFIG_IP_SCTP is not set
@@ -239,6 +244,7 @@ CONFIG_TCP_CONG_BIC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
#
# Device Drivers
@@ -252,6 +258,11 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
@@ -358,7 +369,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
# CONFIG_LBD is not set
# CONFIG_CDROM_PKTCDVD is not set
@@ -379,6 +389,7 @@ CONFIG_IOSCHED_CFQ=y
#
# SCSI device support
#
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
#
@@ -420,6 +431,10 @@ CONFIG_NETDEVICES=y
# CONFIG_ARCNET is not set
#
+# PHY device support
+#
+
+#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
@@ -434,6 +449,7 @@ CONFIG_NETDEVICES=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
@@ -446,6 +462,7 @@ CONFIG_MV643XX_ETH_0=y
#
# Ethernet (10000 Mbit)
#
+# CONFIG_CHELSIO_T1 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
@@ -547,7 +564,20 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Watchdog Cards
#
-# CONFIG_WATCHDOG is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_MV64X60_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
@@ -571,7 +601,6 @@ CONFIG_GEN_RTC=y
# I2C support
#
# CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
#
# Dallas's 1-wire bus
@@ -582,6 +611,7 @@ CONFIG_GEN_RTC=y
# Hardware Monitoring support
#
CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -589,6 +619,10 @@ CONFIG_HWMON=y
#
#
+# Multimedia Capabilities Port drivers
+#
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -651,10 +685,6 @@ CONFIG_EXT2_FS=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -663,6 +693,7 @@ CONFIG_INOTIFY=y
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -683,11 +714,10 @@ CONFIG_DNOTIFY=y
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_SYSFS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
#
# Miscellaneous filesystems
@@ -735,6 +765,7 @@ CONFIG_SUNRPC=y
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
#
# Partition Types
@@ -751,6 +782,7 @@ CONFIG_MSDOS_PARTITION=y
# Library routines
#
# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
@@ -767,6 +799,7 @@ CONFIG_ZLIB_DEFLATE=y
# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SERIAL_TEXT_DEBUG is not set
#
# Security options
diff --git a/arch/ppc/configs/stx_gp3_defconfig b/arch/ppc/configs/stx_gp3_defconfig
index 66dae8367659..3fedc43e44ad 100644
--- a/arch/ppc/configs/stx_gp3_defconfig
+++ b/arch/ppc/configs/stx_gp3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Wed Jan 26 14:32:58 2005
+# Linux kernel version: 2.6.12-rc4
+# Tue May 24 18:11:04 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
@@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y
CONFIG_PPC=y
CONFIG_PPC32=y
CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
#
# Code maturity level options
@@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -29,7 +31,6 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
@@ -37,6 +38,9 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -46,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -69,9 +74,11 @@ CONFIG_KMOD=y
CONFIG_E500=y
CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
# CONFIG_SPE is not set
CONFIG_MATH_EMULATION=y
# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
CONFIG_85xx=y
CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -96,6 +103,7 @@ CONFIG_HIGHMEM=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
#
# Bus options
@@ -104,15 +112,15 @@ CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PC-card bridges
-#
+CONFIG_RAPIDIO=y
+CONFIG_RAPIDIO_8_BIT_TRANSPORT=y
+CONFIG_RAPIDIO_DISC_TIMEOUT=30
#
# Advanced setup
@@ -152,7 +160,7 @@ CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
# CONFIG_PARPORT_1284 is not set
#
@@ -264,7 +272,6 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
@@ -274,7 +281,6 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_IMM is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA2XXX=m
@@ -283,6 +289,7 @@ CONFIG_SCSI_QLA2XXX=m
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
@@ -322,7 +329,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -431,7 +437,7 @@ CONFIG_IP_NF_NAT_FTP=m
#
# Network testing
#
-# CONFIG_NET_PKTGEN is not set
+CONFIG_NET_PKTGEN=y
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_HAMRADIO is not set
@@ -499,6 +505,7 @@ CONFIG_GFAR_NAPI=y
# Wan interfaces
#
# CONFIG_WAN is not set
+CONFIG_RIONET=y
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PLIP is not set
@@ -536,20 +543,6 @@ CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -567,6 +560,19 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -590,6 +596,7 @@ CONFIG_SERIAL_CPM_SCC2=y
# CONFIG_SERIAL_CPM_SCC4 is not set
# CONFIG_SERIAL_CPM_SMC1 is not set
# CONFIG_SERIAL_CPM_SMC2 is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -626,6 +633,11 @@ CONFIG_DRM=m
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=m
@@ -648,12 +660,12 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
@@ -677,7 +689,9 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -688,9 +702,11 @@ CONFIG_I2C_ALGOBIT=m
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -700,10 +716,12 @@ CONFIG_I2C_ALGOBIT=m
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -732,7 +750,6 @@ CONFIG_I2C_ALGOBIT=m
# Graphics support
#
# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -752,13 +769,9 @@ CONFIG_SOUND=m
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
@@ -789,6 +802,10 @@ CONFIG_JBD_DEBUG=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -859,7 +876,6 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -942,8 +958,10 @@ CONFIG_ZLIB_INFLATE=m
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index c610ca933a25..76a55a438f23 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_POWER4) += cpu_setup_power4.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o
obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_RAPIDIO) += rio.o
obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
obj-$(CONFIG_TAU) += temp.o
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 8b49679fad54..677c571aa276 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -190,8 +190,8 @@ skpinv: addi r4,r4,1 /* Increment */
/* xlat fields */
lis r4,UART0_PHYS_IO_BASE@h /* RPN depends on SoC */
-#ifndef CONFIG_440EP
- ori r4,r4,0x0001 /* ERPN is 1 for second 4GB page */
+#ifdef UART0_PHYS_ERPN
+ ori r4,r4,UART0_PHYS_ERPN /* Add ERPN if above 4GB */
#endif
/* attrib fields */
diff --git a/arch/ppc/kernel/rio.c b/arch/ppc/kernel/rio.c
new file mode 100644
index 000000000000..29487fedfc76
--- /dev/null
+++ b/arch/ppc/kernel/rio.c
@@ -0,0 +1,52 @@
+/*
+ * RapidIO PPC32 support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/rio.h>
+
+#include <asm/rio.h>
+
+/**
+ * platform_rio_init - Do platform specific RIO init
+ *
+ * Any platform specific initialization of RapdIO
+ * hardware is done here as well as registration
+ * of any active master ports in the system.
+ */
+void __attribute__ ((weak))
+ platform_rio_init(void)
+{
+ printk(KERN_WARNING "RIO: No platform_rio_init() present\n");
+}
+
+/**
+ * ppc_rio_init - Do PPC32 RIO init
+ *
+ * Calls platform-specific RIO init code and then calls
+ * rio_init_mports() to initialize any master ports that
+ * have been registered with the RIO subsystem.
+ */
+static int __init ppc_rio_init(void)
+{
+ printk(KERN_INFO "RIO: RapidIO init\n");
+
+ /* Platform specific initialization */
+ platform_rio_init();
+
+ /* Enumerate all registered ports */
+ rio_init_mports();
+
+ return 0;
+}
+
+subsys_initcall(ppc_rio_init);
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 76f4476cab44..d8837911bbc6 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -82,6 +82,12 @@ config LUAN
help
This option enables support for the IBM PPC440SP evaluation board.
+config YUCCA
+ bool "Yucca"
+ select WANT_EARLY_SERIAL
+ help
+ This option enables support for the AMCC PPC440SPe evaluation board.
+
config OCOTEA
bool "Ocotea"
select WANT_EARLY_SERIAL
@@ -124,9 +130,14 @@ config 440SP
depends on LUAN
default y
+config 440SPE
+ bool
+ depends on YUCCA
+ default y
+
config 440
bool
- depends on 440GP || 440SP || 440EP
+ depends on 440GP || 440SP || 440SPE || 440EP
default y
config 440A
@@ -158,7 +169,7 @@ config BOOKE
config IBM_OCP
bool
- depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+ depends on ASH || BAMBOO || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || YUCCA || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
default y
config XILINX_OCP
@@ -168,7 +179,7 @@ config XILINX_OCP
config IBM_EMAC4
bool
- depends on 440GX || 440SP
+ depends on 440GX || 440SP || 440SPE
default y
config BIOS_FIXUP
@@ -214,7 +225,7 @@ config EMBEDDEDBOOT
config IBM_OPENBIOS
bool
- depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT
+ depends on ASH || REDWOOD_5 || REDWOOD_6
default y
config PPC4xx_DMA
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile
index 1dd6d7fd6a9a..c9bb61170954 100644
--- a/arch/ppc/platforms/4xx/Makefile
+++ b/arch/ppc/platforms/4xx/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_EBONY) += ebony.o
obj-$(CONFIG_EP405) += ep405.o
obj-$(CONFIG_BUBINGA) += bubinga.o
obj-$(CONFIG_LUAN) += luan.o
+obj-$(CONFIG_YUCCA) += yucca.o
obj-$(CONFIG_OCOTEA) += ocotea.o
obj-$(CONFIG_REDWOOD_5) += redwood5.o
obj-$(CONFIG_REDWOOD_6) += redwood6.o
@@ -22,6 +23,7 @@ obj-$(CONFIG_440EP) += ibm440ep.o
obj-$(CONFIG_440GP) += ibm440gp.o
obj-$(CONFIG_440GX) += ibm440gx.o
obj-$(CONFIG_440SP) += ibm440sp.o
+obj-$(CONFIG_440SPE) += ppc440spe.o
obj-$(CONFIG_405EP) += ibm405ep.o
obj-$(CONFIG_405GPR) += ibm405gpr.o
obj-$(CONFIG_VIRTEX_II_PRO) += virtex-ii_pro.o
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c
index 3678abf86313..8110f55668c5 100644
--- a/arch/ppc/platforms/4xx/bubinga.c
+++ b/arch/ppc/platforms/4xx/bubinga.c
@@ -89,7 +89,7 @@ bubinga_early_serial_map(void)
* by 16.
*/
uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV);
- uart_clock = __res.bi_pllouta_freq / uart_div;
+ uart_clock = __res.bi_procfreq / uart_div;
/* Setup serial port access */
memset(&port, 0, sizeof(port));
diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h
index b1df856f8e22..b5380cfaf5c0 100644
--- a/arch/ppc/platforms/4xx/bubinga.h
+++ b/arch/ppc/platforms/4xx/bubinga.h
@@ -1,52 +1,34 @@
/*
- * Support for IBM PPC 405EP evaluation board (Bubinga).
+ * arch/ppc/platforms/4xx/bubinga.h
*
- * Author: SAW (IBM), derived from walnut.h.
- * Maintained by MontaVista Software <source@mvista.com>
+ * Bubinga board definitions
+ *
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ * SAW (IBM)
+ * 2003 (c) MontaVista Softare Inc.
+ *
+ * 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.
*
- * 2003 (c) MontaVista Softare Inc. 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.
*/
#ifdef __KERNEL__
#ifndef __BUBINGA_H__
#define __BUBINGA_H__
-/* 405EP */
+#include <linux/config.h>
#include <platforms/4xx/ibm405ep.h>
-
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
- unsigned char bi_s_version[4]; /* Version of this structure */
- unsigned char bi_r_version[30]; /* Version of the IBM ROM */
- unsigned int bi_memsize; /* DRAM installed, in bytes */
- unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
- unsigned int bi_intfreq; /* Processor speed, in Hz */
- unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
- unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
- unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */
- unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
+#include <asm/ppcboot.h>
/* Memory map for the Bubinga board.
* Generic 4xx plus RTC.
*/
-extern void *bubinga_rtc_base;
#define BUBINGA_RTC_PADDR ((uint)0xf0000000)
#define BUBINGA_RTC_VADDR BUBINGA_RTC_PADDR
#define BUBINGA_RTC_SIZE ((uint)8*1024)
@@ -58,12 +40,18 @@ extern void *bubinga_rtc_base;
* for typical configurations at various CPU speeds.
* The base baud is calculated as (FWDA / EXT UART DIV / 16)
*/
-#define BASE_BAUD 0
+#define BASE_BAUD 0
-#define BUBINGA_FPGA_BASE 0xF0300000
+/* Flash */
+#define PPC40x_FPGA_BASE 0xF0300000
+#define PPC40x_FPGA_REG_OFFS 1 /* offset to flash map reg */
+#define PPC40x_FLASH_ONBD_N(x) (x & 0x02)
+#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01)
+#define PPC40x_FLASH_LOW 0xFFF00000
+#define PPC40x_FLASH_HIGH 0xFFF80000
+#define PPC40x_FLASH_SIZE 0x80000
-#define PPC4xx_MACHINE_NAME "IBM Bubinga"
+#define PPC4xx_MACHINE_NAME "IBM Bubinga"
-#endif /* !__ASSEMBLY__ */
#endif /* __BUBINGA_H__ */
#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
index d08faa46a0ae..b91ad4272dfe 100644
--- a/arch/ppc/platforms/4xx/ebony.h
+++ b/arch/ppc/platforms/4xx/ebony.h
@@ -24,8 +24,8 @@
#define PPC44x_EMAC0_MR0 0xE0000800
/* Where to find the MAC info */
-#define EBONY_OPENBIOS_MAC_BASE 0xfffffe0c
-#define EBONY_OPENBIOS_MAC_OFFSET 0x0c
+#define OPENBIOS_MAC_BASE 0xfffffe0c
+#define OPENBIOS_MAC_OFFSET 0x0c
/* Default clock rates for Rev. B and Rev. C silicon */
#define EBONY_440GP_RB_SYSCLK 33000000
diff --git a/arch/ppc/platforms/4xx/ppc440spe.c b/arch/ppc/platforms/4xx/ppc440spe.c
new file mode 100644
index 000000000000..6139a0b3393e
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ppc440spe.c
@@ -0,0 +1,148 @@
+/*
+ * arch/ppc/platforms/4xx/ppc440spe.c
+ *
+ * PPC440SPe I/O descriptions
+ *
+ * Roland Dreier <rolandd@cisco.com>
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <platforms/4xx/ppc440spe.h>
+#include <asm/ocp.h>
+#include <asm/ppc4xx_pic.h>
+
+static struct ocp_func_emac_data ppc440spe_emac0_def = {
+ .rgmii_idx = -1, /* No RGMII */
+ .rgmii_mux = -1, /* No RGMII */
+ .zmii_idx = -1, /* No ZMII */
+ .zmii_mux = -1, /* No ZMII */
+ .mal_idx = 0, /* MAL device index */
+ .mal_rx_chan = 0, /* MAL rx channel number */
+ .mal_tx_chan = 0, /* MAL tx channel number */
+ .wol_irq = 61, /* WOL interrupt number */
+ .mdio_idx = -1, /* No shared MDIO */
+ .tah_idx = -1, /* No TAH */
+};
+OCP_SYSFS_EMAC_DATA()
+
+static struct ocp_func_mal_data ppc440spe_mal0_def = {
+ .num_tx_chans = 1, /* Number of TX channels */
+ .num_rx_chans = 1, /* Number of RX channels */
+ .txeob_irq = 38, /* TX End Of Buffer IRQ */
+ .rxeob_irq = 39, /* RX End Of Buffer IRQ */
+ .txde_irq = 34, /* TX Descriptor Error IRQ */
+ .rxde_irq = 35, /* RX Descriptor Error IRQ */
+ .serr_irq = 33, /* MAL System Error IRQ */
+ .dcr_base = DCRN_MAL_BASE /* MAL0_CFG DCR number */
+};
+OCP_SYSFS_MAL_DATA()
+
+static struct ocp_func_iic_data ppc440spe_iic0_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+
+static struct ocp_func_iic_data ppc440spe_iic1_def = {
+ .fast_mode = 0, /* Use standad mode (100Khz) */
+};
+OCP_SYSFS_IIC_DATA()
+
+struct ocp_def core_ocp[] = {
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 0,
+ .paddr = PPC440SPE_UART0_ADDR,
+ .irq = UART0_INT,
+ .pm = IBM_CPM_UART0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 1,
+ .paddr = PPC440SPE_UART1_ADDR,
+ .irq = UART1_INT,
+ .pm = IBM_CPM_UART1,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_16550,
+ .index = 2,
+ .paddr = PPC440SPE_UART2_ADDR,
+ .irq = UART2_INT,
+ .pm = IBM_CPM_UART2,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 0,
+ .paddr = 0x00000004f0000400ULL,
+ .irq = 2,
+ .pm = IBM_CPM_IIC0,
+ .additions = &ppc440spe_iic0_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_IIC,
+ .index = 1,
+ .paddr = 0x00000004f0000500ULL,
+ .irq = 3,
+ .pm = IBM_CPM_IIC1,
+ .additions = &ppc440spe_iic1_def,
+ .show = &ocp_show_iic_data
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_GPIO,
+ .index = 0,
+ .paddr = 0x00000004f0000700ULL,
+ .irq = OCP_IRQ_NA,
+ .pm = IBM_CPM_GPIO0,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_MAL,
+ .paddr = OCP_PADDR_NA,
+ .irq = OCP_IRQ_NA,
+ .pm = OCP_CPM_NA,
+ .additions = &ppc440spe_mal0_def,
+ .show = &ocp_show_mal_data,
+ },
+ { .vendor = OCP_VENDOR_IBM,
+ .function = OCP_FUNC_EMAC,
+ .index = 0,
+ .paddr = 0x00000004f0000800ULL,
+ .irq = 60,
+ .pm = OCP_CPM_NA,
+ .additions = &ppc440spe_emac0_def,
+ .show = &ocp_show_emac_data,
+ },
+ { .vendor = OCP_VENDOR_INVALID
+ }
+};
+
+/* Polarity and triggering settings for internal interrupt sources */
+struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = {
+ { .polarity = 0xffffffff,
+ .triggering = 0x010f0004,
+ .ext_irq_mask = 0x00000000,
+ },
+ { .polarity = 0xffffffff,
+ .triggering = 0x001f8040,
+ .ext_irq_mask = 0x00007c30, /* IRQ6 - IRQ7, IRQ8 - IRQ12 */
+ },
+ { .polarity = 0xffffffff,
+ .triggering = 0x00000000,
+ .ext_irq_mask = 0x000000fc, /* IRQ0 - IRQ5 */
+ },
+ { .polarity = 0xffffffff,
+ .triggering = 0x00000000,
+ .ext_irq_mask = 0x00000000,
+ },
+};
diff --git a/arch/ppc/platforms/4xx/ppc440spe.h b/arch/ppc/platforms/4xx/ppc440spe.h
new file mode 100644
index 000000000000..2216846973b8
--- /dev/null
+++ b/arch/ppc/platforms/4xx/ppc440spe.h
@@ -0,0 +1,66 @@
+/*
+ * arch/ppc/platforms/4xx/ibm440spe.h
+ *
+ * PPC440SPe definitions
+ *
+ * Roland Dreier <rolandd@cisco.com>
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2004-2005 MontaVista Software, Inc.
+ *
+ * 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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC_PLATFORMS_PPC440SPE_H
+#define __PPC_PLATFORMS_PPC440SPE_H
+
+#include <linux/config.h>
+
+#include <asm/ibm44x.h>
+
+/* UART */
+#define PPC440SPE_UART0_ADDR 0x00000004f0000200ULL
+#define PPC440SPE_UART1_ADDR 0x00000004f0000300ULL
+#define PPC440SPE_UART2_ADDR 0x00000004f0000600ULL
+#define UART0_INT 0
+#define UART1_INT 1
+#define UART2_INT 37
+
+/* Clock and Power Management */
+#define IBM_CPM_IIC0 0x80000000 /* IIC interface */
+#define IBM_CPM_IIC1 0x40000000 /* IIC interface */
+#define IBM_CPM_PCI 0x20000000 /* PCI bridge */
+#define IBM_CPM_CPU 0x02000000 /* processor core */
+#define IBM_CPM_DMA 0x01000000 /* DMA controller */
+#define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */
+#define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */
+#define IBM_CPM_EBC 0x00200000 /* External Bux Controller */
+#define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */
+#define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */
+#define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */
+#define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */
+#define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */
+#define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */
+#define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */
+#define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */
+#define IBM_CPM_UART0 0x00000200 /* serial port 0 */
+#define IBM_CPM_UART1 0x00000100 /* serial port 1 */
+#define IBM_CPM_UART2 0x00000100 /* serial port 1 */
+#define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */
+#define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */
+#define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */
+
+#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \
+ | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \
+ | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \
+ | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \
+ | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \
+ | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \
+ | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 )
+#endif /* __PPC_PLATFORMS_PPC440SP_H */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c
index d8019eec4704..281b4a2ffb96 100644
--- a/arch/ppc/platforms/4xx/sycamore.c
+++ b/arch/ppc/platforms/4xx/sycamore.c
@@ -88,9 +88,6 @@ ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
void __init
sycamore_setup_arch(void)
{
-#define SYCAMORE_PS2_BASE 0xF0100000
-#define SYCAMORE_FPGA_BASE 0xF0300000
-
void *fpga_brdc;
unsigned char fpga_brdc_data;
void *fpga_enable;
@@ -100,7 +97,7 @@ sycamore_setup_arch(void)
ppc4xx_setup_arch();
- ibm_ocp_set_emac(0, 1);
+ ibm_ocp_set_emac(0, 0);
kb_data = ioremap(SYCAMORE_PS2_BASE, 8);
if (!kb_data) {
@@ -111,7 +108,7 @@ sycamore_setup_arch(void)
kb_cs = kb_data + 1;
- fpga_status = ioremap(SYCAMORE_FPGA_BASE, 8);
+ fpga_status = ioremap(PPC40x_FPGA_BASE, 8);
if (!fpga_status) {
printk(KERN_CRIT
"sycamore_setup_arch() fpga_status ioremap failed\n");
diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h
index 3e7b4e2c8c57..1cd6c824fd62 100644
--- a/arch/ppc/platforms/4xx/sycamore.h
+++ b/arch/ppc/platforms/4xx/sycamore.h
@@ -1,67 +1,52 @@
/*
* arch/ppc/platforms/4xx/sycamore.h
*
- * Macros, definitions, and data structures specific to the IBM PowerPC
- * 405GPr "Sycamore" evaluation board.
+ * Sycamore board definitions
*
- * Author: Armin Kuster <akuster@mvista.com>
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
+ *
+ * Based on original work by
+ * Armin Kuster <akuster@mvista.com>
+ * 2000 (c) MontaVista, Software, Inc.
+ *
+ * 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.
*
- * 2000 (c) MontaVista, Software, Inc. 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.
*/
#ifdef __KERNEL__
#ifndef __ASM_SYCAMORE_H__
#define __ASM_SYCAMORE_H__
+#include <linux/config.h>
#include <platforms/4xx/ibm405gpr.h>
+#include <asm/ppcboot.h>
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Sycamore" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
- unsigned char bi_s_version[4]; /* Version of this structure */
- unsigned char bi_r_version[30]; /* Version of the IBM ROM */
- unsigned int bi_memsize; /* DRAM installed, in bytes */
- unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
- unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
- unsigned int bi_intfreq; /* Processor speed, in Hz */
- unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
- unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
-
-/* Memory map for the IBM "Sycamore" 405GP evaluation board.
+/* Memory map for the IBM "Sycamore" 405GPr evaluation board.
* Generic 4xx plus RTC.
*/
-extern void *sycamore_rtc_base;
#define SYCAMORE_RTC_PADDR ((uint)0xf0000000)
#define SYCAMORE_RTC_VADDR SYCAMORE_RTC_PADDR
-#define SYCAMORE_RTC_SIZE ((uint)8*1024)
+#define SYCAMORE_RTC_SIZE ((uint)8*1024)
-#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
-#define BASE_BAUD 201600
-#else
#define BASE_BAUD 691200
-#endif
-#define SYCAMORE_PS2_BASE 0xF0100000
-#define SYCAMORE_FPGA_BASE 0xF0300000
+#define SYCAMORE_PS2_BASE 0xF0100000
+
+/* Flash */
+#define PPC40x_FPGA_BASE 0xF0300000
+#define PPC40x_FPGA_REG_OFFS 5 /* offset to flash map reg */
+#define PPC40x_FLASH_ONBD_N(x) (x & 0x02)
+#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01)
+#define PPC40x_FLASH_LOW 0xFFF00000
+#define PPC40x_FLASH_HIGH 0xFFF80000
+#define PPC40x_FLASH_SIZE 0x80000
#define PPC4xx_MACHINE_NAME "IBM Sycamore"
-#endif /* !__ASSEMBLY__ */
#endif /* __ASM_SYCAMORE_H__ */
#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c
index a33eda4b7489..74cb33182d9f 100644
--- a/arch/ppc/platforms/4xx/walnut.c
+++ b/arch/ppc/platforms/4xx/walnut.c
@@ -90,7 +90,7 @@ walnut_setup_arch(void)
kb_cs = kb_data + 1;
- fpga_status = ioremap(WALNUT_FPGA_BASE, 8);
+ fpga_status = ioremap(PPC40x_FPGA_BASE, 8);
if (!fpga_status) {
printk(KERN_CRIT
"walnut_setup_arch() fpga_status ioremap failed\n");
diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h
index 04cfbf3696b9..dcf2691698c0 100644
--- a/arch/ppc/platforms/4xx/walnut.h
+++ b/arch/ppc/platforms/4xx/walnut.h
@@ -1,72 +1,55 @@
/*
* arch/ppc/platforms/4xx/walnut.h
*
- * Macros, definitions, and data structures specific to the IBM PowerPC
- * 405GP "Walnut" evaluation board.
+ * Walnut board definitions
*
- * Authors: Grant Erickson <grant@lcse.umn.edu>, Frank Rowand
- * <frank_rowand@mvista.com>, Debbie Chu <debbie_chu@mvista.com> or
- * source@mvista.com
+ * Copyright (c) 2005 DENX Software Engineering
+ * Stefan Roese <sr@denx.de>
*
- * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * Based on original work by
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ * Frank Rowand <frank_rowand@mvista.com>
+ * Debbie Chu <debbie_chu@mvista.com>
+ * 2000 (c) MontaVista, Software, Inc.
+ *
+ * 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.
*
- * 2000 (c) MontaVista, Software, Inc. 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.
*/
#ifdef __KERNEL__
#ifndef __ASM_WALNUT_H__
#define __ASM_WALNUT_H__
-/* We have a 405GP core */
+#include <linux/config.h>
#include <platforms/4xx/ibm405gp.h>
-
-#ifndef __ASSEMBLY__
-/*
- * Data structure defining board information maintained by the boot
- * ROM on IBM's "Walnut" evaluation board. An effort has been made to
- * keep the field names consistent with the 8xx 'bd_t' board info
- * structures.
- */
-
-typedef struct board_info {
- unsigned char bi_s_version[4]; /* Version of this structure */
- unsigned char bi_r_version[30]; /* Version of the IBM ROM */
- unsigned int bi_memsize; /* DRAM installed, in bytes */
- unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */
- unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */
- unsigned int bi_intfreq; /* Processor speed, in Hz */
- unsigned int bi_busfreq; /* PLB Bus speed, in Hz */
- unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */
-} bd_t;
-
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
+#include <asm/ppcboot.h>
/* Memory map for the IBM "Walnut" 405GP evaluation board.
* Generic 4xx plus RTC.
*/
-extern void *walnut_rtc_base;
#define WALNUT_RTC_PADDR ((uint)0xf0000000)
#define WALNUT_RTC_VADDR WALNUT_RTC_PADDR
#define WALNUT_RTC_SIZE ((uint)8*1024)
-#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
-#define BASE_BAUD 201600
-#else
#define BASE_BAUD 691200
-#endif
#define WALNUT_PS2_BASE 0xF0100000
-#define WALNUT_FPGA_BASE 0xF0300000
+
+/* Flash */
+#define PPC40x_FPGA_BASE 0xF0300000
+#define PPC40x_FPGA_REG_OFFS 5 /* offset to flash map reg */
+#define PPC40x_FLASH_ONBD_N(x) (x & 0x02)
+#define PPC40x_FLASH_SRAM_SEL(x) (x & 0x01)
+#define PPC40x_FLASH_LOW 0xFFF00000
+#define PPC40x_FLASH_HIGH 0xFFF80000
+#define PPC40x_FLASH_SIZE 0x80000
+#define WALNUT_FPGA_BASE PPC40x_FPGA_BASE
#define PPC4xx_MACHINE_NAME "IBM Walnut"
-#endif /* !__ASSEMBLY__ */
#endif /* __ASM_WALNUT_H__ */
#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/4xx/yucca.c b/arch/ppc/platforms/4xx/yucca.c
new file mode 100644
index 000000000000..e60f4bd437ec
--- /dev/null
+++ b/arch/ppc/platforms/4xx/yucca.c
@@ -0,0 +1,395 @@
+/*
+ * arch/ppc/platforms/4xx/yucca.c
+ *
+ * Yucca board specific routines
+ *
+ * Roland Dreier <rolandd@cisco.com> (based on luan.c by Matt Porter)
+ *
+ * Copyright 2004-2005 MontaVista Software Inc.
+ * Copyright (c) 2005 Cisco Systems. 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.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/initrd.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ocp.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
+
+#include <syslib/ibm44x_common.h>
+#include <syslib/ibm440gx_common.h>
+#include <syslib/ibm440sp_common.h>
+#include <syslib/ppc440spe_pcie.h>
+
+extern bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
+
+static void __init
+yucca_calibrate_decr(void)
+{
+ unsigned int freq;
+
+ if (mfspr(SPRN_CCR1) & CCR1_TCS)
+ freq = YUCCA_TMR_CLK;
+ else
+ freq = clocks.cpu;
+
+ ibm44x_calibrate_decr(freq);
+}
+
+static int
+yucca_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: AMCC\n");
+ seq_printf(m, "machine\t\t: PPC440SPe EVB (Yucca)\n");
+
+ return 0;
+}
+
+static enum {
+ HOSE_UNKNOWN,
+ HOSE_PCIX,
+ HOSE_PCIE0,
+ HOSE_PCIE1,
+ HOSE_PCIE2
+} hose_type[4];
+
+static inline int
+yucca_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+ if (hose_type[hose->index] == HOSE_PCIX) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 81, -1, -1, -1 }, /* IDSEL 1 - PCIX0 Slot 0 */
+ };
+ const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else if (hose_type[hose->index] == HOSE_PCIE0) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 96, 97, 98, 99 },
+ };
+ const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else if (hose_type[hose->index] == HOSE_PCIE1) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 100, 101, 102, 103 },
+ };
+ const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ } else if (hose_type[hose->index] == HOSE_PCIE2) {
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 104, 105, 106, 107 },
+ };
+ const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+ }
+ return -1;
+}
+
+static void __init yucca_set_emacdata(void)
+{
+ struct ocp_def *def;
+ struct ocp_func_emac_data *emacdata;
+
+ /* Set phy_map, phy_mode, and mac_addr for the EMAC */
+ def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
+ emacdata = def->additions;
+ emacdata->phy_map = 0x00000001; /* Skip 0x00 */
+ emacdata->phy_mode = PHY_MODE_GMII;
+ memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+}
+
+static int __init yucca_pcie_card_present(int port)
+{
+ void __iomem *pcie_fpga_base;
+ u16 reg;
+
+ pcie_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE);
+ reg = in_be16(pcie_fpga_base + FPGA_REG1C);
+ iounmap(pcie_fpga_base);
+
+ switch(port) {
+ case 0: return !(reg & FPGA_REG1C_PE0_PRSNT);
+ case 1: return !(reg & FPGA_REG1C_PE1_PRSNT);
+ case 2: return !(reg & FPGA_REG1C_PE2_PRSNT);
+ default: return 0;
+ }
+}
+
+/*
+ * For the given slot, set rootpoint mode, send power to the slot,
+ * turn on the green LED and turn off the yellow LED, enable the clock
+ * and turn off reset.
+ */
+static void __init yucca_setup_pcie_fpga_rootpoint(int port)
+{
+ void __iomem *pcie_reg_fpga_base;
+ u16 power, clock, green_led, yellow_led, reset_off, rootpoint, endpoint;
+
+ pcie_reg_fpga_base = ioremap64(YUCCA_FPGA_REG_BASE, YUCCA_FPGA_REG_SIZE);
+
+ switch(port) {
+ case 0:
+ rootpoint = FPGA_REG1C_PE0_ROOTPOINT;
+ endpoint = 0;
+ power = FPGA_REG1A_PE0_PWRON;
+ green_led = FPGA_REG1A_PE0_GLED;
+ clock = FPGA_REG1A_PE0_REFCLK_ENABLE;
+ yellow_led = FPGA_REG1A_PE0_YLED;
+ reset_off = FPGA_REG1C_PE0_PERST;
+ break;
+ case 1:
+ rootpoint = 0;
+ endpoint = FPGA_REG1C_PE1_ENDPOINT;
+ power = FPGA_REG1A_PE1_PWRON;
+ green_led = FPGA_REG1A_PE1_GLED;
+ clock = FPGA_REG1A_PE1_REFCLK_ENABLE;
+ yellow_led = FPGA_REG1A_PE1_YLED;
+ reset_off = FPGA_REG1C_PE1_PERST;
+ break;
+ case 2:
+ rootpoint = 0;
+ endpoint = FPGA_REG1C_PE2_ENDPOINT;
+ power = FPGA_REG1A_PE2_PWRON;
+ green_led = FPGA_REG1A_PE2_GLED;
+ clock = FPGA_REG1A_PE2_REFCLK_ENABLE;
+ yellow_led = FPGA_REG1A_PE2_YLED;
+ reset_off = FPGA_REG1C_PE2_PERST;
+ break;
+
+ default:
+ return;
+ }
+
+ out_be16(pcie_reg_fpga_base + FPGA_REG1A,
+ ~(power | clock | green_led) &
+ (yellow_led | in_be16(pcie_reg_fpga_base + FPGA_REG1A)));
+ out_be16(pcie_reg_fpga_base + FPGA_REG1C,
+ ~(endpoint | reset_off) &
+ (rootpoint | in_be16(pcie_reg_fpga_base + FPGA_REG1C)));
+
+ /*
+ * Leave device in reset for a while after powering on the
+ * slot to give it a chance to initialize.
+ */
+ mdelay(250);
+
+ out_be16(pcie_reg_fpga_base + FPGA_REG1C,
+ reset_off | in_be16(pcie_reg_fpga_base + FPGA_REG1C));
+
+ iounmap(pcie_reg_fpga_base);
+}
+
+static void __init
+yucca_setup_hoses(void)
+{
+ struct pci_controller *hose;
+ char name[20];
+ int i;
+
+ if (0 && ppc440spe_init_pcie()) {
+ printk(KERN_WARNING "PPC440SPe PCI Express initialization failed\n");
+ return;
+ }
+
+ for (i = 0; i <= 2; ++i) {
+ if (!yucca_pcie_card_present(i))
+ continue;
+
+ printk(KERN_INFO "PCIE%d: card present\n", i);
+ yucca_setup_pcie_fpga_rootpoint(i);
+ if (ppc440spe_init_pcie_rootport(i)) {
+ printk(KERN_WARNING "PCIE%d: initialization failed\n", i);
+ continue;
+ }
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return;
+
+ sprintf(name, "PCIE%d host bridge", i);
+ pci_init_resource(&hose->io_resource,
+ YUCCA_PCIX_LOWER_IO,
+ YUCCA_PCIX_UPPER_IO,
+ IORESOURCE_IO,
+ name);
+
+ hose->mem_space.start = YUCCA_PCIE_LOWER_MEM +
+ i * YUCCA_PCIE_MEM_SIZE;
+ hose->mem_space.end = hose->mem_space.start +
+ YUCCA_PCIE_MEM_SIZE - 1;
+
+ pci_init_resource(&hose->mem_resources[0],
+ hose->mem_space.start,
+ hose->mem_space.end,
+ IORESOURCE_MEM,
+ name);
+
+ hose->first_busno = 0;
+ hose->last_busno = 15;
+ hose_type[hose->index] = HOSE_PCIE0 + i;
+
+ ppc440spe_setup_pcie(hose, i);
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+ }
+
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = yucca_map_irq;
+}
+
+TODC_ALLOC();
+
+static void __init
+yucca_early_serial_map(void)
+{
+ struct uart_port port;
+
+ /* Setup ioremapped serial port access */
+ memset(&port, 0, sizeof(port));
+ port.membase = ioremap64(PPC440SPE_UART0_ADDR, 8);
+ port.irq = UART0_INT;
+ port.uartclk = clocks.uart0;
+ port.regshift = 0;
+ port.iotype = SERIAL_IO_MEM;
+ port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
+ port.line = 0;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 0 failed\n");
+ }
+
+ port.membase = ioremap64(PPC440SPE_UART1_ADDR, 8);
+ port.irq = UART1_INT;
+ port.uartclk = clocks.uart1;
+ port.line = 1;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 1 failed\n");
+ }
+
+ port.membase = ioremap64(PPC440SPE_UART2_ADDR, 8);
+ port.irq = UART2_INT;
+ port.uartclk = BASE_BAUD;
+ port.line = 2;
+
+ if (early_serial_setup(&port) != 0) {
+ printk("Early serial init of port 2 failed\n");
+ }
+}
+
+static void __init
+yucca_setup_arch(void)
+{
+ yucca_set_emacdata();
+
+#if !defined(CONFIG_BDI_SWITCH)
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+ * mucking with the debug registers.
+ */
+ mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM));
+#endif
+
+ /*
+ * Determine various clocks.
+ * To be completely correct we should get SysClk
+ * from FPGA, because it can be changed by on-board switches
+ * --ebs
+ */
+ /* 440GX and 440SPe clocking is the same - rd */
+ ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200);
+ ocp_sys_info.opb_bus_freq = clocks.opb;
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000/HZ;
+
+ /* Setup PCIXn host bridges */
+ yucca_setup_hoses();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ yucca_early_serial_map();
+
+ /* Identify the system */
+ printk("Yucca port (Roland Dreier <rolandd@cisco.com>)\n");
+}
+
+void __init platform_init(unsigned long r3, unsigned long r4,
+ unsigned long r5, unsigned long r6, unsigned long r7)
+{
+ ibm44x_platform_init(r3, r4, r5, r6, r7);
+
+ ppc_md.setup_arch = yucca_setup_arch;
+ ppc_md.show_cpuinfo = yucca_show_cpuinfo;
+ ppc_md.find_end_of_memory = ibm440sp_find_end_of_memory;
+ ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */
+
+ ppc_md.calibrate_decr = yucca_calibrate_decr;
+#ifdef CONFIG_KGDB
+ ppc_md.early_serial_map = yucca_early_serial_map;
+#endif
+}
diff --git a/arch/ppc/platforms/4xx/yucca.h b/arch/ppc/platforms/4xx/yucca.h
new file mode 100644
index 000000000000..01a4afea1514
--- /dev/null
+++ b/arch/ppc/platforms/4xx/yucca.h
@@ -0,0 +1,111 @@
+/*
+ * arch/ppc/platforms/4xx/yucca.h
+ *
+ * Yucca board definitions
+ *
+ * Roland Dreier <rolandd@cisco.com> (based on luan.h by Matt Porter)
+ *
+ * Copyright 2004-2005 MontaVista Software Inc.
+ * Copyright (c) 2005 Cisco Systems. 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.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_YUCCA_H__
+#define __ASM_YUCCA_H__
+
+#include <linux/config.h>
+#include <platforms/4xx/ppc440spe.h>
+
+/* F/W TLB mapping used in bootloader glue to reset EMAC */
+#define PPC44x_EMAC0_MR0 0xa0000800
+
+/* Location of MAC addresses in PIBS image */
+#define PIBS_FLASH_BASE 0xffe00000
+#define PIBS_MAC_BASE (PIBS_FLASH_BASE+0x1b0400)
+
+/* External timer clock frequency */
+#define YUCCA_TMR_CLK 25000000
+
+/*
+ * FPGA registers
+ */
+#define YUCCA_FPGA_REG_BASE 0x00000004e2000000ULL
+#define YUCCA_FPGA_REG_SIZE 0x24
+
+#define FPGA_REG1A 0x1a
+
+#define FPGA_REG1A_PE0_GLED 0x8000
+#define FPGA_REG1A_PE1_GLED 0x4000
+#define FPGA_REG1A_PE2_GLED 0x2000
+#define FPGA_REG1A_PE0_YLED 0x1000
+#define FPGA_REG1A_PE1_YLED 0x0800
+#define FPGA_REG1A_PE2_YLED 0x0400
+#define FPGA_REG1A_PE0_PWRON 0x0200
+#define FPGA_REG1A_PE1_PWRON 0x0100
+#define FPGA_REG1A_PE2_PWRON 0x0080
+#define FPGA_REG1A_PE0_REFCLK_ENABLE 0x0040
+#define FPGA_REG1A_PE1_REFCLK_ENABLE 0x0020
+#define FPGA_REG1A_PE2_REFCLK_ENABLE 0x0010
+#define FPGA_REG1A_PE_SPREAD0 0x0008
+#define FPGA_REG1A_PE_SPREAD1 0x0004
+#define FPGA_REG1A_PE_SELSOURCE_0 0x0002
+#define FPGA_REG1A_PE_SELSOURCE_1 0x0001
+
+#define FPGA_REG1C 0x1c
+
+#define FPGA_REG1C_PE0_ROOTPOINT 0x8000
+#define FPGA_REG1C_PE1_ENDPOINT 0x4000
+#define FPGA_REG1C_PE2_ENDPOINT 0x2000
+#define FPGA_REG1C_PE0_PRSNT 0x1000
+#define FPGA_REG1C_PE1_PRSNT 0x0800
+#define FPGA_REG1C_PE2_PRSNT 0x0400
+#define FPGA_REG1C_PE0_WAKE 0x0080
+#define FPGA_REG1C_PE1_WAKE 0x0040
+#define FPGA_REG1C_PE2_WAKE 0x0020
+#define FPGA_REG1C_PE0_PERST 0x0010
+#define FPGA_REG1C_PE1_PERST 0x0008
+#define FPGA_REG1C_PE2_PERST 0x0004
+
+/*
+ * Serial port defines
+ */
+#define RS_TABLE_SIZE 3
+
+/* PIBS defined UART mappings, used before early_serial_setup */
+#define UART0_IO_BASE 0xa0000200
+#define UART1_IO_BASE 0xa0000300
+#define UART2_IO_BASE 0xa0000600
+
+#define BASE_BAUD 11059200
+#define STD_UART_OP(num) \
+ { 0, BASE_BAUD, 0, UART##num##_INT, \
+ (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \
+ iomem_base: (void*)UART##num##_IO_BASE, \
+ io_type: SERIAL_IO_MEM},
+
+#define SERIAL_PORT_DFNS \
+ STD_UART_OP(0) \
+ STD_UART_OP(1) \
+ STD_UART_OP(2)
+
+/* PCI support */
+#define YUCCA_PCIX_LOWER_IO 0x00000000
+#define YUCCA_PCIX_UPPER_IO 0x0000ffff
+#define YUCCA_PCIX_LOWER_MEM 0x80000000
+#define YUCCA_PCIX_UPPER_MEM 0x8fffffff
+#define YUCCA_PCIE_LOWER_MEM 0x90000000
+#define YUCCA_PCIE_MEM_SIZE 0x10000000
+
+#define YUCCA_PCIX_MEM_SIZE 0x10000000
+#define YUCCA_PCIX_MEM_OFFSET 0x00000000
+#define YUCCA_PCIE_MEM_SIZE 0x10000000
+#define YUCCA_PCIE_MEM_OFFSET 0x00000000
+
+#endif /* __ASM_YUCCA_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
index bd3ac0136756..16ad092d8a06 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
@@ -45,6 +45,8 @@
#include <mm/mmu_decl.h>
+#include <syslib/ppc85xx_rio.h>
+
#include <platforms/85xx/mpc85xx_ads_common.h>
#ifndef CONFIG_PCI
@@ -189,3 +191,11 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
}
#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_RAPIDIO
+void platform_rio_init(void)
+{
+ /* 512MB RIO LAW at 0xc0000000 */
+ mpc85xx_rio_setup(0xc0000000, 0x20000000);
+}
+#endif /* CONFIG_RAPIDIO */
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index 1e1b85f8193a..15ce9d070634 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/fsl_devices.h>
#include <linux/interrupt.h>
+#include <linux/rio.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -57,6 +58,7 @@
#include <syslib/cpm2_pic.h>
#include <syslib/ppc85xx_common.h>
+#include <syslib/ppc85xx_rio.h>
unsigned char __res[sizeof(bd_t)];
@@ -273,6 +275,18 @@ int mpc85xx_exclude_device(u_char bus, u_char devfn)
}
#endif /* CONFIG_PCI */
+#ifdef CONFIG_RAPIDIO
+void
+platform_rio_init(void)
+{
+ /*
+ * The STx firmware configures the RapidIO Local Access Window
+ * at 0xc0000000 with a size of 512MB.
+ */
+ mpc85xx_rio_setup(0xc0000000, 0x20000000);
+}
+#endif /* CONFIG_RAPIDIO */
+
void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
index b1324564456e..b9d844f88c2b 100644
--- a/arch/ppc/platforms/ev64360.c
+++ b/arch/ppc/platforms/ev64360.c
@@ -52,6 +52,8 @@ static u32 ev64360_bus_frequency;
unsigned char __res[sizeof(bd_t)];
+TODC_ALLOC();
+
static int __init
ev64360_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
@@ -182,6 +184,9 @@ ev64360_setup_peripherals(void)
EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
+ TODC_INIT(TODC_TYPE_DS1501, 0, 0,
+ ioremap(EV64360_RTC_WINDOW_BASE, EV64360_RTC_WINDOW_SIZE), 8);
+
mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
EV64360_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
@@ -496,6 +501,13 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.power_off = ev64360_power_off;
ppc_md.halt = ev64360_halt;
ppc_md.find_end_of_memory = ev64360_find_end_of_memory;
+ ppc_md.init = NULL;
+
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.nvram_read_val = todc_direct_read_val;
+ ppc_md.nvram_write_val = todc_direct_write_val;
ppc_md.calibrate_decr = ev64360_calibrate_decr;
#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index b4ef15b45c4a..5bd33baac243 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_440EP) += ibm440gx_common.o
obj-$(CONFIG_440GP) += ibm440gp_common.o
obj-$(CONFIG_440GX) += ibm440gx_common.o
obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o
+obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o
ifeq ($(CONFIG_4xx),y)
ifeq ($(CONFIG_VIRTEX_II_PRO),y)
obj-$(CONFIG_40x) += xilinx_pic.o
@@ -32,6 +33,7 @@ obj-$(CONFIG_PPC4xx_DMA) += ppc4xx_dma.o
obj-$(CONFIG_PPC4xx_EDMA) += ppc4xx_sgdma.o
ifeq ($(CONFIG_40x),y)
obj-$(CONFIG_PCI) += pci_auto.o ppc405_pci.o
+obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o
endif
endif
obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
@@ -46,12 +48,14 @@ obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
obj-$(CONFIG_EBONY) += pci_auto.o todc_time.o
obj-$(CONFIG_EV64260) += todc_time.o pci_auto.o
+obj-$(CONFIG_EV64360) += todc_time.o
obj-$(CONFIG_CHESTNUT) += mv64360_pic.o pci_auto.o
obj-$(CONFIG_GEMINI) += open_pic.o
obj-$(CONFIG_GT64260) += gt64260_pic.o
obj-$(CONFIG_LOPEC) += pci_auto.o todc_time.o
obj-$(CONFIG_HDPU) += pci_auto.o
obj-$(CONFIG_LUAN) += pci_auto.o todc_time.o
+obj-$(CONFIG_YUCCA) += pci_auto.o todc_time.o
obj-$(CONFIG_KATANA) += pci_auto.o
obj-$(CONFIG_MV64360) += mv64360_pic.o
obj-$(CONFIG_MV64X60) += mv64x60.o mv64x60_win.o
diff --git a/arch/ppc/syslib/ibm440sp_common.c b/arch/ppc/syslib/ibm440sp_common.c
index 417d4cff77a0..cdafda127d81 100644
--- a/arch/ppc/syslib/ibm440sp_common.c
+++ b/arch/ppc/syslib/ibm440sp_common.c
@@ -1,7 +1,7 @@
/*
* arch/ppc/syslib/ibm440sp_common.c
*
- * PPC440SP system library
+ * PPC440SP/PPC440SPe system library
*
* Matt Porter <mporter@kernel.crashing.org>
* Copyright 2002-2005 MontaVista Software Inc.
@@ -35,7 +35,7 @@ unsigned long __init ibm440sp_find_end_of_memory(void)
u32 mem_size = 0;
/* Read two bank sizes and sum */
- for (i=0; i<2; i++)
+ for (i=0; i< MQ0_NUM_BANKS; i++)
switch (mfdcr(DCRN_MQ0_BS0BAS + i) & MQ0_CONFIG_SIZE_MASK) {
case MQ0_CONFIG_SIZE_8M:
mem_size += PPC44x_MEM_SIZE_8M;
diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
index 5152c8e41340..71db11d22158 100644
--- a/arch/ppc/syslib/ibm44x_common.c
+++ b/arch/ppc/syslib/ibm44x_common.c
@@ -20,6 +20,7 @@
#include <linux/types.h>
#include <linux/serial.h>
#include <linux/module.h>
+#include <linux/initrd.h>
#include <asm/ibm44x.h>
#include <asm/mmu.h>
@@ -214,9 +215,20 @@ void __init ibm44x_platform_init(unsigned long r3, unsigned long r4, unsigned lo
/* Called from machine_check_exception */
void platform_machine_check(struct pt_regs *regs)
{
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+ printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n",
+ mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL),
+ mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESRH),
+ mfdcr(DCRN_PLB0_BESRL));
+ printk("PLB1: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x%08x\n",
+ mfdcr(DCRN_PLB1_BEARH), mfdcr(DCRN_PLB1_BEARL),
+ mfdcr(DCRN_PLB1_ACR), mfdcr(DCRN_PLB1_BESRH),
+ mfdcr(DCRN_PLB1_BESRL));
+#else
printk("PLB0: BEAR=0x%08x%08x ACR= 0x%08x BESR= 0x%08x\n",
mfdcr(DCRN_PLB0_BEARH), mfdcr(DCRN_PLB0_BEARL),
mfdcr(DCRN_PLB0_ACR), mfdcr(DCRN_PLB0_BESR));
+#endif
printk("POB0: BEAR=0x%08x%08x BESR0=0x%08x BESR1=0x%08x\n",
mfdcr(DCRN_POB0_BEARH), mfdcr(DCRN_POB0_BEARL),
mfdcr(DCRN_POB0_BESR0), mfdcr(DCRN_POB0_BESR1));
diff --git a/arch/ppc/syslib/ppc405_pci.c b/arch/ppc/syslib/ppc405_pci.c
index 81c83bf98df4..d6d838b16dac 100644
--- a/arch/ppc/syslib/ppc405_pci.c
+++ b/arch/ppc/syslib/ppc405_pci.c
@@ -89,13 +89,6 @@ ppc4xx_find_bridges(void)
isa_mem_base = 0;
pci_dram_offset = 0;
-#if (PSR_PCI_ARBIT_EN > 1)
- /* Check if running in slave mode */
- if ((mfdcr(DCRN_CHPSR) & PSR_PCI_ARBIT_EN) == 0) {
- printk("Running as PCI slave, kernel PCI disabled !\n");
- return;
- }
-#endif
/* Setup PCI32 hose */
hose_a = pcibios_alloc_controller();
if (!hose_a)
diff --git a/arch/ppc/syslib/ppc440spe_pcie.c b/arch/ppc/syslib/ppc440spe_pcie.c
new file mode 100644
index 000000000000..1509fc1ddfb6
--- /dev/null
+++ b/arch/ppc/syslib/ppc440spe_pcie.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/ibm44x.h>
+
+#include "ppc440spe_pcie.h"
+
+static int
+pcie_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+
+ if (PCI_SLOT(devfn) != 1)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ offset += devfn << 12;
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ switch (len) {
+ case 1:
+ *val = in_8(hose->cfg_data + offset);
+ break;
+ case 2:
+ *val = in_le16(hose->cfg_data + offset);
+ break;
+ default:
+ *val = in_le32(hose->cfg_data + offset);
+ break;
+ }
+
+ if (0) printk("%s: read %x(%d) @ %x\n", __func__, *val, len, offset);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+pcie_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
+ int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+
+ if (PCI_SLOT(devfn) != 1)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ offset += devfn << 12;
+
+ switch (len) {
+ case 1:
+ out_8(hose->cfg_data + offset, val);
+ break;
+ case 2:
+ out_le16(hose->cfg_data + offset, val);
+ break;
+ default:
+ out_le32(hose->cfg_data + offset, val);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pcie_pci_ops =
+{
+ .read = pcie_read_config,
+ .write = pcie_write_config
+};
+
+enum {
+ PTYPE_ENDPOINT = 0x0,
+ PTYPE_LEGACY_ENDPOINT = 0x1,
+ PTYPE_ROOT_PORT = 0x4,
+
+ LNKW_X1 = 0x1,
+ LNKW_X4 = 0x4,
+ LNKW_X8 = 0x8
+};
+
+static void check_error(void)
+{
+ u32 valPE0, valPE1, valPE2;
+
+ /* SDR0_PEGPLLLCT1 reset */
+ if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) {
+ printk(KERN_INFO "PCIE: SDR0_PEGPLLLCT1 reset error 0x%8x\n", valPE0);
+ }
+
+ valPE0 = SDR_READ(PESDR0_RCSSET);
+ valPE1 = SDR_READ(PESDR1_RCSSET);
+ valPE2 = SDR_READ(PESDR2_RCSSET);
+
+ /* SDR0_PExRCSSET rstgu */
+ if ( !(valPE0 & 0x01000000) ||
+ !(valPE1 & 0x01000000) ||
+ !(valPE2 & 0x01000000)) {
+ printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstgu error\n");
+ }
+
+ /* SDR0_PExRCSSET rstdl */
+ if ( !(valPE0 & 0x00010000) ||
+ !(valPE1 & 0x00010000) ||
+ !(valPE2 & 0x00010000)) {
+ printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstdl error\n");
+ }
+
+ /* SDR0_PExRCSSET rstpyn */
+ if ( (valPE0 & 0x00001000) ||
+ (valPE1 & 0x00001000) ||
+ (valPE2 & 0x00001000)) {
+ printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstpyn error\n");
+ }
+
+ /* SDR0_PExRCSSET hldplb */
+ if ( (valPE0 & 0x10000000) ||
+ (valPE1 & 0x10000000) ||
+ (valPE2 & 0x10000000)) {
+ printk(KERN_INFO "PCIE: SDR0_PExRCSSET hldplb error\n");
+ }
+
+ /* SDR0_PExRCSSET rdy */
+ if ( (valPE0 & 0x00100000) ||
+ (valPE1 & 0x00100000) ||
+ (valPE2 & 0x00100000)) {
+ printk(KERN_INFO "PCIE: SDR0_PExRCSSET rdy error\n");
+ }
+
+ /* SDR0_PExRCSSET shutdown */
+ if ( (valPE0 & 0x00000100) ||
+ (valPE1 & 0x00000100) ||
+ (valPE2 & 0x00000100)) {
+ printk(KERN_INFO "PCIE: SDR0_PExRCSSET shutdown error\n");
+ }
+}
+
+/*
+ * Initialize PCI Express core as described in User Manual section 27.12.1
+ */
+int ppc440spe_init_pcie(void)
+{
+ /* Set PLL clock receiver to LVPECL */
+ SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28);
+
+ check_error();
+
+ printk(KERN_INFO "PCIE initialization OK\n");
+
+ if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000))
+ printk(KERN_INFO "PESDR_PLLCT2 resistance calibration failed (0x%08x)\n",
+ SDR_READ(PESDR0_PLLLCT2));
+
+ /* De-assert reset of PCIe PLL, wait for lock */
+ SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24));
+ udelay(3);
+
+ return 0;
+}
+
+int ppc440spe_init_pcie_rootport(int port)
+{
+ static int core_init;
+ void __iomem *utl_base;
+ u32 val = 0;
+ int i;
+
+ if (!core_init) {
+ ++core_init;
+ i = ppc440spe_init_pcie();
+ if (i)
+ return i;
+ }
+
+ /*
+ * Initialize various parts of the PCI Express core for our port:
+ *
+ * - Set as a root port and enable max width
+ * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4).
+ * - Set up UTL configuration.
+ * - Increase SERDES drive strength to levels suggested by AMCC.
+ * - De-assert RSTPYN, RSTDL and RSTGU.
+ */
+ switch (port) {
+ case 0:
+ SDR_WRITE(PESDR0_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12);
+
+ SDR_WRITE(PESDR0_UTLSET1, 0x21222222);
+ SDR_WRITE(PESDR0_UTLSET2, 0x11000000);
+
+ SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000);
+ SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000);
+
+ SDR_WRITE(PESDR0_RCSSET,
+ (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+ break;
+
+ case 1:
+ SDR_WRITE(PESDR1_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
+
+ SDR_WRITE(PESDR1_UTLSET1, 0x21222222);
+ SDR_WRITE(PESDR1_UTLSET2, 0x11000000);
+
+ SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000);
+ SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000);
+ SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000);
+ SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000);
+
+ SDR_WRITE(PESDR1_RCSSET,
+ (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+ break;
+
+ case 2:
+ SDR_WRITE(PESDR2_DLPSET, PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12);
+
+ SDR_WRITE(PESDR2_UTLSET1, 0x21222222);
+ SDR_WRITE(PESDR2_UTLSET2, 0x11000000);
+
+ SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000);
+ SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000);
+ SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000);
+ SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000);
+
+ SDR_WRITE(PESDR2_RCSSET,
+ (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12);
+ break;
+ }
+
+ mdelay(1000);
+
+ switch (port) {
+ case 0: val = SDR_READ(PESDR0_RCSSTS); break;
+ case 1: val = SDR_READ(PESDR1_RCSSTS); break;
+ case 2: val = SDR_READ(PESDR2_RCSSTS); break;
+ }
+
+ if (!(val & (1 << 20)))
+ printk(KERN_INFO "PCIE%d: PGRST inactive\n", port);
+ else
+ printk(KERN_WARNING "PGRST for PCIE%d failed %08x\n", port, val);
+
+ switch (port) {
+ case 0: printk(KERN_INFO "PCIE0: LOOP %08x\n", SDR_READ(PESDR0_LOOP)); break;
+ case 1: printk(KERN_INFO "PCIE1: LOOP %08x\n", SDR_READ(PESDR1_LOOP)); break;
+ case 2: printk(KERN_INFO "PCIE2: LOOP %08x\n", SDR_READ(PESDR2_LOOP)); break;
+ }
+
+ /*
+ * Map UTL registers at 0xc_1000_0n00
+ */
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x10000000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800);
+ break;
+
+ case 1:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x10001000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800);
+ break;
+
+ case 2:
+ mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c);
+ mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x10002000);
+ mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001);
+ mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800);
+ }
+
+ utl_base = ioremap64(0xc10000000ull + 0x1000 * port, 0x100);
+
+ /*
+ * Set buffer allocations and then assert VRB and TXE.
+ */
+ out_be32(utl_base + PEUTL_OUTTR, 0x08000000);
+ out_be32(utl_base + PEUTL_INTR, 0x02000000);
+ out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000);
+ out_be32(utl_base + PEUTL_PBBSZ, 0x53000000);
+ out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000);
+ out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000);
+ out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000);
+ out_be32(utl_base + PEUTL_PCTL, 0x80800066);
+
+ iounmap(utl_base);
+
+ /*
+ * We map PCI Express configuration access into the 512MB regions
+ * PCIE0: 0xc_4000_0000
+ * PCIE1: 0xc_8000_0000
+ * PCIE2: 0xc_c000_0000
+ */
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000);
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */
+ break;
+
+ case 1:
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000);
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */
+ break;
+
+ case 2:
+ mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c);
+ mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000);
+ mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */
+ break;
+ }
+
+ /*
+ * Check for VC0 active and assert RDY.
+ */
+ switch (port) {
+ case 0:
+ if (!(SDR_READ(PESDR0_RCSSTS) & (1 << 16)))
+ printk(KERN_WARNING "PCIE0: VC0 not active\n");
+ SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20);
+ break;
+ case 1:
+ if (!(SDR_READ(PESDR1_RCSSTS) & (1 << 16)))
+ printk(KERN_WARNING "PCIE0: VC0 not active\n");
+ SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20);
+ break;
+ case 2:
+ if (!(SDR_READ(PESDR2_RCSSTS) & (1 << 16)))
+ printk(KERN_WARNING "PCIE0: VC0 not active\n");
+ SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20);
+ break;
+ }
+
+#if 0
+ /* Dump all config regs */
+ for (i = 0x300; i <= 0x320; ++i)
+ printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+ for (i = 0x340; i <= 0x353; ++i)
+ printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+ for (i = 0x370; i <= 0x383; ++i)
+ printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+ for (i = 0x3a0; i <= 0x3a2; ++i)
+ printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+ for (i = 0x3c0; i <= 0x3c3; ++i)
+ printk("[%04x] 0x%08x\n", i, SDR_READ(i));
+#endif
+
+ mdelay(100);
+
+ return 0;
+}
+
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port)
+{
+ void __iomem *mbase;
+
+ /*
+ * Map 16MB, which is enough for 4 bits of bus #
+ */
+ hose->cfg_data = ioremap64(0xc40000000ull + port * 0x40000000,
+ 1 << 24);
+ hose->ops = &pcie_pci_ops;
+
+ /*
+ * Set bus numbers on our root port
+ */
+ mbase = ioremap64(0xc50000000ull + port * 0x40000000, 4096);
+ out_8(mbase + PCI_PRIMARY_BUS, 0);
+ out_8(mbase + PCI_SECONDARY_BUS, 0);
+
+ /*
+ * Set up outbound translation to hose->mem_space from PLB
+ * addresses at an offset of 0xd_0000_0000. We set the low
+ * bits of the mask to 11 to turn off splitting into 8
+ * subregions and to enable the outbound translation.
+ */
+ out_le32(mbase + PECFG_POM0LAH, 0);
+ out_le32(mbase + PECFG_POM0LAL, hose->mem_space.start);
+
+ switch (port) {
+ case 0:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), hose->mem_space.start);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0),
+ ~(hose->mem_space.end - hose->mem_space.start) | 3);
+ break;
+ case 1:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), hose->mem_space.start);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1),
+ ~(hose->mem_space.end - hose->mem_space.start) | 3);
+
+ break;
+ case 2:
+ mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d);
+ mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), hose->mem_space.start);
+ mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff);
+ mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2),
+ ~(hose->mem_space.end - hose->mem_space.start) | 3);
+ break;
+ }
+
+ /* Set up 16GB inbound memory window at 0 */
+ out_le32(mbase + PCI_BASE_ADDRESS_0, 0);
+ out_le32(mbase + PCI_BASE_ADDRESS_1, 0);
+ out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc);
+ out_le32(mbase + PECFG_BAR0LMPA, 0);
+ out_le32(mbase + PECFG_PIM0LAL, 0);
+ out_le32(mbase + PECFG_PIM0LAH, 0);
+ out_le32(mbase + PECFG_PIMEN, 0x1);
+
+ /* Enable I/O, Mem, and Busmaster cycles */
+ out_le16(mbase + PCI_COMMAND,
+ in_le16(mbase + PCI_COMMAND) |
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+ iounmap(mbase);
+}
diff --git a/arch/ppc/syslib/ppc440spe_pcie.h b/arch/ppc/syslib/ppc440spe_pcie.h
new file mode 100644
index 000000000000..55b765ad3272
--- /dev/null
+++ b/arch/ppc/syslib/ppc440spe_pcie.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2005 Cisco Systems. All rights reserved.
+ * Roland Dreier <rolandd@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __PPC_SYSLIB_PPC440SPE_PCIE_H
+#define __PPC_SYSLIB_PPC440SPE_PCIE_H
+
+#define DCRN_SDR0_CFGADDR 0x00e
+#define DCRN_SDR0_CFGDATA 0x00f
+
+#define DCRN_PCIE0_BASE 0x100
+#define DCRN_PCIE1_BASE 0x120
+#define DCRN_PCIE2_BASE 0x140
+#define PCIE0 DCRN_PCIE0_BASE
+#define PCIE1 DCRN_PCIE1_BASE
+#define PCIE2 DCRN_PCIE2_BASE
+
+#define DCRN_PEGPL_CFGBAH(base) (base + 0x00)
+#define DCRN_PEGPL_CFGBAL(base) (base + 0x01)
+#define DCRN_PEGPL_CFGMSK(base) (base + 0x02)
+#define DCRN_PEGPL_MSGBAH(base) (base + 0x03)
+#define DCRN_PEGPL_MSGBAL(base) (base + 0x04)
+#define DCRN_PEGPL_MSGMSK(base) (base + 0x05)
+#define DCRN_PEGPL_OMR1BAH(base) (base + 0x06)
+#define DCRN_PEGPL_OMR1BAL(base) (base + 0x07)
+#define DCRN_PEGPL_OMR1MSKH(base) (base + 0x08)
+#define DCRN_PEGPL_OMR1MSKL(base) (base + 0x09)
+#define DCRN_PEGPL_REGBAH(base) (base + 0x12)
+#define DCRN_PEGPL_REGBAL(base) (base + 0x13)
+#define DCRN_PEGPL_REGMSK(base) (base + 0x14)
+#define DCRN_PEGPL_SPECIAL(base) (base + 0x15)
+
+/*
+ * System DCRs (SDRs)
+ */
+#define PESDR0_PLLLCT1 0x03a0
+#define PESDR0_PLLLCT2 0x03a1
+#define PESDR0_PLLLCT3 0x03a2
+
+#define PESDR0_UTLSET1 0x0300
+#define PESDR0_UTLSET2 0x0301
+#define PESDR0_DLPSET 0x0302
+#define PESDR0_LOOP 0x0303
+#define PESDR0_RCSSET 0x0304
+#define PESDR0_RCSSTS 0x0305
+#define PESDR0_HSSL0SET1 0x0306
+#define PESDR0_HSSL0SET2 0x0307
+#define PESDR0_HSSL0STS 0x0308
+#define PESDR0_HSSL1SET1 0x0309
+#define PESDR0_HSSL1SET2 0x030a
+#define PESDR0_HSSL1STS 0x030b
+#define PESDR0_HSSL2SET1 0x030c
+#define PESDR0_HSSL2SET2 0x030d
+#define PESDR0_HSSL2STS 0x030e
+#define PESDR0_HSSL3SET1 0x030f
+#define PESDR0_HSSL3SET2 0x0310
+#define PESDR0_HSSL3STS 0x0311
+#define PESDR0_HSSL4SET1 0x0312
+#define PESDR0_HSSL4SET2 0x0313
+#define PESDR0_HSSL4STS 0x0314
+#define PESDR0_HSSL5SET1 0x0315
+#define PESDR0_HSSL5SET2 0x0316
+#define PESDR0_HSSL5STS 0x0317
+#define PESDR0_HSSL6SET1 0x0318
+#define PESDR0_HSSL6SET2 0x0319
+#define PESDR0_HSSL6STS 0x031a
+#define PESDR0_HSSL7SET1 0x031b
+#define PESDR0_HSSL7SET2 0x031c
+#define PESDR0_HSSL7STS 0x031d
+#define PESDR0_HSSCTLSET 0x031e
+#define PESDR0_LANE_ABCD 0x031f
+#define PESDR0_LANE_EFGH 0x0320
+
+#define PESDR1_UTLSET1 0x0340
+#define PESDR1_UTLSET2 0x0341
+#define PESDR1_DLPSET 0x0342
+#define PESDR1_LOOP 0x0343
+#define PESDR1_RCSSET 0x0344
+#define PESDR1_RCSSTS 0x0345
+#define PESDR1_HSSL0SET1 0x0346
+#define PESDR1_HSSL0SET2 0x0347
+#define PESDR1_HSSL0STS 0x0348
+#define PESDR1_HSSL1SET1 0x0349
+#define PESDR1_HSSL1SET2 0x034a
+#define PESDR1_HSSL1STS 0x034b
+#define PESDR1_HSSL2SET1 0x034c
+#define PESDR1_HSSL2SET2 0x034d
+#define PESDR1_HSSL2STS 0x034e
+#define PESDR1_HSSL3SET1 0x034f
+#define PESDR1_HSSL3SET2 0x0350
+#define PESDR1_HSSL3STS 0x0351
+#define PESDR1_HSSCTLSET 0x0352
+#define PESDR1_LANE_ABCD 0x0353
+
+#define PESDR2_UTLSET1 0x0370
+#define PESDR2_UTLSET2 0x0371
+#define PESDR2_DLPSET 0x0372
+#define PESDR2_LOOP 0x0373
+#define PESDR2_RCSSET 0x0374
+#define PESDR2_RCSSTS 0x0375
+#define PESDR2_HSSL0SET1 0x0376
+#define PESDR2_HSSL0SET2 0x0377
+#define PESDR2_HSSL0STS 0x0378
+#define PESDR2_HSSL1SET1 0x0379
+#define PESDR2_HSSL1SET2 0x037a
+#define PESDR2_HSSL1STS 0x037b
+#define PESDR2_HSSL2SET1 0x037c
+#define PESDR2_HSSL2SET2 0x037d
+#define PESDR2_HSSL2STS 0x037e
+#define PESDR2_HSSL3SET1 0x037f
+#define PESDR2_HSSL3SET2 0x0380
+#define PESDR2_HSSL3STS 0x0381
+#define PESDR2_HSSCTLSET 0x0382
+#define PESDR2_LANE_ABCD 0x0383
+
+/*
+ * UTL register offsets
+ */
+#define PEUTL_PBBSZ 0x20
+#define PEUTL_OPDBSZ 0x68
+#define PEUTL_IPHBSZ 0x70
+#define PEUTL_IPDBSZ 0x78
+#define PEUTL_OUTTR 0x90
+#define PEUTL_INTR 0x98
+#define PEUTL_PCTL 0xa0
+#define PEUTL_RCIRQEN 0xb8
+
+/*
+ * Config space register offsets
+ */
+#define PECFG_BAR0LMPA 0x210
+#define PECFG_BAR0HMPA 0x214
+#define PECFG_PIMEN 0x33c
+#define PECFG_PIM0LAL 0x340
+#define PECFG_PIM0LAH 0x344
+#define PECFG_POM0LAL 0x380
+#define PECFG_POM0LAH 0x384
+
+int ppc440spe_init_pcie(void);
+int ppc440spe_init_pcie_rootport(int port);
+void ppc440spe_setup_pcie(struct pci_controller *hose, int port);
+
+#endif /* __PPC_SYSLIB_PPC440SPE_PCIE_H */
diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
index 0b435633a0d1..aa4165144ec2 100644
--- a/arch/ppc/syslib/ppc4xx_pic.c
+++ b/arch/ppc/syslib/ppc4xx_pic.c
@@ -38,6 +38,7 @@ extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak));
#define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f)))
#define IRQ_MASK_UIC1(irq) IRQ_MASK_UICx(irq)
#define IRQ_MASK_UIC2(irq) IRQ_MASK_UICx(irq)
+#define IRQ_MASK_UIC3(irq) IRQ_MASK_UICx(irq)
#define UIC_HANDLERS(n) \
static void ppc4xx_uic##n##_enable(unsigned int irq) \
@@ -88,7 +89,38 @@ static void ppc4xx_uic##n##_end(unsigned int irq) \
.end = ppc4xx_uic##n##_end, \
} \
-#if NR_UICS == 3
+#if NR_UICS == 4
+#define ACK_UIC0_PARENT
+#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
+#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC2NC);
+#define ACK_UIC3_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC3NC);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
+UIC_HANDLERS(2);
+UIC_HANDLERS(3);
+
+static int ppc4xx_pic_get_irq(struct pt_regs *regs)
+{
+ u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0));
+ if (uic0 & UIC0_UIC1NC)
+ return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1)));
+ else if (uic0 & UIC0_UIC2NC)
+ return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2)));
+ else if (uic0 & UIC0_UIC3NC)
+ return 128 - ffs(mfdcr(DCRN_UIC_MSR(UIC3)));
+ else
+ return uic0 ? 32 - ffs(uic0) : -1;
+}
+
+static void __init ppc4xx_pic_impl_init(void)
+{
+ /* Enable cascade interrupts in UIC0 */
+ ppc_cached_irq_mask[0] |= UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC;
+ mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC);
+ mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
+}
+
+#elif NR_UICS == 3
#define ACK_UIC0_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
@@ -170,6 +202,9 @@ static struct ppc4xx_uic_impl {
{ .decl = DECLARE_UIC(1), .base = UIC1 },
#if NR_UICS > 2
{ .decl = DECLARE_UIC(2), .base = UIC2 },
+#if NR_UICS > 3
+ { .decl = DECLARE_UIC(3), .base = UIC3 },
+#endif
#endif
#endif
};
diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c
new file mode 100644
index 000000000000..297f3b549177
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_rio.c
@@ -0,0 +1,938 @@
+/*
+ * MPC85xx RapidIO support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+
+#include <asm/io.h>
+
+#define RIO_REGS_BASE (CCSRBAR + 0xc0000)
+#define RIO_ATMU_REGS_OFFSET 0x10c00
+#define RIO_MSG_REGS_OFFSET 0x11000
+#define RIO_MAINT_WIN_SIZE 0x400000
+#define RIO_DBELL_WIN_SIZE 0x1000
+
+#define RIO_MSG_OMR_MUI 0x00000002
+#define RIO_MSG_OSR_TE 0x00000080
+#define RIO_MSG_OSR_QOI 0x00000020
+#define RIO_MSG_OSR_QFI 0x00000010
+#define RIO_MSG_OSR_MUB 0x00000004
+#define RIO_MSG_OSR_EOMI 0x00000002
+#define RIO_MSG_OSR_QEI 0x00000001
+
+#define RIO_MSG_IMR_MI 0x00000002
+#define RIO_MSG_ISR_TE 0x00000080
+#define RIO_MSG_ISR_QFI 0x00000010
+#define RIO_MSG_ISR_DIQI 0x00000001
+
+#define RIO_MSG_DESC_SIZE 32
+#define RIO_MSG_BUFFER_SIZE 4096
+#define RIO_MIN_TX_RING_SIZE 2
+#define RIO_MAX_TX_RING_SIZE 2048
+#define RIO_MIN_RX_RING_SIZE 2
+#define RIO_MAX_RX_RING_SIZE 2048
+
+#define DOORBELL_DMR_DI 0x00000002
+#define DOORBELL_DSR_TE 0x00000080
+#define DOORBELL_DSR_QFI 0x00000010
+#define DOORBELL_DSR_DIQI 0x00000001
+#define DOORBELL_TID_OFFSET 0x03
+#define DOORBELL_SID_OFFSET 0x05
+#define DOORBELL_INFO_OFFSET 0x06
+
+#define DOORBELL_MESSAGE_SIZE 0x08
+#define DBELL_SID(x) (*(u8 *)(x + DOORBELL_SID_OFFSET))
+#define DBELL_TID(x) (*(u8 *)(x + DOORBELL_TID_OFFSET))
+#define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET))
+
+#define is_power_of_2(x) (((x) & ((x) - 1)) == 0)
+
+struct rio_atmu_regs {
+ u32 rowtar;
+ u32 pad1;
+ u32 rowbar;
+ u32 pad2;
+ u32 rowar;
+ u32 pad3[3];
+};
+
+struct rio_msg_regs {
+ u32 omr;
+ u32 osr;
+ u32 pad1;
+ u32 odqdpar;
+ u32 pad2;
+ u32 osar;
+ u32 odpr;
+ u32 odatr;
+ u32 odcr;
+ u32 pad3;
+ u32 odqepar;
+ u32 pad4[13];
+ u32 imr;
+ u32 isr;
+ u32 pad5;
+ u32 ifqdpar;
+ u32 pad6;
+ u32 ifqepar;
+ u32 pad7[250];
+ u32 dmr;
+ u32 dsr;
+ u32 pad8;
+ u32 dqdpar;
+ u32 pad9;
+ u32 dqepar;
+ u32 pad10[26];
+ u32 pwmr;
+ u32 pwsr;
+ u32 pad11;
+ u32 pwqbar;
+};
+
+struct rio_tx_desc {
+ u32 res1;
+ u32 saddr;
+ u32 dport;
+ u32 dattr;
+ u32 res2;
+ u32 res3;
+ u32 dwcnt;
+ u32 res4;
+};
+
+static u32 regs_win;
+static struct rio_atmu_regs *atmu_regs;
+static struct rio_atmu_regs *maint_atmu_regs;
+static struct rio_atmu_regs *dbell_atmu_regs;
+static u32 dbell_win;
+static u32 maint_win;
+static struct rio_msg_regs *msg_regs;
+
+static struct rio_dbell_ring {
+ void *virt;
+ dma_addr_t phys;
+} dbell_ring;
+
+static struct rio_msg_tx_ring {
+ void *virt;
+ dma_addr_t phys;
+ void *virt_buffer[RIO_MAX_TX_RING_SIZE];
+ dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE];
+ int tx_slot;
+ int size;
+ void *dev_id;
+} msg_tx_ring;
+
+static struct rio_msg_rx_ring {
+ void *virt;
+ dma_addr_t phys;
+ void *virt_buffer[RIO_MAX_RX_RING_SIZE];
+ int rx_slot;
+ int size;
+ void *dev_id;
+} msg_rx_ring;
+
+/**
+ * mpc85xx_rio_doorbell_send - Send a MPC85xx doorbell message
+ * @index: ID of RapidIO interface
+ * @destid: Destination ID of target device
+ * @data: 16-bit info field of RapidIO doorbell message
+ *
+ * Sends a MPC85xx doorbell message. Returns %0 on success or
+ * %-EINVAL on failure.
+ */
+static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data)
+{
+ pr_debug("mpc85xx_doorbell_send: index %d destid %4.4x data %4.4x\n",
+ index, destid, data);
+ out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22);
+ out_be16((void *)(dbell_win), data);
+
+ return 0;
+}
+
+/**
+ * mpc85xx_local_config_read - Generate a MPC85xx local config space read
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be read into
+ *
+ * Generates a MPC85xx local configuration space read. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data)
+{
+ pr_debug("mpc85xx_local_config_read: index %d offset %8.8x\n", index,
+ offset);
+ *data = in_be32((void *)(regs_win + offset));
+
+ return 0;
+}
+
+/**
+ * mpc85xx_local_config_write - Generate a MPC85xx local config space write
+ * @index: ID of RapdiIO interface
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @data: Value to be written
+ *
+ * Generates a MPC85xx local configuration space write. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data)
+{
+ pr_debug
+ ("mpc85xx_local_config_write: index %d offset %8.8x data %8.8x\n",
+ index, offset, data);
+ out_be32((void *)(regs_win + offset), data);
+
+ return 0;
+}
+
+/**
+ * mpc85xx_rio_config_read - Generate a MPC85xx read maintenance transaction
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Location to be read into
+ *
+ * Generates a MPC85xx read maintenance transaction. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int
+mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len,
+ u32 * val)
+{
+ u8 *data;
+
+ pr_debug
+ ("mpc85xx_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
+ index, destid, hopcount, offset, len);
+ out_be32((void *)&maint_atmu_regs->rowtar,
+ (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+
+ data = (u8 *) maint_win + offset;
+ switch (len) {
+ case 1:
+ *val = in_8((u8 *) data);
+ break;
+ case 2:
+ *val = in_be16((u16 *) data);
+ break;
+ default:
+ *val = in_be32((u32 *) data);
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * mpc85xx_rio_config_write - Generate a MPC85xx write maintenance transaction
+ * @index: ID of RapdiIO interface
+ * @destid: Destination ID of transaction
+ * @hopcount: Number of hops to target device
+ * @offset: Offset into configuration space
+ * @len: Length (in bytes) of the maintenance transaction
+ * @val: Value to be written
+ *
+ * Generates an MPC85xx write maintenance transaction. Returns %0 on
+ * success or %-EINVAL on failure.
+ */
+static int
+mpc85xx_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset,
+ int len, u32 val)
+{
+ u8 *data;
+ pr_debug
+ ("mpc85xx_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
+ index, destid, hopcount, offset, len, val);
+ out_be32((void *)&maint_atmu_regs->rowtar,
+ (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
+
+ data = (u8 *) maint_win + offset;
+ switch (len) {
+ case 1:
+ out_8((u8 *) data, val);
+ break;
+ case 2:
+ out_be16((u16 *) data, val);
+ break;
+ default:
+ out_be32((u32 *) data, val);
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue
+ * @mport: Master port with outbound message queue
+ * @rdev: Target of outbound message
+ * @mbox: Outbound mailbox
+ * @buffer: Message to add to outbound queue
+ * @len: Length of message
+ *
+ * Adds the @buffer message to the MPC85xx outbound message queue. Returns
+ * %0 on success or %-EINVAL on failure.
+ */
+int
+rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+ void *buffer, size_t len)
+{
+ u32 omr;
+ struct rio_tx_desc *desc =
+ (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot;
+ int ret = 0;
+
+ pr_debug
+ ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n",
+ rdev->destid, mbox, (int)buffer, len);
+
+ if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Copy and clear rest of buffer */
+ memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len);
+ if (len < (RIO_MAX_MSG_SIZE - 4))
+ memset((void *)((u32) msg_tx_ring.
+ virt_buffer[msg_tx_ring.tx_slot] + len), 0,
+ RIO_MAX_MSG_SIZE - len);
+
+ /* Set mbox field for message */
+ desc->dport = mbox & 0x3;
+
+ /* Enable EOMI interrupt, set priority, and set destid */
+ desc->dattr = 0x28000000 | (rdev->destid << 2);
+
+ /* Set transfer size aligned to next power of 2 (in double words) */
+ desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);
+
+ /* Set snooping and source buffer address */
+ desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot];
+
+ /* Increment enqueue pointer */
+ omr = in_be32((void *)&msg_regs->omr);
+ out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI);
+
+ /* Go to next descriptor */
+ if (++msg_tx_ring.tx_slot == msg_tx_ring.size)
+ msg_tx_ring.tx_slot = 0;
+
+ out:
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(rio_hw_add_outb_message);
+
+/**
+ * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ * @regs: Register context
+ *
+ * Handles outbound message interrupts. Executes a register outbound
+ * mailbox event handler and acks the interrupt occurence.
+ */
+static irqreturn_t
+mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ int osr;
+ struct rio_mport *port = (struct rio_mport *)dev_instance;
+
+ osr = in_be32((void *)&msg_regs->osr);
+
+ if (osr & RIO_MSG_OSR_TE) {
+ pr_info("RIO: outbound message transmission error\n");
+ out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE);
+ goto out;
+ }
+
+ if (osr & RIO_MSG_OSR_QOI) {
+ pr_info("RIO: outbound message queue overflow\n");
+ out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI);
+ goto out;
+ }
+
+ if (osr & RIO_MSG_OSR_EOMI) {
+ u32 dqp = in_be32((void *)&msg_regs->odqdpar);
+ int slot = (dqp - msg_tx_ring.phys) >> 5;
+ port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot);
+
+ /* Ack the end-of-message interrupt */
+ out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI);
+ }
+
+ out:
+ return IRQ_HANDLED;
+}
+
+/**
+ * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox
+ * @mport: Master port implementing the outbound message unit
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the outbound mailbox ring
+ *
+ * Initializes buffer ring, request the outbound message interrupt,
+ * and enables the outbound message unit. Returns %0 on success and
+ * %-EINVAL or %-ENOMEM on failure.
+ */
+int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
+{
+ int i, j, rc = 0;
+
+ if ((entries < RIO_MIN_TX_RING_SIZE) ||
+ (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Initialize shadow copy ring */
+ msg_tx_ring.dev_id = dev_id;
+ msg_tx_ring.size = entries;
+
+ for (i = 0; i < msg_tx_ring.size; i++) {
+ if (!
+ (msg_tx_ring.virt_buffer[i] =
+ dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+ &msg_tx_ring.phys_buffer[i],
+ GFP_KERNEL))) {
+ rc = -ENOMEM;
+ for (j = 0; j < msg_tx_ring.size; j++)
+ if (msg_tx_ring.virt_buffer[j])
+ dma_free_coherent(NULL,
+ RIO_MSG_BUFFER_SIZE,
+ msg_tx_ring.
+ virt_buffer[j],
+ msg_tx_ring.
+ phys_buffer[j]);
+ goto out;
+ }
+ }
+
+ /* Initialize outbound message descriptor ring */
+ if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL,
+ msg_tx_ring.size *
+ RIO_MSG_DESC_SIZE,
+ &msg_tx_ring.phys,
+ GFP_KERNEL))) {
+ rc = -ENOMEM;
+ goto out_dma;
+ }
+ memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE);
+ msg_tx_ring.tx_slot = 0;
+
+ /* Point dequeue/enqueue pointers at first entry in ring */
+ out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys);
+ out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys);
+
+ /* Configure for snooping */
+ out_be32((void *)&msg_regs->osar, 0x00000004);
+
+ /* Clear interrupt status */
+ out_be32((void *)&msg_regs->osr, 0x000000b3);
+
+ /* Hook up outbound message handler */
+ if ((rc =
+ request_irq(MPC85xx_IRQ_RIO_TX, mpc85xx_rio_tx_handler, 0,
+ "msg_tx", (void *)mport)) < 0)
+ goto out_irq;
+
+ /*
+ * Configure outbound message unit
+ * Snooping
+ * Interrupts (all enabled, except QEIE)
+ * Chaining mode
+ * Disable
+ */
+ out_be32((void *)&msg_regs->omr, 0x00100220);
+
+ /* Set number of entries */
+ out_be32((void *)&msg_regs->omr,
+ in_be32((void *)&msg_regs->omr) |
+ ((get_bitmask_order(entries) - 2) << 12));
+
+ /* Now enable the unit */
+ out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1);
+
+ out:
+ return rc;
+
+ out_irq:
+ dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+ msg_tx_ring.virt, msg_tx_ring.phys);
+
+ out_dma:
+ for (i = 0; i < msg_tx_ring.size; i++)
+ dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+ msg_tx_ring.virt_buffer[i],
+ msg_tx_ring.phys_buffer[i]);
+
+ return rc;
+}
+
+/**
+ * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox
+ * @mport: Master port implementing the outbound message unit
+ * @mbox: Mailbox to close
+ *
+ * Disables the outbound message unit, free all buffers, and
+ * frees the outbound message interrupt.
+ */
+void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
+{
+ /* Disable inbound message unit */
+ out_be32((void *)&msg_regs->omr, 0);
+
+ /* Free ring */
+ dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+ msg_tx_ring.virt, msg_tx_ring.phys);
+
+ /* Free interrupt */
+ free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport);
+}
+
+/**
+ * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ * @regs: Register context
+ *
+ * Handles inbound message interrupts. Executes a registered inbound
+ * mailbox event handler and acks the interrupt occurence.
+ */
+static irqreturn_t
+mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ int isr;
+ struct rio_mport *port = (struct rio_mport *)dev_instance;
+
+ isr = in_be32((void *)&msg_regs->isr);
+
+ if (isr & RIO_MSG_ISR_TE) {
+ pr_info("RIO: inbound message reception error\n");
+ out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE);
+ goto out;
+ }
+
+ /* XXX Need to check/dispatch until queue empty */
+ if (isr & RIO_MSG_ISR_DIQI) {
+ /*
+ * We implement *only* mailbox 0, but can receive messages
+ * for any mailbox/letter to that mailbox destination. So,
+ * make the callback with an unknown/invalid mailbox number
+ * argument.
+ */
+ port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1);
+
+ /* Ack the queueing interrupt */
+ out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI);
+ }
+
+ out:
+ return IRQ_HANDLED;
+}
+
+/**
+ * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox
+ * @mport: Master port implementing the inbound message unit
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox to open
+ * @entries: Number of entries in the inbound mailbox ring
+ *
+ * Initializes buffer ring, request the inbound message interrupt,
+ * and enables the inbound message unit. Returns %0 on success
+ * and %-EINVAL or %-ENOMEM on failure.
+ */
+int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
+{
+ int i, rc = 0;
+
+ if ((entries < RIO_MIN_RX_RING_SIZE) ||
+ (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Initialize client buffer ring */
+ msg_rx_ring.dev_id = dev_id;
+ msg_rx_ring.size = entries;
+ msg_rx_ring.rx_slot = 0;
+ for (i = 0; i < msg_rx_ring.size; i++)
+ msg_rx_ring.virt_buffer[i] = NULL;
+
+ /* Initialize inbound message ring */
+ if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL,
+ msg_rx_ring.size *
+ RIO_MAX_MSG_SIZE,
+ &msg_rx_ring.phys,
+ GFP_KERNEL))) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Point dequeue/enqueue pointers at first entry in ring */
+ out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys);
+ out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys);
+
+ /* Clear interrupt status */
+ out_be32((void *)&msg_regs->isr, 0x00000091);
+
+ /* Hook up inbound message handler */
+ if ((rc =
+ request_irq(MPC85xx_IRQ_RIO_RX, mpc85xx_rio_rx_handler, 0,
+ "msg_rx", (void *)mport)) < 0) {
+ dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
+ msg_tx_ring.virt_buffer[i],
+ msg_tx_ring.phys_buffer[i]);
+ goto out;
+ }
+
+ /*
+ * Configure inbound message unit:
+ * Snooping
+ * 4KB max message size
+ * Unmask all interrupt sources
+ * Disable
+ */
+ out_be32((void *)&msg_regs->imr, 0x001b0060);
+
+ /* Set number of queue entries */
+ out_be32((void *)&msg_regs->imr,
+ in_be32((void *)&msg_regs->imr) |
+ ((get_bitmask_order(entries) - 2) << 12));
+
+ /* Now enable the unit */
+ out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1);
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox
+ * @mport: Master port implementing the inbound message unit
+ * @mbox: Mailbox to close
+ *
+ * Disables the inbound message unit, free all buffers, and
+ * frees the inbound message interrupt.
+ */
+void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
+{
+ /* Disable inbound message unit */
+ out_be32((void *)&msg_regs->imr, 0);
+
+ /* Free ring */
+ dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+ msg_rx_ring.virt, msg_rx_ring.phys);
+
+ /* Free interrupt */
+ free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport);
+}
+
+/**
+ * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
+ * @mport: Master port implementing the inbound message unit
+ * @mbox: Inbound mailbox number
+ * @buf: Buffer to add to inbound queue
+ *
+ * Adds the @buf buffer to the MPC85xx inbound message queue. Returns
+ * %0 on success or %-EINVAL on failure.
+ */
+int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
+{
+ int rc = 0;
+
+ pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
+ msg_rx_ring.rx_slot);
+
+ if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) {
+ printk(KERN_ERR
+ "RIO: error adding inbound buffer %d, buffer exists\n",
+ msg_rx_ring.rx_slot);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf;
+ if (++msg_rx_ring.rx_slot == msg_rx_ring.size)
+ msg_rx_ring.rx_slot = 0;
+
+ out:
+ return rc;
+}
+
+EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer);
+
+/**
+ * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit
+ * @mport: Master port implementing the inbound message unit
+ * @mbox: Inbound mailbox number
+ *
+ * Gets the next available inbound message from the inbound message queue.
+ * A pointer to the message is returned on success or NULL on failure.
+ */
+void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
+{
+ u32 imr;
+ u32 phys_buf, virt_buf;
+ void *buf = NULL;
+ int buf_idx;
+
+ phys_buf = in_be32((void *)&msg_regs->ifqdpar);
+
+ /* If no more messages, then bail out */
+ if (phys_buf == in_be32((void *)&msg_regs->ifqepar))
+ goto out2;
+
+ virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys);
+ buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
+ buf = msg_rx_ring.virt_buffer[buf_idx];
+
+ if (!buf) {
+ printk(KERN_ERR
+ "RIO: inbound message copy failed, no buffers\n");
+ goto out1;
+ }
+
+ /* Copy max message size, caller is expected to allocate that big */
+ memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE);
+
+ /* Clear the available buffer */
+ msg_rx_ring.virt_buffer[buf_idx] = NULL;
+
+ out1:
+ imr = in_be32((void *)&msg_regs->imr);
+ out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI);
+
+ out2:
+ return buf;
+}
+
+EXPORT_SYMBOL_GPL(rio_hw_get_inb_message);
+
+/**
+ * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler
+ * @irq: Linux interrupt number
+ * @dev_instance: Pointer to interrupt-specific data
+ * @regs: Register context
+ *
+ * Handles doorbell interrupts. Parses a list of registered
+ * doorbell event handlers and executes a matching event handler.
+ */
+static irqreturn_t
+mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ int dsr;
+ struct rio_mport *port = (struct rio_mport *)dev_instance;
+
+ dsr = in_be32((void *)&msg_regs->dsr);
+
+ if (dsr & DOORBELL_DSR_TE) {
+ pr_info("RIO: doorbell reception error\n");
+ out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE);
+ goto out;
+ }
+
+ if (dsr & DOORBELL_DSR_QFI) {
+ pr_info("RIO: doorbell queue full\n");
+ out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI);
+ goto out;
+ }
+
+ /* XXX Need to check/dispatch until queue empty */
+ if (dsr & DOORBELL_DSR_DIQI) {
+ u32 dmsg =
+ (u32) dbell_ring.virt +
+ (in_be32((void *)&msg_regs->dqdpar) & 0xfff);
+ u32 dmr;
+ struct rio_dbell *dbell;
+ int found = 0;
+
+ pr_debug
+ ("RIO: processing doorbell, sid %2.2x tid %2.2x info %4.4x\n",
+ DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
+
+ list_for_each_entry(dbell, &port->dbells, node) {
+ if ((dbell->res->start <= DBELL_INF(dmsg)) &&
+ (dbell->res->end >= DBELL_INF(dmsg))) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg),
+ DBELL_INF(dmsg));
+ } else {
+ pr_debug
+ ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n",
+ DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
+ }
+ dmr = in_be32((void *)&msg_regs->dmr);
+ out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI);
+ out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI);
+ }
+
+ out:
+ return IRQ_HANDLED;
+}
+
+/**
+ * mpc85xx_rio_doorbell_init - MPC85xx doorbell interface init
+ * @mport: Master port implementing the inbound doorbell unit
+ *
+ * Initializes doorbell unit hardware and inbound DMA buffer
+ * ring. Called from mpc85xx_rio_setup(). Returns %0 on success
+ * or %-ENOMEM on failure.
+ */
+static int mpc85xx_rio_doorbell_init(struct rio_mport *mport)
+{
+ int rc = 0;
+
+ /* Map outbound doorbell window immediately after maintenance window */
+ if (!(dbell_win =
+ (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
+ RIO_DBELL_WIN_SIZE))) {
+ printk(KERN_ERR
+ "RIO: unable to map outbound doorbell window\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* Initialize inbound doorbells */
+ if (!(dbell_ring.virt = dma_alloc_coherent(NULL,
+ 512 * DOORBELL_MESSAGE_SIZE,
+ &dbell_ring.phys,
+ GFP_KERNEL))) {
+ printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
+ rc = -ENOMEM;
+ iounmap((void *)dbell_win);
+ goto out;
+ }
+
+ /* Point dequeue/enqueue pointers at first entry in ring */
+ out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys);
+ out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys);
+
+ /* Clear interrupt status */
+ out_be32((void *)&msg_regs->dsr, 0x00000091);
+
+ /* Hook up doorbell handler */
+ if ((rc =
+ request_irq(MPC85xx_IRQ_RIO_BELL, mpc85xx_rio_dbell_handler, 0,
+ "dbell_rx", (void *)mport) < 0)) {
+ iounmap((void *)dbell_win);
+ dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE,
+ dbell_ring.virt, dbell_ring.phys);
+ printk(KERN_ERR
+ "MPC85xx RIO: unable to request inbound doorbell irq");
+ goto out;
+ }
+
+ /* Configure doorbells for snooping, 512 entries, and enable */
+ out_be32((void *)&msg_regs->dmr, 0x00108161);
+
+ out:
+ return rc;
+}
+
+static char *cmdline = NULL;
+
+static int mpc85xx_rio_get_hdid(int index)
+{
+ /* XXX Need to parse multiple entries in some format */
+ if (!cmdline)
+ return -1;
+
+ return simple_strtol(cmdline, NULL, 0);
+}
+
+static int mpc85xx_rio_get_cmdline(char *s)
+{
+ if (!s)
+ return 0;
+
+ cmdline = s;
+ return 1;
+}
+
+__setup("riohdid=", mpc85xx_rio_get_cmdline);
+
+/**
+ * mpc85xx_rio_setup - Setup MPC85xx RapidIO interface
+ * @law_start: Starting physical address of RapidIO LAW
+ * @law_size: Size of RapidIO LAW
+ *
+ * Initializes MPC85xx RapidIO hardware interface, configures
+ * master port with system-specific info, and registers the
+ * master port with the RapidIO subsystem.
+ */
+void mpc85xx_rio_setup(int law_start, int law_size)
+{
+ struct rio_ops *ops;
+ struct rio_mport *port;
+
+ ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL);
+ ops->lcread = mpc85xx_local_config_read;
+ ops->lcwrite = mpc85xx_local_config_write;
+ ops->cread = mpc85xx_rio_config_read;
+ ops->cwrite = mpc85xx_rio_config_write;
+ ops->dsend = mpc85xx_rio_doorbell_send;
+
+ port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL);
+ port->id = 0;
+ port->index = 0;
+ INIT_LIST_HEAD(&port->dbells);
+ port->iores.start = law_start;
+ port->iores.end = law_start + law_size;
+ port->iores.flags = IORESOURCE_MEM;
+
+ rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
+ rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
+ rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
+ strcpy(port->name, "RIO0 mport");
+
+ port->ops = ops;
+ port->host_deviceid = mpc85xx_rio_get_hdid(port->id);
+
+ rio_register_mport(port);
+
+ regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000);
+ atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET);
+ maint_atmu_regs = atmu_regs + 1;
+ dbell_atmu_regs = atmu_regs + 2;
+ msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET);
+
+ /* Configure maintenance transaction window */
+ out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000);
+ out_be32((void *)&maint_atmu_regs->rowar, 0x80077015);
+
+ maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE);
+
+ /* Configure outbound doorbell window */
+ out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400);
+ out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b);
+ mpc85xx_rio_doorbell_init(port);
+}
diff --git a/arch/ppc/syslib/ppc85xx_rio.h b/arch/ppc/syslib/ppc85xx_rio.h
new file mode 100644
index 000000000000..c0827a2c3eec
--- /dev/null
+++ b/arch/ppc/syslib/ppc85xx_rio.h
@@ -0,0 +1,21 @@
+/*
+ * MPC85xx RapidIO definitions
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#ifndef __PPC_SYSLIB_PPC85XX_RIO_H
+#define __PPC_SYSLIB_PPC85XX_RIO_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+extern void mpc85xx_rio_setup(int law_start, int law_size);
+
+#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */
diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c
index 62ee86e80711..603f01190816 100644
--- a/arch/ppc/syslib/ppc_sys.c
+++ b/arch/ppc/syslib/ppc_sys.c
@@ -14,6 +14,7 @@
* option) any later version.
*/
+#include <linux/string.h>
#include <asm/ppc_sys.h>
int (*ppc_sys_device_fixup) (struct platform_device * pdev);
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
index 278da6ee62ea..1b9aa0d6a924 100644
--- a/arch/ppc/syslib/prom.c
+++ b/arch/ppc/syslib/prom.c
@@ -1335,10 +1335,8 @@ release_OF_resource(struct device_node* node, int index)
if (!res)
return -ENODEV;
- if (res->name) {
- kfree(res->name);
- res->name = NULL;
- }
+ kfree(res->name);
+ res->name = NULL;
release_resource(res);
kfree(res);
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index c1dc876bccab..e0dde24a72ce 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -203,8 +203,15 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0)
break;
}
- vmlinux.size = (unsigned long)elf64ph->p_filesz;
- vmlinux.memsize = (unsigned long)elf64ph->p_memsz;
+ vmlinux.size = (unsigned long)elf64ph->p_filesz +
+ (unsigned long)elf64ph->p_offset;
+ /* We need to claim the memsize plus the file offset since gzip
+ * will expand the header (file offset), then the kernel, then
+ * possible rubbish we don't care about. But the kernel bss must
+ * be claimed (it will be zero'd by the kernel itself)
+ */
+ vmlinux.memsize = (unsigned long)elf64ph->p_memsz +
+ (unsigned long)elf64ph->p_offset;
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
vmlinux.addr = try_claim(vmlinux.memsize);
if (vmlinux.addr == 0) {
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index ed876a5178ae..511af54e6230 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -30,19 +30,14 @@
#include <linux/config.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
-#include <linux/spinlock.h>
#include <linux/preempt.h>
#include <asm/cacheflush.h>
#include <asm/kdebug.h>
#include <asm/sstep.h>
static DECLARE_MUTEX(kprobe_mutex);
-
-static struct kprobe *current_kprobe;
-static unsigned long kprobe_status, kprobe_saved_msr;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
-static struct pt_regs jprobe_saved_regs;
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
@@ -108,20 +103,28 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->nip = (unsigned long)p->ainsn.insn;
}
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
+ kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
+}
+
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- kprobe_prev = current_kprobe;
- kprobe_status_prev = kprobe_status;
- kprobe_saved_msr_prev = kprobe_saved_msr;
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+ kcb->kprobe_status = kcb->prev_kprobe.status;
+ kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
}
-static inline void restore_previous_kprobe(void)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
{
- current_kprobe = kprobe_prev;
- kprobe_status = kprobe_status_prev;
- kprobe_saved_msr = kprobe_saved_msr_prev;
+ __get_cpu_var(current_kprobe) = p;
+ kcb->kprobe_saved_msr = regs->msr;
}
+/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
struct pt_regs *regs)
{
@@ -145,19 +148,24 @@ static inline int kprobe_handler(struct pt_regs *regs)
struct kprobe *p;
int ret = 0;
unsigned int *addr = (unsigned int *)regs->nip;
+ struct kprobe_ctlblk *kcb;
+
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
+ preempt_disable();
+ kcb = get_kprobe_ctlblk();
/* Check we're not actually recursing */
if (kprobe_running()) {
- /* We *are* holding lock here, so this is safe.
- Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
kprobe_opcode_t insn = *p->ainsn.insn;
- if (kprobe_status == KPROBE_HIT_SS &&
+ if (kcb->kprobe_status == KPROBE_HIT_SS &&
is_trap(insn)) {
regs->msr &= ~MSR_SE;
- regs->msr |= kprobe_saved_msr;
- unlock_kprobes();
+ regs->msr |= kcb->kprobe_saved_msr;
goto no_kprobe;
}
/* We have reentered the kprobe_handler(), since
@@ -166,27 +174,24 @@ static inline int kprobe_handler(struct pt_regs *regs)
* just single step on the instruction of the new probe
* without calling any user handlers.
*/
- save_previous_kprobe();
- current_kprobe = p;
- kprobe_saved_msr = regs->msr;
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p, regs, kcb);
+ kcb->kprobe_saved_msr = regs->msr;
p->nmissed++;
prepare_singlestep(p, regs);
- kprobe_status = KPROBE_REENTER;
+ kcb->kprobe_status = KPROBE_REENTER;
return 1;
} else {
- p = current_kprobe;
+ p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
}
}
- /* If it's not ours, can't be delete race, (we hold lock). */
goto no_kprobe;
}
- lock_kprobes();
p = get_kprobe(addr);
if (!p) {
- unlock_kprobes();
if (*addr != BREAKPOINT_INSTRUCTION) {
/*
* PowerPC has multiple variants of the "trap"
@@ -209,24 +214,19 @@ static inline int kprobe_handler(struct pt_regs *regs)
goto no_kprobe;
}
- kprobe_status = KPROBE_HIT_ACTIVE;
- current_kprobe = p;
- kprobe_saved_msr = regs->msr;
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+ set_current_kprobe(p, regs, kcb);
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);
- kprobe_status = KPROBE_HIT_SS;
- /*
- * This preempt_disable() matches the preempt_enable_no_resched()
- * in post_kprobe_handler().
- */
- preempt_disable();
+ kcb->kprobe_status = KPROBE_HIT_SS;
return 1;
no_kprobe:
+ preempt_enable_no_resched();
return ret;
}
@@ -251,9 +251,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
+ unsigned long flags, orig_ret_address = 0;
unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+ spin_lock_irqsave(&kretprobe_lock, flags);
head = kretprobe_inst_table_head(current);
/*
@@ -292,12 +293,14 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
regs->nip = orig_ret_address;
- unlock_kprobes();
+ reset_current_kprobe();
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
+ preempt_enable_no_resched();
/*
* By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
+ * kprobe_handler() that we don't want the post_handler
+ * to run (and have re-enabled preemption)
*/
return 1;
}
@@ -323,23 +326,26 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
static inline int post_kprobe_handler(struct pt_regs *regs)
{
- if (!kprobe_running())
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (!cur)
return 0;
- if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
- kprobe_status = KPROBE_HIT_SSDONE;
- current_kprobe->post_handler(current_kprobe, regs, 0);
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
}
- resume_execution(current_kprobe, regs);
- regs->msr |= kprobe_saved_msr;
+ resume_execution(cur, regs);
+ regs->msr |= kcb->kprobe_saved_msr;
/*Restore back the original saved kprobes variables and continue. */
- if (kprobe_status == KPROBE_REENTER) {
- restore_previous_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
goto out;
}
- unlock_kprobes();
+ reset_current_kprobe();
out:
preempt_enable_no_resched();
@@ -354,19 +360,20 @@ out:
return 1;
}
-/* Interrupts disabled, kprobe_lock held. */
static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
- if (current_kprobe->fault_handler
- && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;
- if (kprobe_status & KPROBE_HIT_SS) {
- resume_execution(current_kprobe, regs);
+ if (kcb->kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs);
regs->msr &= ~MSR_SE;
- regs->msr |= kprobe_saved_msr;
+ regs->msr |= kcb->kprobe_saved_msr;
- unlock_kprobes();
+ reset_current_kprobe();
preempt_enable_no_resched();
}
return 0;
@@ -381,11 +388,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
struct die_args *args = (struct die_args *)data;
int ret = NOTIFY_DONE;
- /*
- * Interrupts are not disabled here. We need to disable
- * preemption, because kprobe_running() uses smp_processor_id().
- */
- preempt_disable();
switch (val) {
case DIE_BPT:
if (kprobe_handler(args->regs))
@@ -396,22 +398,25 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
ret = NOTIFY_STOP;
break;
case DIE_PAGE_FAULT:
+ /* kprobe_running() needs smp_processor_id() */
+ preempt_disable();
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
ret = NOTIFY_STOP;
+ preempt_enable();
break;
default:
break;
}
- preempt_enable_no_resched();
return ret;
}
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
+ memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs));
/* setup return addr to the jprobe handler routine */
regs->nip = (unsigned long)(((func_descr_t *)jp->entry)->entry);
@@ -431,12 +436,15 @@ void __kprobes jprobe_return_end(void)
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
/*
* FIXME - we should ideally be validating that we got here 'cos
* of the "trap" in jprobe_return() above, before restoring the
* saved regs...
*/
- memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
+ memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs));
+ preempt_enable_no_resched();
return 1;
}
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index e86155770bbc..3e7b2f28ec83 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -599,9 +599,7 @@ int __init lparcfg_init(void)
void __exit lparcfg_cleanup(void)
{
if (proc_ppc64_lparcfg) {
- if (proc_ppc64_lparcfg->data) {
- kfree(proc_ppc64_lparcfg->data);
- }
+ kfree(proc_ppc64_lparcfg->data);
remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
}
}
diff --git a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c
index 215bf8900304..2edc947f7c44 100644
--- a/arch/ppc64/kernel/scanlog.c
+++ b/arch/ppc64/kernel/scanlog.c
@@ -225,8 +225,7 @@ int __init scanlog_init(void)
void __exit scanlog_cleanup(void)
{
if (proc_ppc64_scan_log_dump) {
- if (proc_ppc64_scan_log_dump->data)
- kfree(proc_ppc64_scan_log_dump->data);
+ kfree(proc_ppc64_scan_log_dump->data);
remove_proc_entry("scan-log-dump", proc_ppc64_scan_log_dump->parent);
}
}
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 6654b350979c..e99ec62c2c52 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -20,6 +20,7 @@
#include <asm/paca.h>
#include <asm/lppaca.h>
#include <asm/machdep.h>
+#include <asm/smp.h>
static DEFINE_PER_CPU(struct cpu, cpu_devices);
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 98db30481d97..73a09a6ee6c8 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -76,9 +76,7 @@ AFLAGS += $(aflags-y)
OBJCOPYFLAGS := -O binary
LDFLAGS_vmlinux := -e start
-head-$(CONFIG_ARCH_S390_31) += arch/$(ARCH)/kernel/head.o
-head-$(CONFIG_ARCH_S390X) += arch/$(ARCH)/kernel/head64.o
-head-y += arch/$(ARCH)/kernel/init_task.o
+head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \
arch/$(ARCH)/appldata/
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 8584dd823218..7434c32bc631 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -8,9 +8,7 @@ obj-y := bitmap.o traps.o time.o process.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o
-extra-$(CONFIG_ARCH_S390_31) += head.o
-extra-$(CONFIG_ARCH_S390X) += head64.o
-extra-y += init_task.o vmlinux.lds
+extra-y += head.o init_task.o vmlinux.lds
obj-$(CONFIG_MODULES) += s390_ksyms.o module.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 9b30f4cf32c4..27b07730b7b8 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -288,7 +288,7 @@ sysc_sigpending:
bo BASED(sysc_restart)
tm __TI_flags+3(%r9),_TIF_SINGLE_STEP
bo BASED(sysc_singlestep)
- b BASED(sysc_leave) # out of here, do NOT recheck
+ b BASED(sysc_work_loop)
#
# _TIF_RESTART_SVC is set, set up registers and restart svc
@@ -645,7 +645,7 @@ io_sigpending:
l %r1,BASED(.Ldo_signal)
basr %r14,%r1 # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
- b BASED(io_leave) # out of here, do NOT recheck
+ b BASED(io_work_loop)
/*
* External interrupt handler routine
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 7b9b4a2ba1d7..4eb71ffcf484 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -283,7 +283,7 @@ sysc_sigpending:
jo sysc_restart
tm __TI_flags+7(%r9),_TIF_SINGLE_STEP
jo sysc_singlestep
- j sysc_leave # out of here, do NOT recheck
+ j sysc_work_loop
#
# _TIF_RESTART_SVC is set, set up registers and restart svc
@@ -684,7 +684,7 @@ io_sigpending:
slgr %r3,%r3 # clear *oldset
brasl %r14,do_signal # call do_signal
stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts
- j sysc_leave # out of here, do NOT recheck
+ j io_work_loop
/*
* External interrupt handler routine
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 039354d72348..d31a97c89f68 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -1,11 +1,12 @@
/*
* arch/s390/kernel/head.S
*
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Hartmut Penner (hp@de.ibm.com),
- * Martin Schwidefsky (schwidefsky@de.ibm.com),
- * Rob van der Heij (rvdhei@iae.nl)
+ * (C) Copyright IBM Corp. 1999, 2005
+ *
+ * Author(s): Hartmut Penner <hp@de.ibm.com>
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * Rob van der Heij <rvdhei@iae.nl>
+ * Heiko Carstens <heiko.carstens@de.ibm.com>
*
* There are 5 different IPL methods
* 1) load the image directly into ram at address 0 and do an PSW restart
@@ -19,12 +20,7 @@
* 5) direct call of start by the SALIPL loader
* We use the cpuid to distinguish between VM and native ipl
* params for kernel are pushed to 0x10400 (see setup.h)
-
- Changes:
- Okt 25 2000 <rvdheij@iae.nl>
- added code to skip HDR and EOF to allow SL tape IPL (5 retries)
- changed first CCW from rewind to backspace block
-
+ *
*/
#include <linux/config.h>
@@ -34,6 +30,12 @@
#include <asm/thread_info.h>
#include <asm/page.h>
+#ifdef CONFIG_ARCH_S390X
+#define ARCH_OFFSET 4
+#else
+#define ARCH_OFFSET 0
+#endif
+
#ifndef CONFIG_IPL
.org 0
.long 0x00080000,0x80000000+startup # Just a restart PSW
@@ -201,7 +203,7 @@
ssch 0(%r3) # load chunk of 1600 bytes
bnz .Llderr
.Lwait4irq:
- mvc __LC_IO_NEW_PSW(8),.Lnewpsw # set up IO interrupt psw
+ mvc 0x78(8),.Lnewpsw # set up IO interrupt psw
lpsw .Lwaitpsw
.Lioint:
c %r1,0xb8 # compare subchannel number
@@ -265,13 +267,13 @@ iplstart:
la %r2,IPL_BS # load start address
bas %r14,.Lloader # load rest of ipl image
l %r12,.Lparm # pointer to parameter area
- st %r1,IPL_DEVICE-PARMAREA(%r12) # store ipl device number
+ st %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number
#
# load parameter file from ipl device
#
.Lagain1:
- l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp
+ l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp
bas %r14,.Lloader # load parameter file
ltr %r2,%r2 # got anything ?
bz .Lnopf
@@ -279,7 +281,7 @@ iplstart:
bnh .Lnotrunc
la %r2,895
.Lnotrunc:
- l %r4,INITRD_START-PARMAREA(%r12)
+ l %r4,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
clc 0(3,%r4),.L_hdr # if it is HDRx
bz .Lagain1 # skip dataset header
clc 0(3,%r4),.L_eof # if it is EOFx
@@ -322,14 +324,14 @@ iplstart:
# load ramdisk from ipl device
#
.Lagain2:
- l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk
+ l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk
bas %r14,.Lloader # load ramdisk
- st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk
+ st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk
ltr %r2,%r2
bnz .Lrdcont
- st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it
+ st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found
.Lrdcont:
- l %r2,INITRD_START-PARMAREA(%r12)
+ l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12)
clc 0(3,%r2),.L_hdr # skip HDRx and EOFx
bz .Lagain2
@@ -432,10 +434,10 @@ start:
la %r3,1(%r3)
.done:
l %r1,.memsize
- st %r3,0(%r1)
+ st %r3,ARCH_OFFSET(%r1)
slr %r0,%r0
- st %r0,INITRD_SIZE-PARMAREA(%r11)
- st %r0,INITRD_START-PARMAREA(%r11)
+ st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11)
+ st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11)
j startup # continue with startup
.tbl: .long _ebcasc # translate table
.cmd: .long COMMAND_LINE # address of command line buffer
@@ -478,304 +480,23 @@ start:
.byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
.byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
-#
-# startup-code at 0x10000, running in real mode
-# this is called either by the ipl loader or directly by PSW restart
-# or linload or SALIPL
-#
- .org 0x10000
-startup:basr %r13,0 # get base
-.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13)
- basr %r14, %r1
- lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
- la %r12,_pstart-.LPG1(%r13) # pointer to parameter area
- # move IPL device to lowcore
- mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
-
-#
-# clear bss memory
-#
- l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss
- l %r3,.Lbss_end-.LPG1(%r13) # end of bss
- sr %r3,%r2 # length of bss
- sr %r4,%r4 #
- sr %r5,%r5 # set src,length and pad to zero
- sr %r0,%r0 #
- mvcle %r2,%r4,0 # clear mem
- jo .-4 # branch back, if not finish
-
- l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
-.Lservicecall:
- stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
-
- stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0
- la %r1,0x200 # set bit 22
- o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
- st %r1,.Lcr-.LPG1(%r13)
- lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0
-
- mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
- la %r1, .Lsclph-.LPG1(%r13)
- a %r1,__LC_EXT_NEW_PSW+4 # set handler
- st %r1,__LC_EXT_NEW_PSW+4
-
- la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff
- la %r1, .Lsccb-PARMAREA(%r4) # our sccb
- .insn rre,0xb2200000,%r2,%r1 # service call
- ipm %r1
- srl %r1,28 # get cc code
- xr %r3, %r3
- chi %r1,3
- be .Lfchunk-.LPG1(%r13) # leave
- chi %r1,2
- be .Lservicecall-.LPG1(%r13)
- lpsw .Lwaitsclp-.LPG1(%r13)
-.Lsclph:
- lh %r1,.Lsccbr-PARMAREA(%r4)
- chi %r1,0x10 # 0x0010 is the sucess code
- je .Lprocsccb # let's process the sccb
- chi %r1,0x1f0
- bne .Lfchunk-.LPG1(%r13) # unhandled error code
- c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced
- bne .Lfchunk-.LPG1(%r13) # if no, give up
- l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP
- b .Lservicecall-.LPG1(%r13)
-.Lprocsccb:
- lhi %r1,0
- icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
- jnz .Lscnd
- lhi %r1,0x800 # otherwise report 2GB
-.Lscnd:
- lhi %r3,0x800 # limit reported memory size to 2GB
- cr %r1,%r3
- jl .Lno2gb
- lr %r1,%r3
-.Lno2gb:
- xr %r3,%r3 # same logic
- ic %r3,.Lscpa1-PARMAREA(%r4)
- chi %r3,0x00
- jne .Lcompmem
- l %r3,.Lscpa2-PARMAREA(%r13)
-.Lcompmem:
- mr %r2,%r1 # mem in MB on 128-bit
- l %r1,.Lonemb-.LPG1(%r13)
- mr %r2,%r1 # mem size in bytes in %r3
- b .Lfchunk-.LPG1(%r13)
-
- .align 4
-.Lget_ipl_device_addr:
- .long .Lget_ipl_device
-.Lpmask:
- .byte 0
-.align 8
-.Lpcext:.long 0x00080000,0x80000000
-.Lcr:
- .long 0x00 # place holder for cr0
-.Lwaitsclp:
- .long 0x020A0000
- .long .Lsclph
-.Lrcp:
- .int 0x00120001 # Read SCP forced code
-.Lrcp2:
- .int 0x00020001 # Read SCP code
-.Lonemb:
- .int 0x100000
-.Lfchunk:
-
-#
-# find memory chunks.
-#
- lr %r9,%r3 # end of mem
- mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
- la %r1,1 # test in increments of 128KB
- sll %r1,17
- l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
- slr %r4,%r4 # set start of chunk to zero
- slr %r5,%r5 # set end of chunk to zero
- slr %r6,%r6 # set access code to zero
- la %r10, MEMORY_CHUNKS # number of chunks
-.Lloop:
- tprot 0(%r5),0 # test protection of first byte
- ipm %r7
- srl %r7,28
- clr %r6,%r7 # compare cc with last access code
- be .Lsame-.LPG1(%r13)
- b .Lchkmem-.LPG1(%r13)
-.Lsame:
- ar %r5,%r1 # add 128KB to end of chunk
- bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop
-.Lchkmem: # > 2GB or tprot got a program check
- clr %r4,%r5 # chunk size > 0?
- be .Lchkloop-.LPG1(%r13)
- st %r4,0(%r3) # store start address of chunk
- lr %r0,%r5
- slr %r0,%r4
- st %r0,4(%r3) # store size of chunk
- st %r6,8(%r3) # store type of chunk
- la %r3,12(%r3)
- l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size
- st %r5,0(%r4) # store last end to memory size
- ahi %r10,-1 # update chunk number
-.Lchkloop:
- lr %r6,%r7 # set access code to last cc
- # we got an exception or we're starting a new
- # chunk , we must check if we should
- # still try to find valid memory (if we detected
- # the amount of available storage), and if we
- # have chunks left
- xr %r0,%r0
- clr %r0,%r9 # did we detect memory?
- je .Ldonemem # if not, leave
- chi %r10,0 # do we have chunks left?
- je .Ldonemem
- alr %r5,%r1 # add 128KB to end of chunk
- lr %r4,%r5 # potential new chunk
- clr %r5,%r9 # should we go on?
- jl .Lloop
-.Ldonemem:
- l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
-#
-# find out if we are running under VM
-#
- stidp __LC_CPUID # store cpuid
- tm __LC_CPUID,0xff # running under VM ?
- bno .Lnovm-.LPG1(%r13)
- oi 3(%r12),1 # set VM flag
-.Lnovm:
- lh %r0,__LC_CPUID+4 # get cpu version
- chi %r0,0x7490 # running on a P/390 ?
- bne .Lnop390-.LPG1(%r13)
- oi 3(%r12),4 # set P/390 flag
-.Lnop390:
-
-#
-# find out if we have an IEEE fpu
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
- efpc %r0,0 # test IEEE extract fpc instruction
- oi 3(%r12),2 # set IEEE fpu flag
-.Lchkfpu:
-
-#
-# find out if we have the CSP instruction
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
- la %r0,0
- lr %r1,%r0
- la %r2,4
- csp %r0,%r2 # Test CSP instruction
- oi 3(%r12),8 # set CSP flag
-.Lchkcsp:
-
-#
-# find out if we have the MVPG instruction
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
- sr %r0,%r0
- la %r1,0
- la %r2,0
- mvpg %r1,%r2 # Test CSP instruction
- oi 3(%r12),16 # set MVPG flag
-.Lchkmvpg:
-
-#
-# find out if we have the IDTE instruction
-#
- mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
- .long 0xb2b10000 # store facility list
- tm 0xc8,0x08 # check bit for clearing-by-ASCE
- bno .Lchkidte-.LPG1(%r13)
- lhi %r1,2094
- lhi %r2,0
- .long 0xb98e2001
- oi 3(%r12),0x80 # set IDTE flag
-.Lchkidte:
-
- lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space,
- # virtual and never return ...
- .align 8
-.Lentry:.long 0x00080000,0x80000000 + _stext
-.Lctl: .long 0x04b50002 # cr0: various things
- .long 0 # cr1: primary space segment table
- .long .Lduct # cr2: dispatchable unit control table
- .long 0 # cr3: instruction authorization
- .long 0 # cr4: instruction authorization
- .long 0xffffffff # cr5: primary-aste origin
- .long 0 # cr6: I/O interrupts
- .long 0 # cr7: secondary space segment table
- .long 0 # cr8: access registers translation
- .long 0 # cr9: tracing off
- .long 0 # cr10: tracing off
- .long 0 # cr11: tracing off
- .long 0 # cr12: tracing off
- .long 0 # cr13: home space segment table
- .long 0xc0000000 # cr14: machine check handling off
- .long 0 # cr15: linkage stack operations
-.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem
-.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
-.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
-.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
-.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
-.Lmemsize:.long memory_size
-.Lmchunk:.long memory_chunk
-.Lmflags:.long machine_flags
-.Lbss_bgn: .long __bss_start
-.Lbss_end: .long _end
-
- .org PARMAREA-64
-.Lduct: .long 0,0,0,0,0,0,0,0
- .long 0,0,0,0,0,0,0,0
-
-#
-# params at 10400 (setup.h)
-#
- .org PARMAREA
- .global _pstart
-_pstart:
- .long 0,0 # IPL_DEVICE
- .long 0,RAMDISK_ORIGIN # INITRD_START
- .long 0,RAMDISK_SIZE # INITRD_SIZE
-
- .org COMMAND_LINE
- .byte "root=/dev/ram0 ro"
- .byte 0
- .org 0x11000
-.Lsccb:
- .hword 0x1000 # length, one page
- .byte 0x00,0x00,0x00
- .byte 0x80 # variable response bit set
-.Lsccbr:
- .hword 0x00 # response code
-.Lscpincr1:
- .hword 0x00
-.Lscpa1:
- .byte 0x00
- .fill 89,1,0
-.Lscpa2:
- .int 0x00
-.Lscpincr2:
- .quad 0x00
- .fill 3984,1,0
- .org 0x12000
- .global _pend
-_pend:
-
+.macro GET_IPL_DEVICE
.Lget_ipl_device:
basr %r12,0
-.LPG2: l %r1,0xb8 # get sid
+.LGID: l %r1,0xb8 # get sid
sll %r1,15 # test if subchannel is enabled
srl %r1,31
ltr %r1,%r1
bz 0(%r14) # subchannel disabled
l %r1,0xb8
- la %r5,.Lipl_schib-.LPG2(%r12)
+ la %r5,.Lipl_schib-.LGID(%r12)
stsch 0(%r5) # get schib of subchannel
bnz 0(%r14) # schib not available
tm 5(%r5),0x01 # devno valid?
bno 0(%r14)
- la %r6,ipl_parameter_flags-.LPG2(%r12)
+ la %r6,ipl_parameter_flags-.LGID(%r12)
oi 3(%r6),0x01 # set flag
- la %r2,ipl_devno-.LPG2(%r12)
+ la %r2,ipl_devno-.LGID(%r12)
mvc 0(2,%r2),6(%r5) # store devno
tm 4(%r5),0x80 # qdio capable device?
bno 0(%r14)
@@ -816,46 +537,10 @@ ipl_parameter_flags:
.globl ipl_devno
ipl_devno:
.word 0
+.endm
-#ifdef CONFIG_SHARED_KERNEL
- .org 0x100000
+#ifdef CONFIG_ARCH_S390X
+#include "head64.S"
+#else
+#include "head31.S"
#endif
-
-#
-# startup-code, running in virtual mode
-#
- .globl _stext
-_stext: basr %r13,0 # get base
-.LPG3:
-#
-# Setup stack
-#
- l %r15,.Linittu-.LPG3(%r13)
- mvc __LC_CURRENT(4),__TI_task(%r15)
- ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
- st %r15,__LC_KERNEL_STACK # set end of kernel stack
- ahi %r15,-96
- xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
-# check control registers
- stctl %c0,%c15,0(%r15)
- oi 2(%r15),0x40 # enable sigp emergency signal
- oi 0(%r15),0x10 # switch on low address protection
- lctl %c0,%c15,0(%r15)
-
-#
- lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
- l %r14,.Lstart-.LPG3(%r13)
- basr %r14,%r14 # call start_kernel
-#
-# We returned from start_kernel ?!? PANIK
-#
- basr %r13,0
- lpsw .Ldw-.(%r13) # load disabled wait psw
-#
- .align 8
-.Ldw: .long 0x000a0000,0x00000000
-.Linittu: .long init_thread_union
-.Lstart: .long start_kernel
-.Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
new file mode 100644
index 000000000000..2d3b089bfb83
--- /dev/null
+++ b/arch/s390/kernel/head31.S
@@ -0,0 +1,336 @@
+/*
+ * arch/s390/kernel/head31.S
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Hartmut Penner <hp@de.ibm.com>
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * Rob van der Heij <rvdhei@iae.nl>
+ * Heiko Carstens <heiko.carstens@de.ibm.com>
+ *
+ */
+
+#
+# startup-code at 0x10000, running in absolute addressing mode
+# this is called either by the ipl loader or directly by PSW restart
+# or linload or SALIPL
+#
+ .org 0x10000
+startup:basr %r13,0 # get base
+.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13)
+ basr %r14, %r1
+ lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
+ la %r12,_pstart-.LPG1(%r13) # pointer to parameter area
+ # move IPL device to lowcore
+ mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12)
+
+#
+# clear bss memory
+#
+ l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss
+ l %r3,.Lbss_end-.LPG1(%r13) # end of bss
+ sr %r3,%r2 # length of bss
+ sr %r4,%r4
+ sr %r5,%r5 # set src,length and pad to zero
+ sr %r0,%r0
+ mvcle %r2,%r4,0 # clear mem
+ jo .-4 # branch back, if not finish
+
+ l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word
+.Lservicecall:
+ stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts
+
+ stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0
+ la %r1,0x200 # set bit 22
+ o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1
+ st %r1,.Lcr-.LPG1(%r13)
+ lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0
+
+ mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
+ la %r1, .Lsclph-.LPG1(%r13)
+ a %r1,__LC_EXT_NEW_PSW+4 # set handler
+ st %r1,__LC_EXT_NEW_PSW+4
+
+ la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff
+ la %r1, .Lsccb-PARMAREA(%r4) # our sccb
+ .insn rre,0xb2200000,%r2,%r1 # service call
+ ipm %r1
+ srl %r1,28 # get cc code
+ xr %r3, %r3
+ chi %r1,3
+ be .Lfchunk-.LPG1(%r13) # leave
+ chi %r1,2
+ be .Lservicecall-.LPG1(%r13)
+ lpsw .Lwaitsclp-.LPG1(%r13)
+.Lsclph:
+ lh %r1,.Lsccbr-PARMAREA(%r4)
+ chi %r1,0x10 # 0x0010 is the sucess code
+ je .Lprocsccb # let's process the sccb
+ chi %r1,0x1f0
+ bne .Lfchunk-.LPG1(%r13) # unhandled error code
+ c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced
+ bne .Lfchunk-.LPG1(%r13) # if no, give up
+ l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP
+ b .Lservicecall-.LPG1(%r13)
+.Lprocsccb:
+ lhi %r1,0
+ icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+ jnz .Lscnd
+ lhi %r1,0x800 # otherwise report 2GB
+.Lscnd:
+ lhi %r3,0x800 # limit reported memory size to 2GB
+ cr %r1,%r3
+ jl .Lno2gb
+ lr %r1,%r3
+.Lno2gb:
+ xr %r3,%r3 # same logic
+ ic %r3,.Lscpa1-PARMAREA(%r4)
+ chi %r3,0x00
+ jne .Lcompmem
+ l %r3,.Lscpa2-PARMAREA(%r13)
+.Lcompmem:
+ mr %r2,%r1 # mem in MB on 128-bit
+ l %r1,.Lonemb-.LPG1(%r13)
+ mr %r2,%r1 # mem size in bytes in %r3
+ b .Lfchunk-.LPG1(%r13)
+
+ .align 4
+.Lget_ipl_device_addr:
+ .long .Lget_ipl_device
+.Lpmask:
+ .byte 0
+.align 8
+.Lpcext:.long 0x00080000,0x80000000
+.Lcr:
+ .long 0x00 # place holder for cr0
+.Lwaitsclp:
+ .long 0x010a0000,0x80000000 + .Lsclph
+.Lrcp:
+ .int 0x00120001 # Read SCP forced code
+.Lrcp2:
+ .int 0x00020001 # Read SCP code
+.Lonemb:
+ .int 0x100000
+.Lfchunk:
+
+#
+# find memory chunks.
+#
+ lr %r9,%r3 # end of mem
+ mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
+ la %r1,1 # test in increments of 128KB
+ sll %r1,17
+ l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
+ slr %r4,%r4 # set start of chunk to zero
+ slr %r5,%r5 # set end of chunk to zero
+ slr %r6,%r6 # set access code to zero
+ la %r10, MEMORY_CHUNKS # number of chunks
+.Lloop:
+ tprot 0(%r5),0 # test protection of first byte
+ ipm %r7
+ srl %r7,28
+ clr %r6,%r7 # compare cc with last access code
+ be .Lsame-.LPG1(%r13)
+ b .Lchkmem-.LPG1(%r13)
+.Lsame:
+ ar %r5,%r1 # add 128KB to end of chunk
+ bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop
+.Lchkmem: # > 2GB or tprot got a program check
+ clr %r4,%r5 # chunk size > 0?
+ be .Lchkloop-.LPG1(%r13)
+ st %r4,0(%r3) # store start address of chunk
+ lr %r0,%r5
+ slr %r0,%r4
+ st %r0,4(%r3) # store size of chunk
+ st %r6,8(%r3) # store type of chunk
+ la %r3,12(%r3)
+ l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size
+ st %r5,0(%r4) # store last end to memory size
+ ahi %r10,-1 # update chunk number
+.Lchkloop:
+ lr %r6,%r7 # set access code to last cc
+ # we got an exception or we're starting a new
+ # chunk , we must check if we should
+ # still try to find valid memory (if we detected
+ # the amount of available storage), and if we
+ # have chunks left
+ xr %r0,%r0
+ clr %r0,%r9 # did we detect memory?
+ je .Ldonemem # if not, leave
+ chi %r10,0 # do we have chunks left?
+ je .Ldonemem
+ alr %r5,%r1 # add 128KB to end of chunk
+ lr %r4,%r5 # potential new chunk
+ clr %r5,%r9 # should we go on?
+ jl .Lloop
+.Ldonemem:
+ l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
+#
+# find out if we are running under VM
+#
+ stidp __LC_CPUID # store cpuid
+ tm __LC_CPUID,0xff # running under VM ?
+ bno .Lnovm-.LPG1(%r13)
+ oi 3(%r12),1 # set VM flag
+.Lnovm:
+ lh %r0,__LC_CPUID+4 # get cpu version
+ chi %r0,0x7490 # running on a P/390 ?
+ bne .Lnop390-.LPG1(%r13)
+ oi 3(%r12),4 # set P/390 flag
+.Lnop390:
+
+#
+# find out if we have an IEEE fpu
+#
+ mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13)
+ efpc %r0,0 # test IEEE extract fpc instruction
+ oi 3(%r12),2 # set IEEE fpu flag
+.Lchkfpu:
+
+#
+# find out if we have the CSP instruction
+#
+ mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13)
+ la %r0,0
+ lr %r1,%r0
+ la %r2,4
+ csp %r0,%r2 # Test CSP instruction
+ oi 3(%r12),8 # set CSP flag
+.Lchkcsp:
+
+#
+# find out if we have the MVPG instruction
+#
+ mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13)
+ sr %r0,%r0
+ la %r1,0
+ la %r2,0
+ mvpg %r1,%r2 # Test CSP instruction
+ oi 3(%r12),16 # set MVPG flag
+.Lchkmvpg:
+
+#
+# find out if we have the IDTE instruction
+#
+ mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13)
+ .long 0xb2b10000 # store facility list
+ tm 0xc8,0x08 # check bit for clearing-by-ASCE
+ bno .Lchkidte-.LPG1(%r13)
+ lhi %r1,2094
+ lhi %r2,0
+ .long 0xb98e2001
+ oi 3(%r12),0x80 # set IDTE flag
+.Lchkidte:
+
+ lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space,
+ # virtual and never return ...
+ .align 8
+.Lentry:.long 0x00080000,0x80000000 + _stext
+.Lctl: .long 0x04b50002 # cr0: various things
+ .long 0 # cr1: primary space segment table
+ .long .Lduct # cr2: dispatchable unit control table
+ .long 0 # cr3: instruction authorization
+ .long 0 # cr4: instruction authorization
+ .long 0xffffffff # cr5: primary-aste origin
+ .long 0 # cr6: I/O interrupts
+ .long 0 # cr7: secondary space segment table
+ .long 0 # cr8: access registers translation
+ .long 0 # cr9: tracing off
+ .long 0 # cr10: tracing off
+ .long 0 # cr11: tracing off
+ .long 0 # cr12: tracing off
+ .long 0 # cr13: home space segment table
+ .long 0xc0000000 # cr14: machine check handling off
+ .long 0 # cr15: linkage stack operations
+.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem
+.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu
+.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp
+.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
+.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte
+.Lmemsize:.long memory_size
+.Lmchunk:.long memory_chunk
+.Lmflags:.long machine_flags
+.Lbss_bgn: .long __bss_start
+.Lbss_end: .long _end
+
+ .org PARMAREA-64
+.Lduct: .long 0,0,0,0,0,0,0,0
+ .long 0,0,0,0,0,0,0,0
+
+#
+# params at 10400 (setup.h)
+#
+ .org PARMAREA
+ .global _pstart
+_pstart:
+ .long 0,0 # IPL_DEVICE
+ .long 0,RAMDISK_ORIGIN # INITRD_START
+ .long 0,RAMDISK_SIZE # INITRD_SIZE
+
+ .org COMMAND_LINE
+ .byte "root=/dev/ram0 ro"
+ .byte 0
+ .org 0x11000
+.Lsccb:
+ .hword 0x1000 # length, one page
+ .byte 0x00,0x00,0x00
+ .byte 0x80 # variable response bit set
+.Lsccbr:
+ .hword 0x00 # response code
+.Lscpincr1:
+ .hword 0x00
+.Lscpa1:
+ .byte 0x00
+ .fill 89,1,0
+.Lscpa2:
+ .int 0x00
+.Lscpincr2:
+ .quad 0x00
+ .fill 3984,1,0
+ .org 0x12000
+ .global _pend
+_pend:
+
+ GET_IPL_DEVICE
+
+#ifdef CONFIG_SHARED_KERNEL
+ .org 0x100000
+#endif
+
+#
+# startup-code, running in virtual mode
+#
+ .globl _stext
+_stext: basr %r13,0 # get base
+.LPG3:
+#
+# Setup stack
+#
+ l %r15,.Linittu-.LPG3(%r13)
+ mvc __LC_CURRENT(4),__TI_task(%r15)
+ ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE
+ st %r15,__LC_KERNEL_STACK # set end of kernel stack
+ ahi %r15,-96
+ xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
+
+# check control registers
+ stctl %c0,%c15,0(%r15)
+ oi 2(%r15),0x40 # enable sigp emergency signal
+ oi 0(%r15),0x10 # switch on low address protection
+ lctl %c0,%c15,0(%r15)
+
+#
+ lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess
+ l %r14,.Lstart-.LPG3(%r13)
+ basr %r14,%r14 # call start_kernel
+#
+# We returned from start_kernel ?!? PANIK
+#
+ basr %r13,0
+ lpsw .Ldw-.(%r13) # load disabled wait psw
+#
+ .align 8
+.Ldw: .long 0x000a0000,0x00000000
+.Linittu:.long init_thread_union
+.Lstart:.long start_kernel
+.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 193aafa72f54..f08c06f45d5c 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -1,482 +1,17 @@
/*
- * arch/s390/kernel/head.S
+ * arch/s390/kernel/head64.S
*
- * S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Hartmut Penner (hp@de.ibm.com),
- * Martin Schwidefsky (schwidefsky@de.ibm.com),
- * Rob van der Heij (rvdhei@iae.nl)
+ * (C) Copyright IBM Corp. 1999,2005
+ *
+ * Author(s): Hartmut Penner <hp@de.ibm.com>
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>
+ * Rob van der Heij <rvdhei@iae.nl>
+ * Heiko Carstens <heiko.carstens@de.ibm.com>
*
- * There are 5 different IPL methods
- * 1) load the image directly into ram at address 0 and do an PSW restart
- * 2) linload will load the image from address 0x10000 to memory 0x10000
- * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
- * 3) generate the tape ipl header, store the generated image on a tape
- * and ipl from it
- * In case of SL tape you need to IPL 5 times to get past VOL1 etc
- * 4) generate the vm reader ipl header, move the generated image to the
- * VM reader (use option NOH!) and do a ipl from reader (VM only)
- * 5) direct call of start by the SALIPL loader
- * We use the cpuid to distinguish between VM and native ipl
- * params for kernel are pushed to 0x10400 (see setup.h)
-
- Changes:
- Okt 25 2000 <rvdheij@iae.nl>
- added code to skip HDR and EOF to allow SL tape IPL (5 retries)
- changed first CCW from rewind to backspace block
-
*/
-#include <linux/config.h>
-#include <asm/setup.h>
-#include <asm/lowcore.h>
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-#include <asm/page.h>
-
-#ifndef CONFIG_IPL
- .org 0
- .long 0x00080000,0x80000000+startup # Just a restart PSW
-#else
-#ifdef CONFIG_IPL_TAPE
-#define IPL_BS 1024
- .org 0
- .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
- .long 0x27000000,0x60000001 # by ipl to addresses 0-23.
- .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs).
- .long 0x00000000,0x00000000 # external old psw
- .long 0x00000000,0x00000000 # svc old psw
- .long 0x00000000,0x00000000 # program check old psw
- .long 0x00000000,0x00000000 # machine check old psw
- .long 0x00000000,0x00000000 # io old psw
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x00000000,0x00000000
- .long 0x000a0000,0x00000058 # external new psw
- .long 0x000a0000,0x00000060 # svc new psw
- .long 0x000a0000,0x00000068 # program check new psw
- .long 0x000a0000,0x00000070 # machine check new psw
- .long 0x00080000,0x80000000+.Lioint # io new psw
-
- .org 0x100
-#
-# subroutine for loading from tape
-# Paramters:
-# R1 = device number
-# R2 = load address
-.Lloader:
- st %r14,.Lldret
- la %r3,.Lorbread # r3 = address of orb
- la %r5,.Lirb # r5 = address of irb
- st %r2,.Lccwread+4 # initialize CCW data addresses
- lctl %c6,%c6,.Lcr6
- slr %r2,%r2
-.Lldlp:
- la %r6,3 # 3 retries
-.Lssch:
- ssch 0(%r3) # load chunk of IPL_BS bytes
- bnz .Llderr
-.Lw4end:
- bas %r14,.Lwait4io
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Lrecov
- slr %r7,%r7
- icm %r7,3,10(%r5) # get residual count
- lcr %r7,%r7
- la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read
- ar %r2,%r7 # add to total size
- tm 8(%r5),0x01 # found a tape mark ?
- bnz .Ldone
- l %r0,.Lccwread+4 # update CCW data addresses
- ar %r0,%r7
- st %r0,.Lccwread+4
- b .Lldlp
-.Ldone:
- l %r14,.Lldret
- br %r14 # r2 contains the total size
-.Lrecov:
- bas %r14,.Lsense # do the sensing
- bct %r6,.Lssch # dec. retry count & branch
- b .Llderr
-#
-# Sense subroutine
-#
-.Lsense:
- st %r14,.Lsnsret
- la %r7,.Lorbsense
- ssch 0(%r7) # start sense command
- bnz .Llderr
- bas %r14,.Lwait4io
- l %r14,.Lsnsret
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Llderr
- br %r14
-#
-# Wait for interrupt subroutine
-#
-.Lwait4io:
- lpsw .Lwaitpsw
-.Lioint:
- c %r1,0xb8 # compare subchannel number
- bne .Lwait4io
- tsch 0(%r5)
- slr %r0,%r0
- tm 8(%r5),0x82 # do we have a problem ?
- bnz .Lwtexit
- tm 8(%r5),0x04 # got device end ?
- bz .Lwait4io
-.Lwtexit:
- br %r14
-.Llderr:
- lpsw .Lcrash
-
- .align 8
-.Lorbread:
- .long 0x00000000,0x0080ff00,.Lccwread
- .align 8
-.Lorbsense:
- .long 0x00000000,0x0080ff00,.Lccwsense
- .align 8
-.Lccwread:
- .long 0x02200000+IPL_BS,0x00000000
-.Lccwsense:
- .long 0x04200001,0x00000000
-.Lwaitpsw:
- .long 0x020a0000,0x80000000+.Lioint
-
-.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6: .long 0xff000000
- .align 8
-.Lcrash:.long 0x000a0000,0x00000000
-.Lldret:.long 0
-.Lsnsret: .long 0
-#endif /* CONFIG_IPL_TAPE */
-
-#ifdef CONFIG_IPL_VM
-#define IPL_BS 0x730
- .org 0
- .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded
- .long 0x02000018,0x60000050 # by ipl to addresses 0-23.
- .long 0x02000068,0x60000050 # (a PSW and two CCWs).
- .fill 80-24,1,0x40 # bytes 24-79 are discarded !!
- .long 0x020000f0,0x60000050 # The next 160 byte are loaded
- .long 0x02000140,0x60000050 # to addresses 0x18-0xb7
- .long 0x02000190,0x60000050 # They form the continuation
- .long 0x020001e0,0x60000050 # of the CCW program started
- .long 0x02000230,0x60000050 # by ipl and load the range
- .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image
- .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730
- .long 0x02000320,0x60000050 # in memory. At the end of
- .long 0x02000370,0x60000050 # the channel program the PSW
- .long 0x020003c0,0x60000050 # at location 0 is loaded.
- .long 0x02000410,0x60000050 # Initial processing starts
- .long 0x02000460,0x60000050 # at 0xf0 = iplstart.
- .long 0x020004b0,0x60000050
- .long 0x02000500,0x60000050
- .long 0x02000550,0x60000050
- .long 0x020005a0,0x60000050
- .long 0x020005f0,0x60000050
- .long 0x02000640,0x60000050
- .long 0x02000690,0x60000050
- .long 0x020006e0,0x20000050
-
- .org 0xf0
-#
-# subroutine for loading cards from the reader
-#
-.Lloader:
- la %r3,.Lorb # r2 = address of orb into r2
- la %r5,.Lirb # r4 = address of irb
- la %r6,.Lccws
- la %r7,20
-.Linit:
- st %r2,4(%r6) # initialize CCW data addresses
- la %r2,0x50(%r2)
- la %r6,8(%r6)
- bct 7,.Linit
-
- lctl %c6,%c6,.Lcr6 # set IO subclass mask
- slr %r2,%r2
-.Lldlp:
- ssch 0(%r3) # load chunk of 1600 bytes
- bnz .Llderr
-.Lwait4irq:
- mvc 0x78(8),.Lnewpsw # set up IO interrupt psw
- lpsw .Lwaitpsw
-.Lioint:
- c %r1,0xb8 # compare subchannel number
- bne .Lwait4irq
- tsch 0(%r5)
-
- slr %r0,%r0
- ic %r0,8(%r5) # get device status
- chi %r0,8 # channel end ?
- be .Lcont
- chi %r0,12 # channel end + device end ?
- be .Lcont
-
- l %r0,4(%r5)
- s %r0,8(%r3) # r0/8 = number of ccws executed
- mhi %r0,10 # *10 = number of bytes in ccws
- lh %r3,10(%r5) # get residual count
- sr %r0,%r3 # #ccws*80-residual=#bytes read
- ar %r2,%r0
-
- br %r14 # r2 contains the total size
-
-.Lcont:
- ahi %r2,0x640 # add 0x640 to total size
- la %r6,.Lccws
- la %r7,20
-.Lincr:
- l %r0,4(%r6) # update CCW data addresses
- ahi %r0,0x640
- st %r0,4(%r6)
- ahi %r6,8
- bct 7,.Lincr
-
- b .Lldlp
-.Llderr:
- lpsw .Lcrash
-
- .align 8
-.Lorb: .long 0x00000000,0x0080ff00,.Lccws
-.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-.Lcr6: .long 0xff000000
-.Lloadp:.long 0,0
- .align 8
-.Lcrash:.long 0x000a0000,0x00000000
-.Lnewpsw:
- .long 0x00080000,0x80000000+.Lioint
-.Lwaitpsw:
- .long 0x020a0000,0x80000000+.Lioint
-
- .align 8
-.Lccws: .rept 19
- .long 0x02600050,0x00000000
- .endr
- .long 0x02200050,0x00000000
-#endif /* CONFIG_IPL_VM */
-
-iplstart:
- lh %r1,0xb8 # test if subchannel number
- bct %r1,.Lnoload # is valid
- l %r1,0xb8 # load ipl subchannel number
- la %r2,IPL_BS # load start address
- bas %r14,.Lloader # load rest of ipl image
- larl %r12,_pstart # pointer to parameter area
- st %r1,IPL_DEVICE+4-PARMAREA(%r12) # store ipl device number
-
-#
-# load parameter file from ipl device
#
-.Lagain1:
- l %r2,INITRD_START+4-PARMAREA(%r12)# use ramdisk location as temp
- bas %r14,.Lloader # load parameter file
- ltr %r2,%r2 # got anything ?
- bz .Lnopf
- chi %r2,895
- bnh .Lnotrunc
- la %r2,895
-.Lnotrunc:
- l %r4,INITRD_START+4-PARMAREA(%r12)
- clc 0(3,%r4),.L_hdr # if it is HDRx
- bz .Lagain1 # skip dataset header
- clc 0(3,%r4),.L_eof # if it is EOFx
- bz .Lagain1 # skip dateset trailer
- la %r5,0(%r4,%r2)
- lr %r3,%r2
-.Lidebc:
- tm 0(%r5),0x80 # high order bit set ?
- bo .Ldocv # yes -> convert from EBCDIC
- ahi %r5,-1
- bct %r3,.Lidebc
- b .Lnocv
-.Ldocv:
- l %r3,.Lcvtab
- tr 0(256,%r4),0(%r3) # convert parameters to ascii
- tr 256(256,%r4),0(%r3)
- tr 512(256,%r4),0(%r3)
- tr 768(122,%r4),0(%r3)
-.Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line
- mvc 0(256,%r3),0(%r4)
- mvc 256(256,%r3),256(%r4)
- mvc 512(256,%r3),512(%r4)
- mvc 768(122,%r3),768(%r4)
- slr %r0,%r0
- b .Lcntlp
-.Ldelspc:
- ic %r0,0(%r2,%r3)
- chi %r0,0x20 # is it a space ?
- be .Lcntlp
- ahi %r2,1
- b .Leolp
-.Lcntlp:
- brct %r2,.Ldelspc
-.Leolp:
- slr %r0,%r0
- stc %r0,0(%r2,%r3) # terminate buffer
-.Lnopf:
-
-#
-# load ramdisk from ipl device
-#
-.Lagain2:
- l %r2,INITRD_START+4-PARMAREA(%r12)# load adr. of ramdisk
- bas %r14,.Lloader # load ramdisk
- st %r2,INITRD_SIZE+4-PARMAREA(%r12) # store size of ramdisk
- ltr %r2,%r2
- bnz .Lrdcont
- st %r2,INITRD_START+4-PARMAREA(%r12)# no ramdisk found, null it
-.Lrdcont:
- l %r2,INITRD_START+4-PARMAREA(%r12)
- clc 0(3,%r2),.L_hdr # skip HDRx and EOFx
- bz .Lagain2
- clc 0(3,%r2),.L_eof
- bz .Lagain2
-
-#ifdef CONFIG_IPL_VM
-#
-# reset files in VM reader
-#
- stidp __LC_CPUID # store cpuid
- tm __LC_CPUID,0xff # running VM ?
- bno .Lnoreset
- la %r2,.Lreset
- lhi %r3,26
- diag %r2,%r3,8
- la %r5,.Lirb
- stsch 0(%r5) # check if irq is pending
- tm 30(%r5),0x0f # by verifying if any of the
- bnz .Lwaitforirq # activity or status control
- tm 31(%r5),0xff # bits is set in the schib
- bz .Lnoreset
-.Lwaitforirq:
- mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw
-.Lwaitrdrirq:
- lpsw .Lrdrwaitpsw
-.Lrdrint:
- c %r1,0xb8 # compare subchannel number
- bne .Lwaitrdrirq
- la %r5,.Lirb
- tsch 0(%r5)
-.Lnoreset:
- b .Lnoload
-
- .align 8
-.Lrdrnewpsw:
- .long 0x00080000,0x80000000+.Lrdrint
-.Lrdrwaitpsw:
- .long 0x020a0000,0x80000000+.Lrdrint
-#endif
-
-#
-# everything loaded, go for it
-#
-.Lnoload:
- l %r1,.Lstartup
- br %r1
-
-.Lstartup: .long startup
-.Lcvtab:.long _ebcasc # ebcdic to ascii table
-.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
- .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
- .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold"
-.L_eof: .long 0xc5d6c600 /* C'EOF' */
-.L_hdr: .long 0xc8c4d900 /* C'HDR' */
-#endif /* CONFIG_IPL */
-
-#
-# SALIPL loader support. Based on a patch by Rob van der Heij.
-# This entry point is called directly from the SALIPL loader and
-# doesn't need a builtin ipl record.
-#
- .org 0x800
- .globl start
-start:
- stm %r0,%r15,0x07b0 # store registers
- basr %r12,%r0
-.base:
- l %r11,.parm
- l %r8,.cmd # pointer to command buffer
-
- ltr %r9,%r9 # do we have SALIPL parameters?
- bp .sk8x8
-
- mvc 0(64,%r8),0x00b0 # copy saved registers
- xc 64(240-64,%r8),0(%r8) # remainder of buffer
- tr 0(64,%r8),.lowcase
- b .gotr
-.sk8x8:
- mvc 0(240,%r8),0(%r9) # copy iplparms into buffer
-.gotr:
- l %r10,.tbl # EBCDIC to ASCII table
- tr 0(240,%r8),0(%r10)
- stidp __LC_CPUID # Are we running on VM maybe
- cli __LC_CPUID,0xff
- bnz .test
- .long 0x83300060 # diag 3,0,x'0060' - storage size
- b .done
-.test:
- mvc 0x68(8),.pgmnw # set up pgm check handler
- l %r2,.fourmeg
- lr %r3,%r2
- bctr %r3,%r0 # 4M-1
-.loop: iske %r0,%r3
- ar %r3,%r2
-.pgmx:
- sr %r3,%r2
- la %r3,1(%r3)
-.done:
- l %r1,.memsize
- st %r3,4(%r1)
- slr %r0,%r0
- st %r0,INITRD_SIZE+4-PARMAREA(%r11)
- st %r0,INITRD_START+4-PARMAREA(%r11)
- j startup # continue with startup
-.tbl: .long _ebcasc # translate table
-.cmd: .long COMMAND_LINE # address of command line buffer
-.parm: .long PARMAREA
-.fourmeg: .long 0x00400000 # 4M
-.pgmnw: .long 0x00080000,.pgmx
-.memsize: .long memory_size
-.lowcase:
- .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07
- .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
- .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17
- .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
- .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
- .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
- .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37
- .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
- .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47
- .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
- .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57
- .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
- .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67
- .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
- .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77
- .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
-
- .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87
- .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
- .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97
- .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
- .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7
- .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
- .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7
- .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
- .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87 # .abcdefg
- .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf # hi
- .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 # .jklmnop
- .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf # qr
- .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 # ..stuvwx
- .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef # yz
- .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7
- .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
-
-#
-# startup-code at 0x10000, running in real mode
+# startup-code at 0x10000, running in absolute addressing mode
# this is called either by the ipl loader or directly by PSW restart
# or linload or SALIPL
#
@@ -530,7 +65,7 @@ startup:basr %r13,0 # get base
be .Lfchunk-.LPG1(%r13) # leave
chi %r1,2
be .Lservicecall-.LPG1(%r13)
- lpsw .Lwaitsclp-.LPG1(%r13)
+ lpswe .Lwaitsclp-.LPG1(%r13)
.Lsclph:
lh %r1,.Lsccbr-PARMAREA(%r4)
chi %r1,0x10 # 0x0010 is the sucess code
@@ -567,8 +102,7 @@ startup:basr %r13,0 # get base
.Lcr:
.quad 0x00 # place holder for cr0
.Lwaitsclp:
- .long 0x020A0000
- .quad .Lsclph
+ .quad 0x0102000180000000,.Lsclph
.Lrcp:
.int 0x00120001 # Read SCP forced code
.Lrcp2:
@@ -751,62 +285,7 @@ _pstart:
.global _pend
_pend:
-.Lget_ipl_device:
- basr %r12,0
-.LPG2: l %r1,0xb8 # get sid
- sll %r1,15 # test if subchannel is enabled
- srl %r1,31
- ltr %r1,%r1
- bz 0(%r14) # subchannel disabled
- l %r1,0xb8
- la %r5,.Lipl_schib-.LPG2(%r12)
- stsch 0(%r5) # get schib of subchannel
- bnz 0(%r14) # schib not available
- tm 5(%r5),0x01 # devno valid?
- bno 0(%r14)
- la %r6,ipl_parameter_flags-.LPG2(%r12)
- oi 3(%r6),0x01 # set flag
- la %r2,ipl_devno-.LPG2(%r12)
- mvc 0(2,%r2),6(%r5) # store devno
- tm 4(%r5),0x80 # qdio capable device?
- bno 0(%r14)
- oi 3(%r6),0x02 # set flag
-
- # copy ipl parameters
-
- lhi %r0,4096
- l %r2,20(%r0) # get address of parameter list
- lhi %r3,IPL_PARMBLOCK_ORIGIN
- st %r3,20(%r0)
- lhi %r4,1
- cr %r2,%r3 # start parameters < destination ?
- jl 0f
- lhi %r1,1 # copy direction is upwards
- j 1f
-0: lhi %r1,-1 # copy direction is downwards
- ar %r2,%r0
- ar %r3,%r0
- ar %r2,%r1
- ar %r3,%r1
-1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters
- ar %r3,%r1
- ar %r2,%r1
- sr %r0,%r4
- jne 1b
- b 0(%r14)
-
- .align 4
-.Lipl_schib:
- .rept 13
- .long 0
- .endr
-
- .globl ipl_parameter_flags
-ipl_parameter_flags:
- .long 0
- .globl ipl_devno
-ipl_devno:
- .word 0
+ GET_IPL_DEVICE
#ifdef CONFIG_SHARED_KERNEL
.org 0x100000
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9a1d95894f3d..c36353e8c140 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -237,6 +237,8 @@ int sysctl_hz_timer = 1;
*/
static inline void stop_hz_timer(void)
{
+ unsigned long flags;
+ unsigned long seq, next;
__u64 timer, todval;
if (sysctl_hz_timer != 0)
@@ -257,7 +259,11 @@ static inline void stop_hz_timer(void)
* This cpu is going really idle. Set up the clock comparator
* for the next event.
*/
- timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
+ next = next_timer_interrupt();
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ timer = (__u64)(next - jiffies) + jiffies_64;
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
todval = -1ULL;
/* Be careful about overflows. */
if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 6b8703ec2ae6..c5bd36fae56b 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -57,7 +57,6 @@ int sysctl_userprocess_debug = 0;
extern pgm_check_handler_t do_protection_exception;
extern pgm_check_handler_t do_dat_exception;
-extern pgm_check_handler_t do_pseudo_page_fault;
#ifdef CONFIG_PFAULT
extern int pfault_init(void);
extern void pfault_fini(void);
@@ -676,20 +675,6 @@ asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
panic("Corrupt kernel stack, can't continue.");
}
-#ifndef CONFIG_ARCH_S390X
-static int
-pagex_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
- if (MACHINE_IS_VM)
- cpcmd("SET PAGEX OFF", NULL, 0, NULL);
- return NOTIFY_DONE;
-}
-
-static struct notifier_block pagex_reboot_notifier = {
- .notifier_call = &pagex_reboot_event,
-};
-#endif
-
/* init is done in lowcore.S and head.S */
void __init trap_init(void)
@@ -717,9 +702,7 @@ void __init trap_init(void)
pgm_check_table[0x11] = &do_dat_exception;
pgm_check_table[0x12] = &translation_exception;
pgm_check_table[0x13] = &special_op_exception;
-#ifndef CONFIG_ARCH_S390X
- pgm_check_table[0x14] = &do_pseudo_page_fault;
-#else /* CONFIG_ARCH_S390X */
+#ifdef CONFIG_ARCH_S390X
pgm_check_table[0x38] = &do_dat_exception;
pgm_check_table[0x39] = &do_dat_exception;
pgm_check_table[0x3A] = &do_dat_exception;
@@ -731,12 +714,10 @@ void __init trap_init(void)
pgm_check_table[0x40] = &do_monitor_call;
if (MACHINE_IS_VM) {
+#ifdef CONFIG_PFAULT
/*
- * First try to get pfault pseudo page faults going.
- * If this isn't available turn on pagex page faults.
+ * Try to get pfault pseudo page faults going.
*/
-#ifdef CONFIG_PFAULT
- /* request the 0x2603 external interrupt */
if (register_early_external_interrupt(0x2603, pfault_interrupt,
&ext_int_pfault) != 0)
panic("Couldn't request external interrupt 0x2603");
@@ -748,9 +729,5 @@ void __init trap_init(void)
unregister_early_external_interrupt(0x2603, pfault_interrupt,
&ext_int_pfault);
#endif
-#ifndef CONFIG_ARCH_S390X
- register_reboot_notifier(&pagex_reboot_notifier);
- cpcmd("SET PAGEX ON", NULL, 0, NULL);
-#endif
}
}
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index c5348108ca3c..506a33b51e4f 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -234,8 +234,8 @@ query_segment_type (struct dcss_segment *seg)
rc = 0;
out_free:
- if (qin) kfree(qin);
- if (qout) kfree(qout);
+ kfree(qin);
+ kfree(qout);
return rc;
}
@@ -394,7 +394,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
segtype_string[seg->vm_segtype]);
goto out;
out_free:
- kfree (seg);
+ kfree(seg);
out:
return rc;
}
@@ -505,7 +505,7 @@ segment_modify_shared (char *name, int do_nonshared)
list_del(&seg->list);
dcss_diag(DCSS_PURGESEG, seg->dcss_name,
&dummy, &dummy);
- kfree (seg);
+ kfree(seg);
out_unlock:
spin_unlock(&dcss_lock);
return rc;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 856a971759b1..64e32da77754 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -352,115 +352,6 @@ void do_dat_exception(struct pt_regs *regs, unsigned long error_code)
do_exception(regs, error_code & 0xff, 0);
}
-#ifndef CONFIG_ARCH_S390X
-
-typedef struct _pseudo_wait_t {
- struct _pseudo_wait_t *next;
- wait_queue_head_t queue;
- unsigned long address;
- int resolved;
-} pseudo_wait_t;
-
-static pseudo_wait_t *pseudo_lock_queue = NULL;
-static spinlock_t pseudo_wait_spinlock; /* spinlock to protect lock queue */
-
-/*
- * This routine handles 'pagex' pseudo page faults.
- */
-asmlinkage void
-do_pseudo_page_fault(struct pt_regs *regs, unsigned long error_code)
-{
- pseudo_wait_t wait_struct;
- pseudo_wait_t *ptr, *last, *next;
- unsigned long address;
-
- /*
- * get the failing address
- * more specific the segment and page table portion of
- * the address
- */
- address = S390_lowcore.trans_exc_code & 0xfffff000;
-
- if (address & 0x80000000) {
- /* high bit set -> a page has been swapped in by VM */
- address &= 0x7fffffff;
- spin_lock(&pseudo_wait_spinlock);
- last = NULL;
- ptr = pseudo_lock_queue;
- while (ptr != NULL) {
- next = ptr->next;
- if (address == ptr->address) {
- /*
- * This is one of the processes waiting
- * for the page. Unchain from the queue.
- * There can be more than one process
- * waiting for the same page. VM presents
- * an initial and a completion interrupt for
- * every process that tries to access a
- * page swapped out by VM.
- */
- if (last == NULL)
- pseudo_lock_queue = next;
- else
- last->next = next;
- /* now wake up the process */
- ptr->resolved = 1;
- wake_up(&ptr->queue);
- } else
- last = ptr;
- ptr = next;
- }
- spin_unlock(&pseudo_wait_spinlock);
- } else {
- /* Pseudo page faults in kernel mode is a bad idea */
- if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
- /*
- * VM presents pseudo page faults if the interrupted
- * state was not disabled for interrupts. So we can
- * get pseudo page fault interrupts while running
- * in kernel mode. We simply access the page here
- * while we are running disabled. VM will then swap
- * in the page synchronously.
- */
- if (check_user_space(regs, error_code) == 0)
- /* dereference a virtual kernel address */
- __asm__ __volatile__ (
- " ic 0,0(%0)"
- : : "a" (address) : "0");
- else
- /* dereference a virtual user address */
- __asm__ __volatile__ (
- " la 2,0(%0)\n"
- " sacf 512\n"
- " ic 2,0(2)\n"
- "0:sacf 0\n"
- ".section __ex_table,\"a\"\n"
- " .align 4\n"
- " .long 0b,0b\n"
- ".previous"
- : : "a" (address) : "2" );
-
- return;
- }
- /* initialize and add element to pseudo_lock_queue */
- init_waitqueue_head (&wait_struct.queue);
- wait_struct.address = address;
- wait_struct.resolved = 0;
- spin_lock(&pseudo_wait_spinlock);
- wait_struct.next = pseudo_lock_queue;
- pseudo_lock_queue = &wait_struct;
- spin_unlock(&pseudo_wait_spinlock);
- /*
- * The instruction that caused the program check will
- * be repeated. Don't signal single step via SIGTRAP.
- */
- clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
- /* go to sleep */
- wait_event(wait_struct.queue, wait_struct.resolved);
- }
-}
-#endif /* CONFIG_ARCH_S390X */
-
#ifdef CONFIG_PFAULT
/*
* 'pfault' pseudo page faults routines.
@@ -508,7 +399,7 @@ int pfault_init(void)
" .quad 0b,1b\n"
#endif /* CONFIG_ARCH_S390X */
".previous"
- : "=d" (rc) : "a" (&refbk) : "cc" );
+ : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" );
__ctl_set_bit(0, 9);
return rc;
}
@@ -532,7 +423,7 @@ void pfault_fini(void)
" .quad 0b,0b\n"
#endif /* CONFIG_ARCH_S390X */
".previous"
- : : "a" (&refbk) : "cc" );
+ : : "a" (&refbk), "m" (refbk) : "cc" );
}
asmlinkage void
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3e804c736e64..64f5ae0ff96d 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -490,16 +490,6 @@ config CPU_SUBTYPE_ST40
depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1
default y
-config ARCH_DISCONTIGMEM_ENABLE
- bool
- depends on SH_HP690
- default y
- help
- Say Y to upport efficient handling of discontiguous physical memory,
- for architectures which are either NUMA (Non-Uniform Memory Access)
- or have huge holes in the physical address space for other reasons.
- See <file:Documentation/vm/numa> for more.
-
source "mm/Kconfig"
config ZERO_PAGE_OFFSET
@@ -770,24 +760,6 @@ source "fs/Kconfig.binfmt"
endmenu
-menu "SH initrd options"
- depends on BLK_DEV_INITRD
-
-config EMBEDDED_RAMDISK
- bool "Embed root filesystem ramdisk into the kernel"
-
-config EMBEDDED_RAMDISK_IMAGE
- string "Filename of gziped ramdisk image"
- depends on EMBEDDED_RAMDISK
- default "ramdisk.gz"
- help
- This is the filename of the ramdisk image to be built into the
- kernel. Relative pathnames are relative to arch/sh/ramdisk/.
- The ramdisk image is not part of the kernel distribution; you must
- provide one yourself.
-
-endmenu
-
source "net/Kconfig"
source "drivers/Kconfig"
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 4a3049080b41..67192d6b00d8 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -60,14 +60,6 @@ LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
core-y += arch/sh/kernel/ arch/sh/mm/
-#
-# ramdisk/initrd support
-# You need a compressed ramdisk image, named
-# CONFIG_EMBEDDED_RAMDISK_IMAGE. Relative pathnames
-# are relative to arch/sh/ramdisk/.
-#
-core-$(CONFIG_EMBEDDED_RAMDISK) += arch/sh/ramdisk/
-
# Boards
machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x
machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751
diff --git a/arch/sh/drivers/Makefile b/arch/sh/drivers/Makefile
index bd6726cde398..338c3729d270 100644
--- a/arch/sh/drivers/Makefile
+++ b/arch/sh/drivers/Makefile
@@ -2,6 +2,7 @@
# Makefile for the Linux SuperH-specific device drivers.
#
-obj-$(CONFIG_PCI) += pci/
-obj-$(CONFIG_SH_DMA) += dma/
+obj-$(CONFIG_PCI) += pci/
+obj-$(CONFIG_SH_DMA) += dma/
+obj-$(CONFIG_SUPERHYWAY) += superhyway/
diff --git a/arch/sh/drivers/superhyway/Makefile b/arch/sh/drivers/superhyway/Makefile
new file mode 100644
index 000000000000..5b8e0c7ca3a5
--- /dev/null
+++ b/arch/sh/drivers/superhyway/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperHyway specific kernel interface routines under Linux.
+#
+
+obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += ops-sh4-202.o
+
diff --git a/arch/sh/drivers/superhyway/ops-sh4-202.c b/arch/sh/drivers/superhyway/ops-sh4-202.c
new file mode 100644
index 000000000000..a55c98a9052b
--- /dev/null
+++ b/arch/sh/drivers/superhyway/ops-sh4-202.c
@@ -0,0 +1,171 @@
+/*
+ * arch/sh/drivers/superhyway/ops-sh4-202.c
+ *
+ * SuperHyway bus support for SH4-202
+ *
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/superhyway.h>
+#include <linux/string.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+#define PHYS_EMI_CBLOCK P4SEGADDR(0x1ec00000)
+#define PHYS_EMI_DBLOCK P4SEGADDR(0x08000000)
+#define PHYS_FEMI_CBLOCK P4SEGADDR(0x1f800000)
+#define PHYS_FEMI_DBLOCK P4SEGADDR(0x00000000)
+
+#define PHYS_EPBR_BLOCK P4SEGADDR(0x1de00000)
+#define PHYS_DMAC_BLOCK P4SEGADDR(0x1fa00000)
+#define PHYS_PBR_BLOCK P4SEGADDR(0x1fc00000)
+
+static struct resource emi_resources[] = {
+ [0] = {
+ .start = PHYS_EMI_CBLOCK,
+ .end = PHYS_EMI_CBLOCK + 0x00300000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PHYS_EMI_DBLOCK,
+ .end = PHYS_EMI_DBLOCK + 0x08000000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct superhyway_device emi_device = {
+ .name = "emi",
+ .num_resources = ARRAY_SIZE(emi_resources),
+ .resource = emi_resources,
+};
+
+static struct resource femi_resources[] = {
+ [0] = {
+ .start = PHYS_FEMI_CBLOCK,
+ .end = PHYS_FEMI_CBLOCK + 0x00100000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PHYS_FEMI_DBLOCK,
+ .end = PHYS_FEMI_DBLOCK + 0x08000000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct superhyway_device femi_device = {
+ .name = "femi",
+ .num_resources = ARRAY_SIZE(femi_resources),
+ .resource = femi_resources,
+};
+
+static struct resource epbr_resources[] = {
+ [0] = {
+ .start = P4SEGADDR(0x1e7ffff8),
+ .end = P4SEGADDR(0x1e7ffff8 + (sizeof(u32) * 2) - 1),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PHYS_EPBR_BLOCK,
+ .end = PHYS_EPBR_BLOCK + 0x00a00000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct superhyway_device epbr_device = {
+ .name = "epbr",
+ .num_resources = ARRAY_SIZE(epbr_resources),
+ .resource = epbr_resources,
+};
+
+static struct resource dmac_resource = {
+ .start = PHYS_DMAC_BLOCK,
+ .end = PHYS_DMAC_BLOCK + 0x00100000 - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct superhyway_device dmac_device = {
+ .name = "dmac",
+ .num_resources = 1,
+ .resource = &dmac_resource,
+};
+
+static struct resource pbr_resources[] = {
+ [0] = {
+ .start = P4SEGADDR(0x1ffffff8),
+ .end = P4SEGADDR(0x1ffffff8 + (sizeof(u32) * 2) - 1),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PHYS_PBR_BLOCK,
+ .end = PHYS_PBR_BLOCK + 0x00400000 - (sizeof(u32) * 2) - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct superhyway_device pbr_device = {
+ .name = "pbr",
+ .num_resources = ARRAY_SIZE(pbr_resources),
+ .resource = pbr_resources,
+};
+
+static struct superhyway_device *sh4202_devices[] __initdata = {
+ &emi_device, &femi_device, &epbr_device, &dmac_device, &pbr_device,
+};
+
+static int sh4202_read_vcr(unsigned long base, struct superhyway_vcr_info *vcr)
+{
+ u32 vcrh, vcrl;
+ u64 tmp;
+
+ /*
+ * XXX: Even though the SH4-202 Evaluation Device documentation
+ * indicates that VCRL is mapped first with VCRH at a + 0x04
+ * offset, the opposite seems to be true.
+ *
+ * Some modules (PBR and ePBR for instance) also appear to have
+ * VCRL/VCRH flipped in the documentation, but on the SH4-202
+ * itself it appears that these are all consistently mapped with
+ * VCRH preceeding VCRL.
+ *
+ * Do not trust the documentation, for it is evil.
+ */
+ vcrh = ctrl_inl(base);
+ vcrl = ctrl_inl(base + sizeof(u32));
+
+ tmp = ((u64)vcrh << 32) | vcrl;
+ memcpy(vcr, &tmp, sizeof(u64));
+
+ return 0;
+}
+
+static int sh4202_write_vcr(unsigned long base, struct superhyway_vcr_info vcr)
+{
+ u64 tmp = *(u64 *)&vcr;
+
+ ctrl_outl((tmp >> 32) & 0xffffffff, base);
+ ctrl_outl(tmp & 0xffffffff, base + sizeof(u32));
+
+ return 0;
+}
+
+static struct superhyway_ops sh4202_superhyway_ops = {
+ .read_vcr = sh4202_read_vcr,
+ .write_vcr = sh4202_write_vcr,
+};
+
+struct superhyway_bus superhyway_channels[] = {
+ { &sh4202_superhyway_ops, },
+ { 0, },
+};
+
+int __init superhyway_scan_bus(struct superhyway_bus *bus)
+{
+ return superhyway_add_devices(bus, sh4202_devices,
+ ARRAY_SIZE(sh4202_devices));
+}
+
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
index 1fbe5a428e31..1a8be06519ec 100644
--- a/arch/sh/kernel/ptrace.c
+++ b/arch/sh/kernel/ptrace.c
@@ -80,48 +80,11 @@ void ptrace_disable(struct task_struct *child)
/* nothing to do.. */
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
struct user * dummy = NULL;
int ret;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -289,10 +252,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+
return ret;
}
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 25b9d9ebe858..036050b377cd 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -83,9 +83,9 @@ static struct sh_machine_vector* __init get_mv_byname(const char* name);
/* ... */
#define COMMAND_LINE ((char *) (PARAM+0x100))
-#define RAMDISK_IMAGE_START_MASK 0x07FF
+#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
-#define RAMDISK_LOAD_FLAG 0x4000
+#define RAMDISK_LOAD_FLAG 0x4000
static char command_line[COMMAND_LINE_SIZE] = { 0, };
@@ -284,18 +284,6 @@ void __init setup_arch(char **cmdline_p)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
-#ifdef CONFIG_DISCONTIGMEM
- NODE_DATA(0)->bdata = &discontig_node_bdata[0];
- NODE_DATA(1)->bdata = &discontig_node_bdata[1];
-
- bootmap_size = init_bootmem_node(NODE_DATA(1),
- PFN_UP(__MEMORY_START_2ND),
- PFN_UP(__MEMORY_START_2ND),
- PFN_DOWN(__MEMORY_START_2ND+__MEMORY_SIZE_2ND));
- free_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, __MEMORY_SIZE_2ND);
- reserve_bootmem_node(NODE_DATA(1), __MEMORY_START_2ND, bootmap_size);
-#endif
-
/*
* Find the highest page frame number we have available
*/
@@ -306,10 +294,10 @@ void __init setup_arch(char **cmdline_p)
*/
max_low_pfn = max_pfn;
- /*
+ /*
* Partially used pages are not usable - thus
* we are rounding upwards:
- */
+ */
start_pfn = PFN_UP(__pa(_end));
/*
@@ -360,12 +348,12 @@ void __init setup_arch(char **cmdline_p)
reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
#ifdef CONFIG_BLK_DEV_INITRD
- ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
- if (&__rd_start != &__rd_end) {
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ if (&__rd_start != &__rd_end) {
LOADER_TYPE = 1;
INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START;
INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start;
- }
+ }
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 4e9c854845a4..e342565f75fb 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -51,11 +51,6 @@ unsigned long mmu_context_cache = NO_CONTEXT;
#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn)
#endif
-#ifdef CONFIG_DISCONTIGMEM
-pg_data_t discontig_page_data[MAX_NUMNODES];
-bootmem_data_t discontig_node_bdata[MAX_NUMNODES];
-#endif
-
void (*copy_page)(void *from, void *to);
void (*clear_page)(void *to);
@@ -216,15 +211,6 @@ void __init paging_init(void)
#endif
NODE_DATA(0)->node_mem_map = NULL;
free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
-
-#ifdef CONFIG_DISCONTIGMEM
- /*
- * And for discontig, do some more fixups on the zone sizes..
- */
- zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
- zones_size[ZONE_NORMAL] = 0;
- free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
-#endif
}
void __init mem_init(void)
@@ -248,7 +234,7 @@ void __init mem_init(void)
memset(empty_zero_page, 0, PAGE_SIZE);
__flush_wback_region(empty_zero_page, PAGE_SIZE);
- /*
+ /*
* Setup wrappers for copy/clear_page(), these will get overridden
* later in the boot process if a better method is available.
*/
@@ -257,9 +243,6 @@ void __init mem_init(void)
/* this will put all low memory onto the freelists */
totalram_pages += free_all_bootmem_node(NODE_DATA(0));
-#ifdef CONFIG_DISCONTIGMEM
- totalram_pages += free_all_bootmem_node(NODE_DATA(1));
-#endif
reservedpages = 0;
for (tmp = 0; tmp < num_physpages; tmp++)
/*
@@ -286,7 +269,7 @@ void __init mem_init(void)
void free_initmem(void)
{
unsigned long addr;
-
+
addr = (unsigned long)(&__init_begin);
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c
index 7a0d5c10bf20..46b09e26e082 100644
--- a/arch/sh/mm/tlb-sh3.c
+++ b/arch/sh/mm/tlb-sh3.c
@@ -40,12 +40,17 @@ void update_mmu_cache(struct vm_area_struct * vma,
return;
#if defined(CONFIG_SH7705_CACHE_32KB)
- struct page *page;
- page = pte_page(pte);
- if (VALID_PAGE(page) && !test_bit(PG_mapped, &page->flags)) {
- unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
- __flush_wback_region((void *)P1SEGADDR(phys), PAGE_SIZE);
- __set_bit(PG_mapped, &page->flags);
+ {
+ struct page *page = pte_page(pte);
+ unsigned long pfn = pte_pfn(pte);
+
+ if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) {
+ unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
+
+ __flush_wback_region((void *)P1SEGADDR(phys),
+ PAGE_SIZE);
+ __set_bit(PG_mapped, &page->flags);
+ }
}
#endif
@@ -80,7 +85,7 @@ void __flush_tlb_page(unsigned long asid, unsigned long page)
*/
addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000);
data = (page & 0xfffe0000) | asid; /* VALID bit is off */
-
+
if ((cpu_data->flags & CPU_HAS_MMU_PAGE_ASSOC)) {
addr |= MMU_PAGE_ASSOC_BIT;
ways = 1; /* we already know the way .. */
diff --git a/arch/sh/ramdisk/Makefile b/arch/sh/ramdisk/Makefile
deleted file mode 100644
index 99e1c68673cf..000000000000
--- a/arch/sh/ramdisk/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Makefile for a ramdisk image
-#
-
-obj-y += ramdisk.o
-
-
-O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32)
-img := $(subst ",,$(CONFIG_EMBEDDED_RAMDISK_IMAGE))
-# add $(src) when $(img) is relative
-img := $(subst $(src)//,/,$(src)/$(img))
-
-quiet_cmd_ramdisk = LD $@
-define cmd_ramdisk
- $(LD) -T $(srctree)/$(src)/ld.script -b binary --oformat $(O_FORMAT) \
- -o $@ $(img)
-endef
-
-$(obj)/ramdisk.o: $(img) $(srctree)/$(src)/ld.script
- $(call cmd,ramdisk)
diff --git a/arch/sh/ramdisk/ld.script b/arch/sh/ramdisk/ld.script
deleted file mode 100644
index 94beee248c04..000000000000
--- a/arch/sh/ramdisk/ld.script
+++ /dev/null
@@ -1,9 +0,0 @@
-OUTPUT_ARCH(sh)
-SECTIONS
-{
- .initrd :
- {
- *(.data)
- }
-}
-
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 71f2eec00b99..cd22e9471316 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -28,6 +28,7 @@
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/signal.h>
+#include <linux/syscalls.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -121,61 +122,11 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data)
return 0;
}
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
- extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
-#define WPC_DBRMODE 0x0d104008
- static int first_call = 1;
int ret;
- lock_kernel();
-
- if (first_call) {
- /* Set WPC.DBRMODE to 0. This makes all debug events get
- * delivered through RESVEC, i.e. into the handlers in entry.S.
- * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
- * would normally be left set to 1, which makes debug events get
- * delivered through DBRVEC, i.e. into the remote gdb's
- * handlers. This prevents ptrace getting them, and confuses
- * the remote gdb.) */
- printk("DBRMODE set to 0 to permit native debugging\n");
- poke_real_address_q(WPC_DBRMODE, 0);
- first_call = 0;
- }
-
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -313,13 +264,33 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
return ret;
}
+asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
+{
+ extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
+#define WPC_DBRMODE 0x0d104008
+ static int first_call = 1;
+
+ lock_kernel();
+ if (first_call) {
+ /* Set WPC.DBRMODE to 0. This makes all debug events get
+ * delivered through RESVEC, i.e. into the handlers in entry.S.
+ * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
+ * would normally be left set to 1, which makes debug events get
+ * delivered through DBRVEC, i.e. into the remote gdb's
+ * handlers. This prevents ptrace getting them, and confuses
+ * the remote gdb.) */
+ printk("DBRMODE set to 0 to permit native debugging\n");
+ poke_real_address_q(WPC_DBRMODE, 0);
+ first_call = 0;
+ }
+ unlock_kernel();
+
+ return sys_ptrace(request, pid, addr, data);
+}
+
asmlinkage void syscall_trace(void)
{
struct task_struct *tsk = current;
diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S
index a3d037805f1c..c0079d54c850 100644
--- a/arch/sh64/kernel/syscalls.S
+++ b/arch/sh64/kernel/syscalls.S
@@ -46,7 +46,7 @@ sys_call_table:
.long sys_setuid16
.long sys_getuid16
.long sys_stime /* 25 */
- .long sys_ptrace
+ .long sh64_ptrace
.long sys_alarm
.long sys_fstat
.long sys_pause
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 1e9d8638a28a..3fded69b1922 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -377,8 +377,21 @@ source "drivers/fc4/Kconfig"
source "fs/Kconfig"
+menu "Instrumentation Support"
+ depends on EXPERIMENTAL
+
source "arch/sparc64/oprofile/Kconfig"
+config KPROBES
+ bool "Kprobes (EXPERIMENTAL)"
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+endmenu
+
source "arch/sparc64/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug
index fa06ea04837b..3e31be494e54 100644
--- a/arch/sparc64/Kconfig.debug
+++ b/arch/sparc64/Kconfig.debug
@@ -11,16 +11,6 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
-config KPROBES
- bool "Kprobes"
- depends on DEBUG_KERNEL
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
config DEBUG_DCFLUSH
bool "D-cache flush debugging"
depends on DEBUG_KERNEL
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 0d66d07c8c6e..96bd09b098f4 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -38,6 +38,9 @@
* - Mark that we are no longer actively in a kprobe.
*/
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
int __kprobes arch_prepare_kprobe(struct kprobe *p)
{
return 0;
@@ -66,46 +69,39 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
{
}
-static struct kprobe *current_kprobe;
-static unsigned long current_kprobe_orig_tnpc;
-static unsigned long current_kprobe_orig_tstate_pil;
-static unsigned int kprobe_status;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_orig_tnpc_prev;
-static unsigned long kprobe_orig_tstate_pil_prev;
-static unsigned int kprobe_status_prev;
-
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- kprobe_status_prev = kprobe_status;
- kprobe_orig_tnpc_prev = current_kprobe_orig_tnpc;
- kprobe_orig_tstate_pil_prev = current_kprobe_orig_tstate_pil;
- kprobe_prev = current_kprobe;
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
+ kcb->prev_kprobe.orig_tnpc = kcb->kprobe_orig_tnpc;
+ kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
}
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- kprobe_status = kprobe_status_prev;
- current_kprobe_orig_tnpc = kprobe_orig_tnpc_prev;
- current_kprobe_orig_tstate_pil = kprobe_orig_tstate_pil_prev;
- current_kprobe = kprobe_prev;
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+ kcb->kprobe_status = kcb->prev_kprobe.status;
+ kcb->kprobe_orig_tnpc = kcb->prev_kprobe.orig_tnpc;
+ kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
{
- current_kprobe_orig_tnpc = regs->tnpc;
- current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
- current_kprobe = p;
+ __get_cpu_var(current_kprobe) = p;
+ kcb->kprobe_orig_tnpc = regs->tnpc;
+ kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
}
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
{
regs->tstate |= TSTATE_PIL;
/*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;
+ regs->tnpc = kcb->kprobe_orig_tnpc;
} else {
regs->tpc = (unsigned long) &p->ainsn.insn[0];
regs->tnpc = (unsigned long) &p->ainsn.insn[1];
@@ -117,19 +113,21 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
struct kprobe *p;
void *addr = (void *) regs->tpc;
int ret = 0;
+ struct kprobe_ctlblk *kcb;
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
preempt_disable();
+ kcb = get_kprobe_ctlblk();
if (kprobe_running()) {
- /* We *are* holding lock here, so this is safe.
- * Disarm the probe we just hit, and ignore it.
- */
p = get_kprobe(addr);
if (p) {
- if (kprobe_status == KPROBE_HIT_SS) {
+ if (kcb->kprobe_status == KPROBE_HIT_SS) {
regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
- current_kprobe_orig_tstate_pil);
- unlock_kprobes();
+ kcb->kprobe_orig_tstate_pil);
goto no_kprobe;
}
/* We have reentered the kprobe_handler(), since
@@ -138,25 +136,22 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
* just single step on the instruction of the new probe
* without calling any user handlers.
*/
- save_previous_kprobe();
- set_current_kprobe(p, regs);
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p, regs, kcb);
p->nmissed++;
- kprobe_status = KPROBE_REENTER;
- prepare_singlestep(p, regs);
+ kcb->kprobe_status = KPROBE_REENTER;
+ prepare_singlestep(p, regs, kcb);
return 1;
} else {
- p = current_kprobe;
+ p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs))
goto ss_probe;
}
- /* If it's not ours, can't be delete race, (we hold lock). */
goto no_kprobe;
}
- lock_kprobes();
p = get_kprobe(addr);
if (!p) {
- unlock_kprobes();
if (*(u32 *)addr != BREAKPOINT_INSTRUCTION) {
/*
* The breakpoint instruction was removed right
@@ -171,14 +166,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
goto no_kprobe;
}
- set_current_kprobe(p, regs);
- kprobe_status = KPROBE_HIT_ACTIVE;
+ set_current_kprobe(p, regs, kcb);
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
if (p->pre_handler && p->pre_handler(p, regs))
return 1;
ss_probe:
- prepare_singlestep(p, regs);
- kprobe_status = KPROBE_HIT_SS;
+ prepare_singlestep(p, regs, kcb);
+ kcb->kprobe_status = KPROBE_HIT_SS;
return 1;
no_kprobe:
@@ -260,11 +255,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
* This function prepares to return from the post-single-step
* breakpoint trap.
*/
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p,
+ struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
u32 insn = p->ainsn.insn[0];
- regs->tpc = current_kprobe_orig_tnpc;
+ regs->tpc = kcb->kprobe_orig_tnpc;
regs->tnpc = relbranch_fixup(insn,
(unsigned long) p->addr,
(unsigned long) &p->ainsn.insn[0],
@@ -272,44 +268,48 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
retpc_fixup(regs, insn, (unsigned long) p->addr);
regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
- current_kprobe_orig_tstate_pil);
+ kcb->kprobe_orig_tstate_pil);
}
static inline int post_kprobe_handler(struct pt_regs *regs)
{
- if (!kprobe_running())
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (!cur)
return 0;
- if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
- kprobe_status = KPROBE_HIT_SSDONE;
- current_kprobe->post_handler(current_kprobe, regs, 0);
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
}
- resume_execution(current_kprobe, regs);
+ resume_execution(cur, regs, kcb);
/*Restore back the original saved kprobes variables and continue. */
- if (kprobe_status == KPROBE_REENTER) {
- restore_previous_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
goto out;
}
- unlock_kprobes();
+ reset_current_kprobe();
out:
preempt_enable_no_resched();
return 1;
}
-/* Interrupts disabled, kprobe_lock held. */
static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
- if (current_kprobe->fault_handler
- && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;
- if (kprobe_status & KPROBE_HIT_SS) {
- resume_execution(current_kprobe, regs);
+ if (kcb->kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs, kcb);
- unlock_kprobes();
+ reset_current_kprobe();
preempt_enable_no_resched();
}
return 0;
@@ -322,29 +322,30 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
switch (val) {
case DIE_DEBUG:
if (kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_DEBUG_2:
if (post_kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_GPF:
- if (kprobe_running() &&
- kprobe_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
- break;
case DIE_PAGE_FAULT:
+ /* kprobe_running() needs smp_processor_id() */
+ preempt_disable();
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
+ preempt_enable();
break;
default:
break;
}
- return NOTIFY_DONE;
+ return ret;
}
asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
@@ -368,24 +369,21 @@ asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
}
/* Jprobes support. */
-static struct pt_regs jprobe_saved_regs;
-static struct pt_regs *jprobe_saved_regs_location;
-static struct sparc_stackf jprobe_saved_stack;
-
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- jprobe_saved_regs_location = regs;
- memcpy(&jprobe_saved_regs, regs, sizeof(*regs));
+ kcb->jprobe_saved_regs_location = regs;
+ memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs));
/* Save a whole stack frame, this gets arguments
* pushed onto the stack after using up all the
* arg registers.
*/
- memcpy(&jprobe_saved_stack,
+ memcpy(&(kcb->jprobe_saved_stack),
(char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
- sizeof(jprobe_saved_stack));
+ sizeof(kcb->jprobe_saved_stack));
regs->tpc = (unsigned long) jp->entry;
regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
@@ -396,7 +394,6 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
void __kprobes jprobe_return(void)
{
- preempt_enable_no_resched();
__asm__ __volatile__(
".globl jprobe_return_trap_instruction\n"
"jprobe_return_trap_instruction:\n\t"
@@ -410,14 +407,15 @@ extern void __show_regs(struct pt_regs * regs);
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
u32 *addr = (u32 *) regs->tpc;
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
if (addr == (u32 *) jprobe_return_trap_instruction) {
- if (jprobe_saved_regs_location != regs) {
+ if (kcb->jprobe_saved_regs_location != regs) {
printk("JPROBE: Current regs (%p) does not match "
"saved regs (%p).\n",
- regs, jprobe_saved_regs_location);
+ regs, kcb->jprobe_saved_regs_location);
printk("JPROBE: Saved registers\n");
- __show_regs(jprobe_saved_regs_location);
+ __show_regs(kcb->jprobe_saved_regs_location);
printk("JPROBE: Current registers\n");
__show_regs(regs);
BUG();
@@ -426,12 +424,13 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
* first so that UREG_FP is the original one for
* the stack frame restore.
*/
- memcpy(regs, &jprobe_saved_regs, sizeof(*regs));
+ memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs));
memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
- &jprobe_saved_stack,
- sizeof(jprobe_saved_stack));
+ &(kcb->jprobe_saved_stack),
+ sizeof(kcb->jprobe_saved_stack));
+ preempt_enable_no_resched();
return 1;
}
return 0;
diff --git a/arch/sparc64/kernel/us2e_cpufreq.c b/arch/sparc64/kernel/us2e_cpufreq.c
index 686e526bec04..b35dc8dc995a 100644
--- a/arch/sparc64/kernel/us2e_cpufreq.c
+++ b/arch/sparc64/kernel/us2e_cpufreq.c
@@ -388,10 +388,8 @@ err_out:
kfree(driver);
cpufreq_us2e_driver = NULL;
}
- if (us2e_freq_table) {
- kfree(us2e_freq_table);
- us2e_freq_table = NULL;
- }
+ kfree(us2e_freq_table);
+ us2e_freq_table = NULL;
return ret;
}
@@ -402,7 +400,6 @@ static void __exit us2e_freq_exit(void)
{
if (cpufreq_us2e_driver) {
cpufreq_unregister_driver(cpufreq_us2e_driver);
-
kfree(cpufreq_us2e_driver);
cpufreq_us2e_driver = NULL;
kfree(us2e_freq_table);
diff --git a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c
index 0340041f6143..6d1f9a3c464f 100644
--- a/arch/sparc64/kernel/us3_cpufreq.c
+++ b/arch/sparc64/kernel/us3_cpufreq.c
@@ -249,10 +249,8 @@ err_out:
kfree(driver);
cpufreq_us3_driver = NULL;
}
- if (us3_freq_table) {
- kfree(us3_freq_table);
- us3_freq_table = NULL;
- }
+ kfree(us3_freq_table);
+ us3_freq_table = NULL;
return ret;
}
@@ -263,7 +261,6 @@ static void __exit us3_freq_exit(void)
{
if (cpufreq_us3_driver) {
cpufreq_unregister_driver(cpufreq_us3_driver);
-
kfree(cpufreq_us3_driver);
cpufreq_us3_driver = NULL;
kfree(us3_freq_table);
diff --git a/arch/sparc64/oprofile/Kconfig b/arch/sparc64/oprofile/Kconfig
index 5ade19801b97..d8a84088471a 100644
--- a/arch/sparc64/oprofile/Kconfig
+++ b/arch/sparc64/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
config PROFILING
bool "Profiling support (EXPERIMENTAL)"
help
@@ -19,5 +15,3 @@ config OPROFILE
If unsure, say N.
-endmenu
-
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index cd06ed7d842d..3b5f47c46907 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -65,6 +65,30 @@ config STATIC_LINK
chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
here.
+config HOST_2G_2G
+ bool "2G/2G host address space split"
+ default n
+ depends on MODE_TT
+ help
+ This is needed when the host on which you run has a 2G/2G memory
+ split, instead of the customary 3G/1G.
+
+ Note that to enable such a host
+ configuration, which makes sense only in some cases, you need special
+ host patches.
+
+ So, if you do not know what to do here, say 'N'.
+
+config KERNEL_HALF_GIGS
+ int "Kernel address space size (in .5G units)"
+ default "1"
+ depends on MODE_TT
+ help
+ This determines the amount of address space that UML will allocate for
+ its own, measured in half Gigabyte units. The default is 1.
+ Change this only if you need to boot UML with an unusually large amount
+ of physical memory.
+
config MODE_SKAS
bool "Separate Kernel Address Space support"
default y
@@ -182,19 +206,6 @@ config MAGIC_SYSRQ
The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
unless you really know what this hack does.
-config HOST_2G_2G
- bool "2G/2G host address space split"
- default n
- help
- This is needed when the host on which you run has a 2G/2G memory
- split, instead of the customary 3G/1G.
-
- Note that to enable such a host
- configuration, which makes sense only in some cases, you need special
- host patches.
-
- So, if you do not know what to do here, say 'N'.
-
config SMP
bool "Symmetric multi-processing support (EXPERIMENTAL)"
default n
@@ -241,15 +252,6 @@ config NEST_LEVEL
set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
Only change this if you are running nested UMLs.
-config KERNEL_HALF_GIGS
- int "Kernel address space size (in .5G units)"
- default "1"
- help
- This determines the amount of address space that UML will allocate for
- its own, measured in half Gigabyte units. The default is 1.
- Change this only if you need to boot UML with an unusually large amount
- of physical memory.
-
config HIGHMEM
bool "Highmem support"
depends on !64BIT
diff --git a/arch/um/Makefile b/arch/um/Makefile
index e1ffad224605..e55d32e903bc 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -60,7 +60,7 @@ AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
- $(MODE_INCLUDE)
+ $(MODE_INCLUDE) -D_FILE_OFFSET_BITS=64
# -Derrno=kernel_errno - This turns all kernel references to errno into
# kernel_errno to separate them from the libc errno. This allows -fno-common
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index aef7c50f8e13..1f7dcb064aee 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -17,8 +17,6 @@ ifeq ("$(origin SUBARCH)", "command line")
ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)")
CFLAGS += $(call cc-option,-m32)
USER_CFLAGS += $(call cc-option,-m32)
-HOSTCFLAGS += $(call cc-option,-m32)
-HOSTLDFLAGS += $(call cc-option,-m32)
AFLAGS += $(call cc-option,-m32)
LINK-y += $(call cc-option,-m32)
UML_OBJCOPYFLAGS += -F $(ELF_FORMAT)
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index de3bce71aeb3..1c55d5802489 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -16,7 +16,6 @@
#include "user_util.h"
#include "chan_user.h"
#include "user.h"
-#include "helper.h"
#include "os.h"
#include "choose-mode.h"
#include "mode.h"
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c
index 147ec19f6bb9..49acb2badf32 100644
--- a/arch/um/drivers/harddog_kern.c
+++ b/arch/um/drivers/harddog_kern.c
@@ -46,7 +46,6 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <asm/uaccess.h>
-#include "helper.h"
#include "mconsole.h"
MODULE_LICENSE("GPL");
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index d934181b8d4c..def013b5a3c7 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -8,7 +8,6 @@
#include <errno.h>
#include "user_util.h"
#include "user.h"
-#include "helper.h"
#include "mconsole.h"
#include "os.h"
#include "choose-mode.h"
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 721e2601a75d..fe865d9a3721 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -96,7 +96,6 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static int uml_net_open(struct net_device *dev)
{
struct uml_net_private *lp = dev->priv;
- char addr[sizeof("255.255.255.255\0")];
int err;
spin_lock(&lp->lock);
@@ -107,7 +106,7 @@ static int uml_net_open(struct net_device *dev)
}
if(!lp->have_mac){
- dev_ip_addr(dev, addr, &lp->mac[2]);
+ dev_ip_addr(dev, &lp->mac[2]);
set_ether_mac(dev, lp->mac);
}
@@ -664,8 +663,6 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
void *ptr)
{
struct in_ifaddr *ifa = ptr;
- u32 addr = ifa->ifa_address;
- u32 netmask = ifa->ifa_mask;
struct net_device *dev = ifa->ifa_dev->dev;
struct uml_net_private *lp;
void (*proc)(unsigned char *, unsigned char *, void *);
@@ -685,14 +682,8 @@ static int uml_inetaddr_event(struct notifier_block *this, unsigned long event,
break;
}
if(proc != NULL){
- addr_buf[0] = addr & 0xff;
- addr_buf[1] = (addr >> 8) & 0xff;
- addr_buf[2] = (addr >> 16) & 0xff;
- addr_buf[3] = addr >> 24;
- netmask_buf[0] = netmask & 0xff;
- netmask_buf[1] = (netmask >> 8) & 0xff;
- netmask_buf[2] = (netmask >> 16) & 0xff;
- netmask_buf[3] = netmask >> 24;
+ memcpy(addr_buf, &ifa->ifa_address, sizeof(addr_buf));
+ memcpy(netmask_buf, &ifa->ifa_mask, sizeof(netmask_buf));
(*proc)(addr_buf, netmask_buf, &lp->user);
}
return(NOTIFY_DONE);
@@ -774,27 +765,18 @@ int setup_etheraddr(char *str, unsigned char *addr)
return(1);
}
-void dev_ip_addr(void *d, char *buf, char *bin_buf)
+void dev_ip_addr(void *d, unsigned char *bin_buf)
{
struct net_device *dev = d;
struct in_device *ip = dev->ip_ptr;
struct in_ifaddr *in;
- u32 addr;
if((ip == NULL) || ((in = ip->ifa_list) == NULL)){
printk(KERN_WARNING "dev_ip_addr - device not assigned an "
"IP address\n");
return;
}
- addr = in->ifa_address;
- sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
- (addr >> 16) & 0xff, addr >> 24);
- if(bin_buf){
- bin_buf[0] = addr & 0xff;
- bin_buf[1] = (addr >> 8) & 0xff;
- bin_buf[2] = (addr >> 16) & 0xff;
- bin_buf[3] = addr >> 24;
- }
+ memcpy(bin_buf, &in->ifa_address, sizeof(in->ifa_address));
}
void set_ether_mac(void *d, unsigned char *addr)
@@ -829,14 +811,8 @@ void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *,
if(ip == NULL) return;
in = ip->ifa_list;
while(in != NULL){
- address[0] = in->ifa_address & 0xff;
- address[1] = (in->ifa_address >> 8) & 0xff;
- address[2] = (in->ifa_address >> 16) & 0xff;
- address[3] = in->ifa_address >> 24;
- netmask[0] = in->ifa_mask & 0xff;
- netmask[1] = (in->ifa_mask >> 8) & 0xff;
- netmask[2] = (in->ifa_mask >> 16) & 0xff;
- netmask[3] = in->ifa_mask >> 24;
+ memcpy(address, &in->ifa_address, sizeof(address));
+ memcpy(netmask, &in->ifa_mask, sizeof(netmask));
(*cb)(address, netmask, arg);
in = in->ifa_next;
}
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 3730d4f12713..098fa65981ab 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -16,7 +16,6 @@
#include "user_util.h"
#include "kern_util.h"
#include "net_user.h"
-#include "helper.h"
#include "os.h"
int tap_open_common(void *dev, char *gate_addr)
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 14dd2002d2da..ed4a1a6c5d83 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -18,7 +18,6 @@
#include "user.h"
#include "chan_user.h"
#include "port.h"
-#include "helper.h"
#include "os.h"
struct port_chan {
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index f9e22198e011..ba471f5864a6 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -58,10 +58,8 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
if (filp->f_flags & O_NONBLOCK)
return ret ? : -EAGAIN;
- if(need_resched()){
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
- }
+ if(need_resched())
+ schedule_timeout_interruptible(1);
}
else return n;
if (signal_pending (current))
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 71af444e591f..89fbec185cc1 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -14,7 +14,6 @@
#include "net_user.h"
#include "slip.h"
#include "slip_common.h"
-#include "helper.h"
#include "os.h"
void slip_user_init(void *data, void *dev)
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 8d91f663d82c..b94c66114bc8 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -13,7 +13,6 @@
#include "net_user.h"
#include "slirp.h"
#include "slip_common.h"
-#include "helper.h"
#include "os.h"
void slirp_user_init(void *data, void *dev)
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 90e0e5ff451e..b530f1a6540d 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -14,7 +14,6 @@
#include <sys/socket.h>
#include "kern_util.h"
#include "chan_user.h"
-#include "helper.h"
#include "user_util.h"
#include "user.h"
#include "os.h"
diff --git a/arch/um/include/helper.h b/arch/um/include/helper.h
deleted file mode 100644
index 162ac31192fd..000000000000
--- a/arch/um/include/helper.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __HELPER_H__
-#define __HELPER_H__
-
-extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
- unsigned long *stack_out);
-extern int run_helper_thread(int (*proc)(void *), void *arg,
- unsigned int flags, unsigned long *stack_out,
- int stack_order);
-extern int helper_wait(int pid);
-
-#endif
-
-/*
- * 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/include/mem_user.h b/arch/um/include/mem_user.h
index 9fef4123a65a..a1064c5823bf 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -57,7 +57,7 @@ extern int init_maps(unsigned long physmem, unsigned long iomem,
unsigned long highmem);
extern unsigned long get_vm(unsigned long len);
extern void setup_physmem(unsigned long start, unsigned long usable,
- unsigned long len, unsigned long highmem);
+ unsigned long len, unsigned long long highmem);
extern void add_iomem(char *name, int fd, unsigned long size);
extern unsigned long phys_offset(unsigned long phys);
extern void unmap_physmem(void);
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 89885a77a771..800c403920bc 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -25,7 +25,7 @@ struct net_user_info {
};
extern void ether_user_init(void *data, void *dev);
-extern void dev_ip_addr(void *d, char *buf, char *bin_buf);
+extern void dev_ip_addr(void *d, unsigned char *bin_buf);
extern void set_ether_mac(void *d, unsigned char *addr);
extern void iter_addresses(void *d, void (*cb)(unsigned char *,
unsigned char *, void *),
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 2e58e304b8be..2cccfa5b8ab5 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -167,7 +167,7 @@ extern int can_do_skas(void);
#endif
/* mem.c */
-extern int create_mem_file(unsigned long len);
+extern int create_mem_file(unsigned long long len);
/* process.c */
extern unsigned long os_process_pc(int pid);
@@ -199,6 +199,20 @@ extern void forward_pending_sigio(int target);
extern int start_fork_tramp(void *arg, unsigned long temp_stack,
int clone_flags, int (*tramp)(void *));
+/* uaccess.c */
+extern unsigned long __do_user_copy(void *to, const void *from, int n,
+ void **fault_addr, void **fault_catcher,
+ void (*op)(void *to, const void *from,
+ int n), int *faulted_out);
+
+/* helper.c */
+extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
+ unsigned long *stack_out);
+extern int run_helper_thread(int (*proc)(void *), void *arg,
+ unsigned int flags, unsigned long *stack_out,
+ int stack_order);
+extern int helper_wait(int pid);
+
#endif
/*
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h
index d3699fe1c613..a49ceb199ee5 100644
--- a/arch/um/include/sysdep-i386/stub.h
+++ b/arch/um/include/sysdep-i386/stub.h
@@ -16,45 +16,69 @@ extern void stub_clone_handler(void);
#define STUB_MMAP_NR __NR_mmap2
#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)
+static inline long stub_syscall1(long syscall, long arg1)
+{
+ long ret;
+
+ __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1));
+
+ return ret;
+}
+
static inline long stub_syscall2(long syscall, long arg1, long arg2)
{
long ret;
- __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
- __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
- __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
- __asm__("int $0x80;" : : : "%eax");
- __asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :);
- return(ret);
+ __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+ "c" (arg2));
+
+ return ret;
}
static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
{
- __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
- return(stub_syscall2(syscall, arg1, arg2));
+ long ret;
+
+ __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+ "c" (arg2), "d" (arg3));
+
+ return ret;
}
static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
long arg4)
{
- __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
- return(stub_syscall3(syscall, arg1, arg2, arg3));
+ long ret;
+
+ __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+ "c" (arg2), "d" (arg3), "S" (arg4));
+
+ return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+ long arg4, long arg5)
+{
+ long ret;
+
+ __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1),
+ "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5));
+
+ return ret;
}
static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6)
{
long ret;
- __asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
- __asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
- __asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
- __asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
- __asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
- __asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi");
- __asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; "
- "int $0x80; popl %%ebp ; "
- "movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax");
- return(ret);
+
+ __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; "
+ "int $0x80 ; pop %%ebp"
+ : "=a" (ret)
+ : "g" (syscall), "b" (arg1), "c" (arg2), "d" (arg3),
+ "S" (arg4), "D" (arg5), "0" (arg6));
+
+ return ret;
}
static inline void trap_myself(void)
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h
index f599058d8263..2bd6e7a97286 100644
--- a/arch/um/include/sysdep-x86_64/stub.h
+++ b/arch/um/include/sysdep-x86_64/stub.h
@@ -17,37 +17,72 @@ extern void stub_clone_handler(void);
#define STUB_MMAP_NR __NR_mmap
#define MMAP_OFFSET(o) (o)
+#define __syscall_clobber "r11","rcx","memory"
+#define __syscall "syscall"
+
static inline long stub_syscall2(long syscall, long arg1, long arg2)
{
long ret;
- __asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi");
- __asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi");
- __asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax");
- __asm__("syscall;" : : : "%rax", "%r11", "%rcx");
- __asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :);
- return(ret);
+ __asm__ volatile (__syscall
+ : "=a" (ret)
+ : "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber );
+
+ return ret;
}
static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
{
- __asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx");
- return(stub_syscall2(syscall, arg1, arg2));
+ long ret;
+
+ __asm__ volatile (__syscall
+ : "=a" (ret)
+ : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3)
+ : __syscall_clobber );
+
+ return ret;
}
static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
long arg4)
{
- __asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10");
- return(stub_syscall3(syscall, arg1, arg2, arg3));
+ long ret;
+
+ __asm__ volatile ("movq %5,%%r10 ; " __syscall
+ : "=a" (ret)
+ : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+ "g" (arg4)
+ : __syscall_clobber, "r10" );
+
+ return ret;
+}
+
+static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3,
+ long arg4, long arg5)
+{
+ long ret;
+
+ __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall
+ : "=a" (ret)
+ : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+ "g" (arg4), "g" (arg5)
+ : __syscall_clobber, "r10", "r8" );
+
+ return ret;
}
static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6)
{
- __asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9");
- __asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8");
- return(stub_syscall4(syscall, arg1, arg2, arg3, arg4));
+ long ret;
+
+ __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; "
+ "movq %7, %%r9; " __syscall : "=a" (ret)
+ : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3),
+ "g" (arg4), "g" (arg5), "g" (arg6)
+ : __syscall_clobber, "r10", "r8", "r9" );
+
+ return ret;
}
static inline void trap_myself(void)
diff --git a/arch/um/include/uml_uaccess.h b/arch/um/include/uml_uaccess.h
index f77eb6428453..c0df11d06f5e 100644
--- a/arch/um/include/uml_uaccess.h
+++ b/arch/um/include/uml_uaccess.h
@@ -8,10 +8,6 @@
extern int __do_copy_to_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher);
-extern unsigned long __do_user_copy(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher,
- void (*op)(void *to, const void *from,
- int n), int *faulted_out);
void __do_copy(void *to, const void *from, int n);
#endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 1a0001b3850c..3de9d21e36bf 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -7,10 +7,10 @@ extra-y := vmlinux.lds
clean-files :=
obj-y = config.o exec_kern.o exitcode.o \
- helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \
+ init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \
process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \
signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \
- time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
+ time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \
umid.o user_util.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
@@ -24,8 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \
- user_util.o
+USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index a97a72e516aa..7713e7a6f476 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -20,7 +20,6 @@
#include "user_util.h"
#include "mem_user.h"
#include "os.h"
-#include "helper.h"
EXPORT_SYMBOL(stop);
EXPORT_SYMBOL(uml_physmem);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 462cc9d65386..fa4f915be5c5 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -234,8 +234,8 @@ void paging_init(void)
empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++)
zones_size[i] = 0;
- zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
- zones_size[2] = highmem >> PAGE_SHIFT;
+ zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
+ zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
free_area_init(zones_size);
/*
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index ea670fcc8af5..f3b583a878a6 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -246,7 +246,7 @@ int is_remapped(void *virt)
/* Changed during early boot */
unsigned long high_physmem;
-extern unsigned long physmem_size;
+extern unsigned long long physmem_size;
int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
{
@@ -321,7 +321,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
extern int __syscall_stub_start, __binary_start;
void setup_physmem(unsigned long start, unsigned long reserve_end,
- unsigned long len, unsigned long highmem)
+ unsigned long len, unsigned long long highmem)
{
unsigned long reserve = reserve_end - start;
int pfn = PFN_UP(__pa(reserve_end));
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 71af4d503899..98e09395c093 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child)
extern int peek_user(struct task_struct * child, long addr, long data);
extern int poke_user(struct task_struct * child, long addr, long data);
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int i, ret;
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
-
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
-
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
-#ifdef SUBACH_PTRACE_SPECIAL
- SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
-#endif
-
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
break;
}
- out_tsk:
- put_task_struct(child);
- out:
- unlock_kernel();
+
return ret;
}
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index a52751108aa1..48b1f644b9a6 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -18,7 +18,6 @@
#include "kern_util.h"
#include "user_util.h"
#include "sigio.h"
-#include "helper.h"
#include "os.h"
/* Changed during early boot */
@@ -225,7 +224,7 @@ static int need_poll(int n)
next_poll.used = n;
return(0);
}
- if(next_poll.poll != NULL) kfree(next_poll.poll);
+ kfree(next_poll.poll);
next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
if(next_poll.poll == NULL){
printk("need_poll : failed to allocate new pollfds\n");
diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h
index 09536f81ee42..44110c521e49 100644
--- a/arch/um/kernel/skas/include/mmu-skas.h
+++ b/arch/um/kernel/skas/include/mmu-skas.h
@@ -8,6 +8,7 @@
#include "linux/config.h"
#include "mm_id.h"
+#include "asm/ldt.h"
struct mmu_context_skas {
struct mm_id id;
@@ -15,6 +16,7 @@ struct mmu_context_skas {
#ifdef CONFIG_3_LEVEL_PGTABLES
unsigned long last_pmd;
#endif
+ uml_ldt_t ldt;
};
extern void switch_mm_skas(struct mm_id * mm_idp);
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 060934740f9f..daa2f85b684c 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -10,7 +10,8 @@
#include "sysdep/ptrace.h"
extern int userspace_pid[];
-extern int proc_mm, ptrace_faultinfo;
+extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
+extern int skas_needs_stub;
extern void switch_threads(void *me, void *next);
extern void thread_wait(void *sw, void *fb);
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
index 147466d7ff4f..88ab96c609ce 100644
--- a/arch/um/kernel/skas/mem.c
+++ b/arch/um/kernel/skas/mem.c
@@ -20,7 +20,7 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
*task_size_out = CONFIG_HOST_TASK_SIZE;
#else
*host_size_out = top;
- if (proc_mm && ptrace_faultinfo)
+ if (!skas_needs_stub)
*task_size_out = top;
else *task_size_out = CONFIG_STUB_START & PGDIR_MASK;
#endif
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 9e5e39cea821..677871f1b37c 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -15,6 +15,7 @@
#include "asm/mmu.h"
#include "asm/pgalloc.h"
#include "asm/pgtable.h"
+#include "asm/ldt.h"
#include "os.h"
#include "skas.h"
@@ -74,13 +75,12 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
{
- struct mm_struct *cur_mm = current->mm;
- struct mm_id *cur_mm_id = &cur_mm->context.skas.id;
- struct mm_id *mm_id = &mm->context.skas.id;
+ struct mmu_context_skas *from_mm = NULL;
+ struct mmu_context_skas *to_mm = &mm->context.skas;
unsigned long stack = 0;
- int from, ret = -ENOMEM;
+ int from_fd, ret = -ENOMEM;
- if(!proc_mm || !ptrace_faultinfo){
+ if(skas_needs_stub){
stack = get_zeroed_page(GFP_KERNEL);
if(stack == 0)
goto out;
@@ -102,33 +102,43 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
mm->nr_ptes--;
}
- mm_id->stack = stack;
+
+ to_mm->id.stack = stack;
+ if(current->mm != NULL && current->mm != &init_mm)
+ from_mm = &current->mm->context.skas;
if(proc_mm){
- if((cur_mm != NULL) && (cur_mm != &init_mm))
- from = cur_mm_id->u.mm_fd;
- else from = -1;
+ if(from_mm)
+ from_fd = from_mm->id.u.mm_fd;
+ else from_fd = -1;
- ret = new_mm(from, stack);
+ ret = new_mm(from_fd, stack);
if(ret < 0){
printk("init_new_context_skas - new_mm failed, "
"errno = %d\n", ret);
goto out_free;
}
- mm_id->u.mm_fd = ret;
+ to_mm->id.u.mm_fd = ret;
}
else {
- if((cur_mm != NULL) && (cur_mm != &init_mm))
- mm_id->u.pid = copy_context_skas0(stack,
- cur_mm_id->u.pid);
- else mm_id->u.pid = start_userspace(stack);
+ if(from_mm)
+ to_mm->id.u.pid = copy_context_skas0(stack,
+ from_mm->id.u.pid);
+ else to_mm->id.u.pid = start_userspace(stack);
+ }
+
+ ret = init_new_ldt(to_mm, from_mm);
+ if(ret < 0){
+ printk("init_new_context_skas - init_ldt"
+ " failed, errno = %d\n", ret);
+ goto out_free;
}
return 0;
out_free:
- if(mm_id->stack != 0)
- free_page(mm_id->stack);
+ if(to_mm->id.stack != 0)
+ free_page(to_mm->id.stack);
out:
return ret;
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 5cd0e9929789..599d679bd4fc 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -69,6 +69,17 @@ void wait_stub_done(int pid, int sig, char * fname)
if((n < 0) || !WIFSTOPPED(status) ||
(WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
+ unsigned long regs[FRAME_SIZE];
+ if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+ printk("Failed to get registers from stub, "
+ "errno = %d\n", errno);
+ else {
+ int i;
+
+ printk("Stub registers -\n");
+ for(i = 0; i < FRAME_SIZE; i++)
+ printk("\t%d - %lx\n", i, regs[i]);
+ }
panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
"pid = %d, n = %d, errno = %d, status = 0x%x\n",
fname, pid, n, errno, status);
@@ -370,9 +381,9 @@ int copy_context_skas0(unsigned long new_stack, int pid)
}
/*
- * This is used only, if proc_mm is available, while PTRACE_FAULTINFO
- * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages
- * Thus, we map them using /proc/mm-fd
+ * This is used only, if stub pages are needed, while proc_mm is
+ * availabl. Opening /proc/mm creates a new mm_context, which lacks
+ * the stub-pages. Thus, we map them using /proc/mm-fd
*/
void map_stub_pages(int fd, unsigned long code,
unsigned long data, unsigned long stack)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index efe92e8aa2a9..9c990253966c 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -145,7 +145,7 @@ int new_mm(int from, unsigned long stack)
"err = %d\n", -n);
}
- if(!ptrace_faultinfo)
+ if(skas_needs_stub)
map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
return(fd);
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index 8c220f054b61..6c92bbccb49c 100644
--- a/arch/um/kernel/tt/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
@@ -10,6 +10,7 @@
#include "uml_uaccess.h"
#include "task.h"
#include "kern_util.h"
+#include "os.h"
int __do_copy_from_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher)
diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
new file mode 100644
index 000000000000..054e3de0784e
--- /dev/null
+++ b/arch/um/kernel/uaccess.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+/* These are here rather than tt/uaccess.c because skas mode needs them in
+ * order to do SIGBUS recovery when a tmpfs mount runs out of room.
+ */
+
+#include <linux/string.h>
+#include "os.h"
+
+void __do_copy(void *to, const void *from, int n)
+{
+ memcpy(to, from, n);
+}
+
+
+int __do_copy_to_user(void *to, const void *from, int n,
+ void **fault_addr, void **fault_catcher)
+{
+ unsigned long fault;
+ int faulted;
+
+ fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
+ __do_copy, &faulted);
+ if(!faulted) return(0);
+ else return(n - (fault - (unsigned long) to));
+}
diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c
deleted file mode 100644
index d035257ed0af..000000000000
--- a/arch/um/kernel/uaccess_user.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <setjmp.h>
-#include <string.h>
-
-/* These are here rather than tt/uaccess.c because skas mode needs them in
- * order to do SIGBUS recovery when a tmpfs mount runs out of room.
- */
-
-unsigned long __do_user_copy(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher,
- void (*op)(void *to, const void *from,
- int n), int *faulted_out)
-{
- unsigned long *faddrp = (unsigned long *) fault_addr, ret;
-
- sigjmp_buf jbuf;
- *fault_catcher = &jbuf;
- if(sigsetjmp(jbuf, 1) == 0){
- (*op)(to, from, n);
- ret = 0;
- *faulted_out = 0;
- }
- else {
- ret = *faddrp;
- *faulted_out = 1;
- }
- *fault_addr = NULL;
- *fault_catcher = NULL;
- return ret;
-}
-
-void __do_copy(void *to, const void *from, int n)
-{
- memcpy(to, from, n);
-}
-
-
-int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher)
-{
- unsigned long fault;
- int faulted;
-
- fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
- __do_copy, &faulted);
- if(!faulted) return(0);
- else return(n - (fault - (unsigned long) to));
-}
-
-/*
- * 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/um_arch.c b/arch/um/kernel/um_arch.c
index 93dc782dc1cc..142a9493912b 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -137,7 +137,7 @@ static char *argv1_end = NULL;
/* Set in early boot */
static int have_root __initdata = 0;
-long physmem_size = 32 * 1024 * 1024;
+long long physmem_size = 32 * 1024 * 1024;
void set_cmdline(char *cmd)
{
@@ -402,7 +402,7 @@ int linux_main(int argc, char **argv)
#ifndef CONFIG_HIGHMEM
highmem = 0;
printf("CONFIG_HIGHMEM not enabled - physical memory shrunk "
- "to %ld bytes\n", physmem_size);
+ "to %lu bytes\n", physmem_size);
#endif
}
@@ -414,8 +414,8 @@ int linux_main(int argc, char **argv)
setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
if(init_maps(physmem_size, iomem_size, highmem)){
- printf("Failed to allocate mem_map for %ld bytes of physical "
- "memory and %ld bytes of highmem\n", physmem_size,
+ printf("Failed to allocate mem_map for %lu bytes of physical "
+ "memory and %lu bytes of highmem\n", physmem_size,
highmem);
exit(1);
}
@@ -426,7 +426,7 @@ int linux_main(int argc, char **argv)
end_vm = start_vm + virtmem_size;
if(virtmem_size < physmem_size)
- printf("Kernel virtual memory size shrunk to %ld bytes\n",
+ printf("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
uml_postsetup();
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
index 41d17c71511c..4c231161f257 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/kernel/user_util.c
@@ -27,7 +27,6 @@
#include "user.h"
#include "mem_user.h"
#include "init.h"
-#include "helper.h"
#include "ptrace_user.h"
#include "uml-config.h"
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index d15ec2af6a22..b83ac8e21c35 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,11 +3,12 @@
# Licensed under the GPL
#
-obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \
- tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/
+obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
+ start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \
+ sys-$(SUBARCH)/
-USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \
- time.o tt.o tty.o
+USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \
+ start_up.o time.o tt.o tty.o uaccess.o
elf_aux.o: $(ARCH_DIR)/kernel-offsets.h
CFLAGS_elf_aux.o += -I$(objtree)/arch/um
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 41cfb0944201..ffa759addd3c 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -10,7 +10,6 @@
#include <sched.h>
#include <sys/syscall.h>
#include "os.h"
-#include "helper.h"
#include "aio.h"
#include "init.h"
#include "user.h"
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index cd4d6544da71..901b85e8a1c6 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -19,7 +19,6 @@
#include "user_util.h"
#include "net_user.h"
#include "etap.h"
-#include "helper.h"
#include "os.h"
#define MAX_PACKET ETH_MAX_PACKET
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 4ba9b17adf13..52945338b64d 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -20,7 +20,6 @@
#include "kern_util.h"
#include "user_util.h"
#include "user.h"
-#include "helper.h"
#include "os.h"
#define MAX_PACKET ETH_MAX_PACKET
diff --git a/arch/um/kernel/helper.c b/arch/um/os-Linux/helper.c
index 33fb0bd3b11a..36cc8475bcda 100644
--- a/arch/um/kernel/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -13,7 +13,6 @@
#include "user.h"
#include "kern_util.h"
#include "user_util.h"
-#include "helper.h"
#include "os.h"
struct helper_data {
@@ -46,7 +45,7 @@ static int helper_child(void *arg)
errval = errno;
printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
- os_kill_process(os_getpid(), 0);
+ kill(os_getpid(), SIGKILL);
return(0);
}
@@ -90,7 +89,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
goto out_close;
}
- os_close_file(fds[1]);
+ close(fds[1]);
fds[1] = -1;
/*Read the errno value from the child.*/
@@ -98,7 +97,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
if(n < 0){
printk("run_helper : read on pipe failed, ret = %d\n", -n);
ret = n;
- os_kill_process(pid, 1);
+ kill(pid, SIGKILL);
+ CATCH_EINTR(waitpid(pid, NULL, 0));
}
else if(n != 0){
CATCH_EINTR(n = waitpid(pid, NULL, 0));
@@ -109,8 +109,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
out_close:
if (fds[1] != -1)
- os_close_file(fds[1]);
- os_close_file(fds[0]);
+ close(fds[1]);
+ close(fds[0]);
out_free:
if(stack_out == NULL)
free_stack(stack, 0);
@@ -118,7 +118,7 @@ out_free:
return(ret);
}
-int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
+int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
unsigned long *stack_out, int stack_order)
{
unsigned long stack, sp;
@@ -131,7 +131,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
if(pid < 0){
err = -errno;
- printk("run_helper_thread : clone failed, errno = %d\n",
+ printk("run_helper_thread : clone failed, errno = %d\n",
errno);
return err;
}
diff --git a/arch/um/kernel/main.c b/arch/um/os-Linux/main.c
index d31027f0fe39..23da27d22569 100644
--- a/arch/um/kernel/main.c
+++ b/arch/um/os-Linux/main.c
@@ -157,25 +157,25 @@ int main(int argc, char **argv, char **envp)
*/
change_sig(SIGPROF, 0);
- /* This signal stuff used to be in the reboot case. However,
- * sometimes a SIGVTALRM can come in when we're halting (reproducably
- * when writing out gcov information, presumably because that takes
- * some time) and cause a segfault.
- */
-
- /* stop timers and set SIG*ALRM to be ignored */
- disable_timer();
-
- /* disable SIGIO for the fds and set SIGIO to be ignored */
- err = deactivate_all_fds();
- if(err)
- printf("deactivate_all_fds failed, errno = %d\n", -err);
-
- /* Let any pending signals fire now. This ensures
- * that they won't be delivered after the exec, when
- * they are definitely not expected.
- */
- unblock_signals();
+ /* This signal stuff used to be in the reboot case. However,
+ * sometimes a SIGVTALRM can come in when we're halting (reproducably
+ * when writing out gcov information, presumably because that takes
+ * some time) and cause a segfault.
+ */
+
+ /* stop timers and set SIG*ALRM to be ignored */
+ disable_timer();
+
+ /* disable SIGIO for the fds and set SIGIO to be ignored */
+ err = deactivate_all_fds();
+ if(err)
+ printf("deactivate_all_fds failed, errno = %d\n", -err);
+
+ /* Let any pending signals fire now. This ensures
+ * that they won't be delivered after the exec, when
+ * they are definitely not expected.
+ */
+ unblock_signals();
/* Reboot */
if(ret){
@@ -257,14 +257,3 @@ void __wrap_free(void *ptr)
}
else __real_free(ptr);
}
-
-/*
- * 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/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 8e71edaaf80b..9d7d69a523bb 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -88,7 +88,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
* This proc is used in start_up.c
* So it isn't 'static'.
*/
-int create_tmp_file(unsigned long len)
+int create_tmp_file(unsigned long long len)
{
int fd, err;
char zero;
@@ -121,7 +121,7 @@ int create_tmp_file(unsigned long len)
return(fd);
}
-static int create_anon_file(unsigned long len)
+static int create_anon_file(unsigned long long len)
{
void *addr;
int fd;
@@ -144,7 +144,7 @@ static int create_anon_file(unsigned long len)
extern int have_devanon;
-int create_mem_file(unsigned long len)
+int create_mem_file(unsigned long long len)
{
int err, fd;
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index b99ab414542f..37517d49c4ae 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -135,7 +135,9 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
}
int ptrace_faultinfo = 1;
+int ptrace_ldt = 1;
int proc_mm = 1;
+int skas_needs_stub = 0;
static int __init skas0_cmd_param(char *str, int* add)
{
@@ -294,7 +296,7 @@ static void __init check_ptrace(void)
check_sysemu();
}
-extern int create_tmp_file(unsigned long len);
+extern int create_tmp_file(unsigned long long len);
static void check_tmpexec(void)
{
@@ -352,14 +354,26 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param,
" it. To support PTRACE_FAULTINFO, the host needs to be patched\n"
" using the current skas3 patch.\n\n");
+static int __init noptraceldt_cmd_param(char *str, int* add)
+{
+ ptrace_ldt = 0;
+ return 0;
+}
+
+__uml_setup("noptraceldt", noptraceldt_cmd_param,
+"noptraceldt\n"
+" Turns off usage of PTRACE_LDT, even if host supports it.\n"
+" To support PTRACE_LDT, the host needs to be patched using\n"
+" the current skas3 patch.\n\n");
+
#ifdef UML_CONFIG_MODE_SKAS
-static inline void check_skas3_ptrace_support(void)
+static inline void check_skas3_ptrace_faultinfo(void)
{
struct ptrace_faultinfo fi;
void *stack;
int pid, n;
- printf("Checking for the skas3 patch in the host...");
+ printf(" - PTRACE_FAULTINFO...");
pid = start_ptraced_child(&stack);
n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
@@ -381,9 +395,49 @@ static inline void check_skas3_ptrace_support(void)
stop_ptraced_child(pid, stack, 1, 1);
}
-int can_do_skas(void)
+static inline void check_skas3_ptrace_ldt(void)
+{
+#ifdef PTRACE_LDT
+ void *stack;
+ int pid, n;
+ unsigned char ldtbuf[40];
+ struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
+ .func = 2, /* read default ldt */
+ .ptr = ldtbuf,
+ .bytecount = sizeof(ldtbuf)};
+
+ printf(" - PTRACE_LDT...");
+ pid = start_ptraced_child(&stack);
+
+ n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
+ if (n < 0) {
+ if(errno == EIO)
+ printf("not found\n");
+ else {
+ perror("not found");
+ }
+ ptrace_ldt = 0;
+ }
+ else {
+ if(ptrace_ldt)
+ printf("found\n");
+ else
+ printf("found, but use is disabled\n");
+ }
+
+ stop_ptraced_child(pid, stack, 1, 1);
+#else
+ /* PTRACE_LDT might be disabled via cmdline option.
+ * We want to override this, else we might use the stub
+ * without real need
+ */
+ ptrace_ldt = 1;
+#endif
+}
+
+static inline void check_skas3_proc_mm(void)
{
- printf("Checking for /proc/mm...");
+ printf(" - /proc/mm...");
if (os_access("/proc/mm", OS_ACC_W_OK) < 0) {
proc_mm = 0;
printf("not found\n");
@@ -394,8 +448,19 @@ int can_do_skas(void)
else
printf("found\n");
}
+}
+
+int can_do_skas(void)
+{
+ printf("Checking for the skas3 patch in the host:\n");
+
+ check_skas3_proc_mm();
+ check_skas3_ptrace_faultinfo();
+ check_skas3_ptrace_ldt();
+
+ if(!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
+ skas_needs_stub = 1;
- check_skas3_ptrace_support();
return 1;
}
#else
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
new file mode 100644
index 000000000000..38d710158c3d
--- /dev/null
+++ b/arch/um/os-Linux/uaccess.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <setjmp.h>
+#include <string.h>
+
+unsigned long __do_user_copy(void *to, const void *from, int n,
+ void **fault_addr, void **fault_catcher,
+ void (*op)(void *to, const void *from,
+ int n), int *faulted_out)
+{
+ unsigned long *faddrp = (unsigned long *) fault_addr, ret;
+
+ sigjmp_buf jbuf;
+ *fault_catcher = &jbuf;
+ if(sigsetjmp(jbuf, 1) == 0){
+ (*op)(to, from, n);
+ ret = 0;
+ *faulted_out = 0;
+ }
+ else {
+ ret = *faddrp;
+ *faulted_out = 1;
+ }
+ *fault_addr = NULL;
+ *fault_catcher = NULL;
+ return ret;
+}
+
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 651d9d88b656..b3fbf125709b 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -26,8 +26,13 @@ define unprofile
$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
endef
+# cmd_make_link checks to see if the $(foo-dir) variable starts with a /. If
+# so, it's considered to be a path relative to $(srcdir) rather than
+# $(srcdir)/arch/$(SUBARCH). This is because x86_64 wants to get ldt.c from
+# arch/um/sys-i386 rather than arch/i386 like the other borrowed files. So,
+# it sets $(ldt.c-dir) to /arch/um/sys-i386.
quiet_cmd_make_link = SYMLINK $@
-cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
+cmd_make_link = rm -f $@; ln -sf $(srctree)$(if $(filter-out /%,$($(notdir $@)-dir)),/arch/$(SUBARCH))/$($(notdir $@)-dir)/$(notdir $@) $@
# this needs to be before the foreach, because targets does not accept
# complete paths like $(obj)/$(f). To make sure this works, use a := assignment
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 36b5c2c13289..6360f1c958d0 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -3,53 +3,26 @@
* Licensed under the GPL
*/
+#include "linux/stddef.h"
#include "linux/config.h"
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/types.h"
+#include "linux/errno.h"
#include "asm/uaccess.h"
-#include "asm/ptrace.h"
#include "asm/smp.h"
#include "asm/ldt.h"
+#include "asm/unistd.h"
#include "choose-mode.h"
#include "kern.h"
#include "mode_kern.h"
-#ifdef CONFIG_MODE_TT
-
extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-static int do_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
-{
- return modify_ldt(func, ptr, bytecount);
-}
-
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-
-#include "skas.h"
-#include "skas_ptrace.h"
-
-static int do_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
-{
- struct ptrace_ldt ldt;
- u32 cpu;
- int res;
-
- ldt = ((struct ptrace_ldt) { .func = func,
- .ptr = ptr,
- .bytecount = bytecount });
-
- cpu = get_cpu();
- res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0, (unsigned long) &ldt);
- put_cpu();
-
- return res;
-}
-#endif
+#ifdef CONFIG_MODE_TT
-int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+static long do_modify_ldt_tt(int func, void __user *ptr,
+ unsigned long bytecount)
{
struct user_desc info;
int res = 0;
@@ -89,8 +62,7 @@ int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
goto out;
}
- res = CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
- p, bytecount);
+ res = modify_ldt(func, p, bytecount);
if(res < 0)
goto out;
@@ -108,3 +80,467 @@ out:
kfree(buf);
return res;
}
+
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+
+#include "skas.h"
+#include "skas_ptrace.h"
+#include "asm/mmu_context.h"
+
+long write_ldt_entry(struct mm_id * mm_idp, int func, struct user_desc * desc,
+ void **addr, int done)
+{
+ long res;
+
+ if(proc_mm){
+ /* This is a special handling for the case, that the mm to
+ * modify isn't current->active_mm.
+ * If this is called directly by modify_ldt,
+ * (current->active_mm->context.skas.u == mm_idp)
+ * will be true. So no call to switch_mm_skas(mm_idp) is done.
+ * If this is called in case of init_new_ldt or PTRACE_LDT,
+ * mm_idp won't belong to current->active_mm, but child->mm.
+ * So we need to switch child's mm into our userspace, then
+ * later switch back.
+ *
+ * Note: I'm unshure: should interrupts be disabled here?
+ */
+ if(!current->active_mm || current->active_mm == &init_mm ||
+ mm_idp != &current->active_mm->context.skas.id)
+ switch_mm_skas(mm_idp);
+ }
+
+ if(ptrace_ldt) {
+ struct ptrace_ldt ldt_op = (struct ptrace_ldt) {
+ .func = func,
+ .ptr = desc,
+ .bytecount = sizeof(*desc)};
+ u32 cpu;
+ int pid;
+
+ if(!proc_mm)
+ pid = mm_idp->u.pid;
+ else {
+ cpu = get_cpu();
+ pid = userspace_pid[cpu];
+ }
+
+ res = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
+ if(res)
+ res = errno;
+
+ if(proc_mm)
+ put_cpu();
+ }
+ else {
+ void *stub_addr;
+ res = syscall_stub_data(mm_idp, (unsigned long *)desc,
+ (sizeof(*desc) + sizeof(long) - 1) &
+ ~(sizeof(long) - 1),
+ addr, &stub_addr);
+ if(!res){
+ unsigned long args[] = { func,
+ (unsigned long)stub_addr,
+ sizeof(*desc),
+ 0, 0, 0 };
+ res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
+ 0, addr, done);
+ }
+ }
+
+ if(proc_mm){
+ /* This is the second part of special handling, that makes
+ * PTRACE_LDT possible to implement.
+ */
+ if(current->active_mm && current->active_mm != &init_mm &&
+ mm_idp != &current->active_mm->context.skas.id)
+ switch_mm_skas(&current->active_mm->context.skas.id);
+ }
+
+ return res;
+}
+
+static long read_ldt_from_host(void __user * ptr, unsigned long bytecount)
+{
+ int res, n;
+ struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) {
+ .func = 0,
+ .bytecount = bytecount,
+ .ptr = (void *)kmalloc(bytecount, GFP_KERNEL)};
+ u32 cpu;
+
+ if(ptrace_ldt.ptr == NULL)
+ return -ENOMEM;
+
+ /* This is called from sys_modify_ldt only, so userspace_pid gives
+ * us the right number
+ */
+
+ cpu = get_cpu();
+ res = ptrace(PTRACE_LDT, userspace_pid[cpu], 0,
+ (unsigned long) &ptrace_ldt);
+ put_cpu();
+ if(res < 0)
+ goto out;
+
+ n = copy_to_user(ptr, ptrace_ldt.ptr, res);
+ if(n != 0)
+ res = -EFAULT;
+
+ out:
+ kfree(ptrace_ldt.ptr);
+
+ return res;
+}
+
+/*
+ * In skas mode, we hold our own ldt data in UML.
+ * Thus, the code implementing sys_modify_ldt_skas
+ * is very similar to (and mostly stolen from) sys_modify_ldt
+ * for arch/i386/kernel/ldt.c
+ * The routines copied and modified in part are:
+ * - read_ldt
+ * - read_default_ldt
+ * - write_ldt
+ * - sys_modify_ldt_skas
+ */
+
+static int read_ldt(void __user * ptr, unsigned long bytecount)
+{
+ int i, err = 0;
+ unsigned long size;
+ uml_ldt_t * ldt = &current->mm->context.skas.ldt;
+
+ if(!ldt->entry_count)
+ goto out;
+ if(bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+ bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+ err = bytecount;
+
+ if(ptrace_ldt){
+ return read_ldt_from_host(ptr, bytecount);
+ }
+
+ down(&ldt->semaphore);
+ if(ldt->entry_count <= LDT_DIRECT_ENTRIES){
+ size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
+ if(size > bytecount)
+ size = bytecount;
+ if(copy_to_user(ptr, ldt->entries, size))
+ err = -EFAULT;
+ bytecount -= size;
+ ptr += size;
+ }
+ else {
+ for(i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
+ i++){
+ size = PAGE_SIZE;
+ if(size > bytecount)
+ size = bytecount;
+ if(copy_to_user(ptr, ldt->pages[i], size)){
+ err = -EFAULT;
+ break;
+ }
+ bytecount -= size;
+ ptr += size;
+ }
+ }
+ up(&ldt->semaphore);
+
+ if(bytecount == 0 || err == -EFAULT)
+ goto out;
+
+ if(clear_user(ptr, bytecount))
+ err = -EFAULT;
+
+out:
+ return err;
+}
+
+static int read_default_ldt(void __user * ptr, unsigned long bytecount)
+{
+ int err;
+
+ if(bytecount > 5*LDT_ENTRY_SIZE)
+ bytecount = 5*LDT_ENTRY_SIZE;
+
+ err = bytecount;
+ /* UML doesn't support lcall7 and lcall27.
+ * So, we don't really have a default ldt, but emulate
+ * an empty ldt of common host default ldt size.
+ */
+ if(clear_user(ptr, bytecount))
+ err = -EFAULT;
+
+ return err;
+}
+
+static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
+{
+ uml_ldt_t * ldt = &current->mm->context.skas.ldt;
+ struct mm_id * mm_idp = &current->mm->context.skas.id;
+ int i, err;
+ struct user_desc ldt_info;
+ struct ldt_entry entry0, *ldt_p;
+ void *addr = NULL;
+
+ err = -EINVAL;
+ if(bytecount != sizeof(ldt_info))
+ goto out;
+ err = -EFAULT;
+ if(copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+ goto out;
+
+ err = -EINVAL;
+ if(ldt_info.entry_number >= LDT_ENTRIES)
+ goto out;
+ if(ldt_info.contents == 3){
+ if (func == 1)
+ goto out;
+ if (ldt_info.seg_not_present == 0)
+ goto out;
+ }
+
+ if(!ptrace_ldt)
+ down(&ldt->semaphore);
+
+ err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
+ if(err)
+ goto out_unlock;
+ else if(ptrace_ldt) {
+ /* With PTRACE_LDT available, this is used as a flag only */
+ ldt->entry_count = 1;
+ goto out;
+ }
+
+ if(ldt_info.entry_number >= ldt->entry_count &&
+ ldt_info.entry_number >= LDT_DIRECT_ENTRIES){
+ for(i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
+ i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
+ i++){
+ if(i == 0)
+ memcpy(&entry0, ldt->entries, sizeof(entry0));
+ ldt->pages[i] = (struct ldt_entry *)
+ __get_free_page(GFP_KERNEL|__GFP_ZERO);
+ if(!ldt->pages[i]){
+ err = -ENOMEM;
+ /* Undo the change in host */
+ memset(&ldt_info, 0, sizeof(ldt_info));
+ write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
+ goto out_unlock;
+ }
+ if(i == 0) {
+ memcpy(ldt->pages[0], &entry0, sizeof(entry0));
+ memcpy(ldt->pages[0]+1, ldt->entries+1,
+ sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
+ }
+ ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
+ }
+ }
+ if(ldt->entry_count <= ldt_info.entry_number)
+ ldt->entry_count = ldt_info.entry_number + 1;
+
+ if(ldt->entry_count <= LDT_DIRECT_ENTRIES)
+ ldt_p = ldt->entries + ldt_info.entry_number;
+ else
+ ldt_p = ldt->pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
+ ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
+
+ if(ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
+ (func == 1 || LDT_empty(&ldt_info))){
+ ldt_p->a = 0;
+ ldt_p->b = 0;
+ }
+ else{
+ if (func == 1)
+ ldt_info.useable = 0;
+ ldt_p->a = LDT_entry_a(&ldt_info);
+ ldt_p->b = LDT_entry_b(&ldt_info);
+ }
+ err = 0;
+
+out_unlock:
+ up(&ldt->semaphore);
+out:
+ return err;
+}
+
+static long do_modify_ldt_skas(int func, void __user *ptr,
+ unsigned long bytecount)
+{
+ int ret = -ENOSYS;
+
+ switch (func) {
+ case 0:
+ ret = read_ldt(ptr, bytecount);
+ break;
+ case 1:
+ case 0x11:
+ ret = write_ldt(ptr, bytecount, func);
+ break;
+ case 2:
+ ret = read_default_ldt(ptr, bytecount);
+ break;
+ }
+ return ret;
+}
+
+short dummy_list[9] = {0, -1};
+short * host_ldt_entries = NULL;
+
+void ldt_get_host_info(void)
+{
+ long ret;
+ struct ldt_entry * ldt;
+ int i, size, k, order;
+
+ host_ldt_entries = dummy_list+1;
+
+ for(i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++);
+
+ ldt = (struct ldt_entry *)
+ __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
+ if(ldt == NULL) {
+ printk("ldt_get_host_info: couldn't allocate buffer for host ldt\n");
+ return;
+ }
+
+ ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
+ if(ret < 0) {
+ printk("ldt_get_host_info: couldn't read host ldt\n");
+ goto out_free;
+ }
+ if(ret == 0) {
+ /* default_ldt is active, simply write an empty entry 0 */
+ host_ldt_entries = dummy_list;
+ goto out_free;
+ }
+
+ for(i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++){
+ if(ldt[i].a != 0 || ldt[i].b != 0)
+ size++;
+ }
+
+ if(size < sizeof(dummy_list)/sizeof(dummy_list[0])) {
+ host_ldt_entries = dummy_list;
+ }
+ else {
+ size = (size + 1) * sizeof(dummy_list[0]);
+ host_ldt_entries = (short *)kmalloc(size, GFP_KERNEL);
+ if(host_ldt_entries == NULL) {
+ printk("ldt_get_host_info: couldn't allocate host ldt list\n");
+ goto out_free;
+ }
+ }
+
+ for(i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++){
+ if(ldt[i].a != 0 || ldt[i].b != 0) {
+ host_ldt_entries[k++] = i;
+ }
+ }
+ host_ldt_entries[k] = -1;
+
+out_free:
+ free_pages((unsigned long)ldt, order);
+}
+
+long init_new_ldt(struct mmu_context_skas * new_mm,
+ struct mmu_context_skas * from_mm)
+{
+ struct user_desc desc;
+ short * num_p;
+ int i;
+ long page, err=0;
+ void *addr = NULL;
+
+ memset(&desc, 0, sizeof(desc));
+
+ if(!ptrace_ldt)
+ init_MUTEX(&new_mm->ldt.semaphore);
+
+ if(!from_mm){
+ /*
+ * We have to initialize a clean ldt.
+ */
+ if(proc_mm) {
+ /*
+ * If the new mm was created using proc_mm, host's
+ * default-ldt currently is assigned, which normally
+ * contains the call-gates for lcall7 and lcall27.
+ * To remove these gates, we simply write an empty
+ * entry as number 0 to the host.
+ */
+ err = write_ldt_entry(&new_mm->id, 1, &desc,
+ &addr, 1);
+ }
+ else{
+ /*
+ * Now we try to retrieve info about the ldt, we
+ * inherited from the host. All ldt-entries found
+ * will be reset in the following loop
+ */
+ if(host_ldt_entries == NULL)
+ ldt_get_host_info();
+ for(num_p=host_ldt_entries; *num_p != -1; num_p++){
+ desc.entry_number = *num_p;
+ err = write_ldt_entry(&new_mm->id, 1, &desc,
+ &addr, *(num_p + 1) == -1);
+ if(err)
+ break;
+ }
+ }
+ new_mm->ldt.entry_count = 0;
+ }
+ else if (!ptrace_ldt) {
+ /* Our local LDT is used to supply the data for
+ * modify_ldt(READLDT), if PTRACE_LDT isn't available,
+ * i.e., we have to use the stub for modify_ldt, which
+ * can't handle the big read buffer of up to 64kB.
+ */
+ down(&from_mm->ldt.semaphore);
+ if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){
+ memcpy(new_mm->ldt.entries, from_mm->ldt.entries,
+ sizeof(new_mm->ldt.entries));
+ }
+ else{
+ i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+ while(i-->0){
+ page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
+ if (!page){
+ err = -ENOMEM;
+ break;
+ }
+ new_mm->ldt.pages[i] = (struct ldt_entry*)page;
+ memcpy(new_mm->ldt.pages[i],
+ from_mm->ldt.pages[i], PAGE_SIZE);
+ }
+ }
+ new_mm->ldt.entry_count = from_mm->ldt.entry_count;
+ up(&from_mm->ldt.semaphore);
+ }
+
+ return err;
+}
+
+
+void free_ldt(struct mmu_context_skas * mm)
+{
+ int i;
+
+ if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){
+ i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE;
+ while(i-- > 0){
+ free_page((long )mm->ldt.pages[i]);
+ }
+ }
+ mm->ldt.entry_count = 0;
+}
+#endif
+
+int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
+{
+ return(CHOOSE_MODE_PROC(do_modify_ldt_tt, do_modify_ldt_skas, func,
+ ptr, bytecount));
+}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 06c3633457a2..ea977df395a1 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -5,7 +5,7 @@
#
#XXX: why into lib-y?
-lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o mem.o memcpy.o \
+lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \
ptrace.o ptrace_user.o sigcontext.o signal.o stub.o \
stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o
@@ -14,7 +14,7 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
USER_OBJS := ptrace_user.o sigcontext.o
-SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
+SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \
thunk.S module.c
include arch/um/scripts/Makefile.rules
@@ -23,6 +23,7 @@ bitops.c-dir = lib
csum-copy.S-dir = lib
csum-partial.c-dir = lib
csum-wrappers.c-dir = lib
+ldt.c-dir = /arch/um/sys-i386
memcpy.S-dir = lib
thunk.S-dir = lib
module.c-dir = kernel
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 3259a4db4534..6acee5c4ada6 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -29,81 +29,6 @@ asmlinkage long sys_uname64(struct new_utsname __user * name)
}
#ifdef CONFIG_MODE_TT
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-
-long sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
-{
- /* XXX This should check VERIFY_WRITE depending on func, check this
- * in i386 as well.
- */
- if (!access_ok(VERIFY_READ, ptr, bytecount))
- return -EFAULT;
- return(modify_ldt(func, ptr, bytecount));
-}
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-extern int userspace_pid[];
-
-#include "skas_ptrace.h"
-
-long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
-{
- struct ptrace_ldt ldt;
- void *buf;
- int res, n;
-
- buf = kmalloc(bytecount, GFP_KERNEL);
- if(buf == NULL)
- return(-ENOMEM);
-
- res = 0;
-
- switch(func){
- case 1:
- case 0x11:
- res = copy_from_user(buf, ptr, bytecount);
- break;
- }
-
- if(res != 0){
- res = -EFAULT;
- goto out;
- }
-
- ldt = ((struct ptrace_ldt) { .func = func,
- .ptr = buf,
- .bytecount = bytecount });
-#warning Need to look up userspace_pid by cpu
- res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt);
- if(res < 0)
- goto out;
-
- switch(func){
- case 0:
- case 2:
- n = res;
- res = copy_to_user(ptr, buf, n);
- if(res != 0)
- res = -EFAULT;
- else
- res = n;
- break;
- }
-
- out:
- kfree(buf);
- return(res);
-}
-#endif
-
-long sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
-{
- return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func,
- ptr, bytecount));
-}
-
-#ifdef CONFIG_MODE_TT
extern long arch_prctl(int code, unsigned long addr);
static long arch_prctl_tt(int code, unsigned long addr)
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index d6077ff47d22..18492d02aaf6 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -113,45 +113,10 @@ static int set_single_step (struct task_struct *t, int val)
return 1;
}
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int rval;
- lock_kernel();
-
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED) {
- rval = -EPERM;
- goto out;
- }
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- rval = 0;
- goto out;
- }
- rval = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- rval = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- rval = ptrace_attach(child);
- goto out_tsk;
- }
- rval = ptrace_check_attach(child, request == PTRACE_KILL);
- if (rval < 0)
- goto out_tsk;
-
switch (request) {
unsigned long val, copied;
@@ -248,11 +213,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
rval = -EIO;
goto out;
}
-
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+ out:
return rval;
}
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 21afa69a086d..4cce2f6f170c 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -532,8 +532,21 @@ source "drivers/firmware/Kconfig"
source fs/Kconfig
+menu "Instrumentation Support"
+ depends on EXPERIMENTAL
+
source "arch/x86_64/oprofile/Kconfig"
+config KPROBES
+ bool "Kprobes (EXPERIMENTAL)"
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+endmenu
+
source "arch/x86_64/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
index 9cf1410d2f5a..d584ecc27ea1 100644
--- a/arch/x86_64/Kconfig.debug
+++ b/arch/x86_64/Kconfig.debug
@@ -33,16 +33,6 @@ config IOMMU_DEBUG
options. See Documentation/x86_64/boot-options.txt for more
details.
-config KPROBES
- bool "Kprobes"
- depends on DEBUG_KERNEL
- help
- Kprobes allows you to trap at almost any kernel address and
- execute a callback function. register_kprobe() establishes
- a probepoint and specifies the callback. Kprobes is useful
- for kernel debugging, non-intrusive instrumentation and testing.
- If in doubt, say "N".
-
config IOMMU_LEAK
bool "IOMMU leak tracing"
depends on DEBUG_KERNEL
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index 76a28b007be9..dddeb678b440 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -34,7 +34,6 @@
#include <linux/config.h>
#include <linux/kprobes.h>
#include <linux/ptrace.h>
-#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/preempt.h>
@@ -44,17 +43,10 @@
#include <asm/kdebug.h>
static DECLARE_MUTEX(kprobe_mutex);
-
-static struct kprobe *current_kprobe;
-static unsigned long kprobe_status, kprobe_old_rflags, kprobe_saved_rflags;
-static struct kprobe *kprobe_prev;
-static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev;
-static struct pt_regs jprobe_saved_regs;
-static long *jprobe_saved_rsp;
void jprobe_return_end(void);
-/* copy of the kernel stack at the probe fire time */
-static kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
/*
* returns non-zero if opcode modifies the interrupt flag.
@@ -236,29 +228,30 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
up(&kprobe_mutex);
}
-static inline void save_previous_kprobe(void)
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- kprobe_prev = current_kprobe;
- kprobe_status_prev = kprobe_status;
- kprobe_old_rflags_prev = kprobe_old_rflags;
- kprobe_saved_rflags_prev = kprobe_saved_rflags;
+ kcb->prev_kprobe.kp = kprobe_running();
+ kcb->prev_kprobe.status = kcb->kprobe_status;
+ kcb->prev_kprobe.old_rflags = kcb->kprobe_old_rflags;
+ kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags;
}
-static inline void restore_previous_kprobe(void)
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
{
- current_kprobe = kprobe_prev;
- kprobe_status = kprobe_status_prev;
- kprobe_old_rflags = kprobe_old_rflags_prev;
- kprobe_saved_rflags = kprobe_saved_rflags_prev;
+ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+ kcb->kprobe_status = kcb->prev_kprobe.status;
+ kcb->kprobe_old_rflags = kcb->prev_kprobe.old_rflags;
+ kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags;
}
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
{
- current_kprobe = p;
- kprobe_saved_rflags = kprobe_old_rflags
+ __get_cpu_var(current_kprobe) = p;
+ kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags
= (regs->eflags & (TF_MASK | IF_MASK));
if (is_IF_modifier(p->ainsn.insn))
- kprobe_saved_rflags &= ~IF_MASK;
+ kcb->kprobe_saved_rflags &= ~IF_MASK;
}
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -272,6 +265,7 @@ static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->rip = (unsigned long)p->ainsn.insn;
}
+/* Called with kretprobe_lock held */
void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
struct pt_regs *regs)
{
@@ -292,32 +286,30 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
}
}
-/*
- * Interrupts are disabled on entry as trap3 is an interrupt gate and they
- * remain disabled thorough out this function.
- */
int __kprobes kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
int ret = 0;
kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t));
+ struct kprobe_ctlblk *kcb;
- /* We're in an interrupt, but this is clear and BUG()-safe. */
+ /*
+ * We don't want to be preempted for the entire
+ * duration of kprobe processing
+ */
preempt_disable();
+ kcb = get_kprobe_ctlblk();
/* Check we're not actually recursing */
if (kprobe_running()) {
- /* We *are* holding lock here, so this is safe.
- Disarm the probe we just hit, and ignore it. */
p = get_kprobe(addr);
if (p) {
- if (kprobe_status == KPROBE_HIT_SS &&
+ if (kcb->kprobe_status == KPROBE_HIT_SS &&
*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
regs->eflags &= ~TF_MASK;
- regs->eflags |= kprobe_saved_rflags;
- unlock_kprobes();
+ regs->eflags |= kcb->kprobe_saved_rflags;
goto no_kprobe;
- } else if (kprobe_status == KPROBE_HIT_SSDONE) {
+ } else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
/* TODO: Provide re-entrancy from
* post_kprobes_handler() and avoid exception
* stack corruption while single-stepping on
@@ -325,6 +317,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
*/
arch_disarm_kprobe(p);
regs->rip = (unsigned long)p->addr;
+ reset_current_kprobe();
ret = 1;
} else {
/* We have reentered the kprobe_handler(), since
@@ -334,27 +327,24 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
* of the new probe without calling any user
* handlers.
*/
- save_previous_kprobe();
- set_current_kprobe(p, regs);
+ save_previous_kprobe(kcb);
+ set_current_kprobe(p, regs, kcb);
p->nmissed++;
prepare_singlestep(p, regs);
- kprobe_status = KPROBE_REENTER;
+ kcb->kprobe_status = KPROBE_REENTER;
return 1;
}
} else {
- p = current_kprobe;
+ p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
goto ss_probe;
}
}
- /* If it's not ours, can't be delete race, (we hold lock). */
goto no_kprobe;
}
- lock_kprobes();
p = get_kprobe(addr);
if (!p) {
- unlock_kprobes();
if (*addr != BREAKPOINT_INSTRUCTION) {
/*
* The breakpoint instruction was removed right
@@ -372,8 +362,8 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
goto no_kprobe;
}
- kprobe_status = KPROBE_HIT_ACTIVE;
- set_current_kprobe(p, regs);
+ set_current_kprobe(p, regs, kcb);
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
@@ -381,7 +371,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
ss_probe:
prepare_singlestep(p, regs);
- kprobe_status = KPROBE_HIT_SS;
+ kcb->kprobe_status = KPROBE_HIT_SS;
return 1;
no_kprobe:
@@ -409,9 +399,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
struct kretprobe_instance *ri = NULL;
struct hlist_head *head;
struct hlist_node *node, *tmp;
- unsigned long orig_ret_address = 0;
+ unsigned long flags, orig_ret_address = 0;
unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+ spin_lock_irqsave(&kretprobe_lock, flags);
head = kretprobe_inst_table_head(current);
/*
@@ -450,13 +441,14 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
regs->rip = orig_ret_address;
- unlock_kprobes();
+ reset_current_kprobe();
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
preempt_enable_no_resched();
/*
* By returning a non-zero value, we are telling
- * kprobe_handler() that we have handled unlocking
- * and re-enabling preemption.
+ * kprobe_handler() that we don't want the post_handler
+ * to run (and have re-enabled preemption)
*/
return 1;
}
@@ -483,7 +475,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
* that is atop the stack is the address following the copied instruction.
* We need to make it the address following the original instruction.
*/
-static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes resume_execution(struct kprobe *p,
+ struct pt_regs *regs, struct kprobe_ctlblk *kcb)
{
unsigned long *tos = (unsigned long *)regs->rsp;
unsigned long next_rip = 0;
@@ -498,7 +491,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
switch (*insn) {
case 0x9c: /* pushfl */
*tos &= ~(TF_MASK | IF_MASK);
- *tos |= kprobe_old_rflags;
+ *tos |= kcb->kprobe_old_rflags;
break;
case 0xc3: /* ret/lret */
case 0xcb:
@@ -537,30 +530,28 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
}
}
-/*
- * Interrupts are disabled on entry as trap1 is an interrupt gate and they
- * remain disabled thoroughout this function. And we hold kprobe lock.
- */
int __kprobes post_kprobe_handler(struct pt_regs *regs)
{
- if (!kprobe_running())
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (!cur)
return 0;
- if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
- kprobe_status = KPROBE_HIT_SSDONE;
- current_kprobe->post_handler(current_kprobe, regs, 0);
+ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+ kcb->kprobe_status = KPROBE_HIT_SSDONE;
+ cur->post_handler(cur, regs, 0);
}
- resume_execution(current_kprobe, regs);
- regs->eflags |= kprobe_saved_rflags;
+ resume_execution(cur, regs, kcb);
+ regs->eflags |= kcb->kprobe_saved_rflags;
/* Restore the original saved kprobes variables and continue. */
- if (kprobe_status == KPROBE_REENTER) {
- restore_previous_kprobe();
+ if (kcb->kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe(kcb);
goto out;
- } else {
- unlock_kprobes();
}
+ reset_current_kprobe();
out:
preempt_enable_no_resched();
@@ -575,18 +566,19 @@ out:
return 1;
}
-/* Interrupts disabled, kprobe_lock held. */
int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
- if (current_kprobe->fault_handler
- && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+ struct kprobe *cur = kprobe_running();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;
- if (kprobe_status & KPROBE_HIT_SS) {
- resume_execution(current_kprobe, regs);
- regs->eflags |= kprobe_old_rflags;
+ if (kcb->kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(cur, regs, kcb);
+ regs->eflags |= kcb->kprobe_old_rflags;
- unlock_kprobes();
+ reset_current_kprobe();
preempt_enable_no_resched();
}
return 0;
@@ -599,39 +591,41 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data)
{
struct die_args *args = (struct die_args *)data;
+ int ret = NOTIFY_DONE;
+
switch (val) {
case DIE_INT3:
if (kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_DEBUG:
if (post_kprobe_handler(args->regs))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
break;
case DIE_GPF:
- if (kprobe_running() &&
- kprobe_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
- break;
case DIE_PAGE_FAULT:
+ /* kprobe_running() needs smp_processor_id() */
+ preempt_disable();
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
- return NOTIFY_STOP;
+ ret = NOTIFY_STOP;
+ preempt_enable();
break;
default:
break;
}
- return NOTIFY_DONE;
+ return ret;
}
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
unsigned long addr;
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- jprobe_saved_regs = *regs;
- jprobe_saved_rsp = (long *) regs->rsp;
- addr = (unsigned long)jprobe_saved_rsp;
+ kcb->jprobe_saved_regs = *regs;
+ kcb->jprobe_saved_rsp = (long *) regs->rsp;
+ addr = (unsigned long)(kcb->jprobe_saved_rsp);
/*
* As Linus pointed out, gcc assumes that the callee
* owns the argument space and could overwrite it, e.g.
@@ -639,7 +633,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
* we also save and restore enough stack bytes to cover
* the argument area.
*/
- memcpy(jprobes_stack, (kprobe_opcode_t *) addr, MIN_STACK_SIZE(addr));
+ memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
+ MIN_STACK_SIZE(addr));
regs->eflags &= ~IF_MASK;
regs->rip = (unsigned long)(jp->entry);
return 1;
@@ -647,36 +642,40 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
void __kprobes jprobe_return(void)
{
- preempt_enable_no_resched();
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
asm volatile (" xchg %%rbx,%%rsp \n"
" int3 \n"
" .globl jprobe_return_end \n"
" jprobe_return_end: \n"
" nop \n"::"b"
- (jprobe_saved_rsp):"memory");
+ (kcb->jprobe_saved_rsp):"memory");
}
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
+ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
u8 *addr = (u8 *) (regs->rip - 1);
- unsigned long stack_addr = (unsigned long)jprobe_saved_rsp;
+ unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp);
struct jprobe *jp = container_of(p, struct jprobe, kp);
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
- if ((long *)regs->rsp != jprobe_saved_rsp) {
+ if ((long *)regs->rsp != kcb->jprobe_saved_rsp) {
struct pt_regs *saved_regs =
- container_of(jprobe_saved_rsp, struct pt_regs, rsp);
+ container_of(kcb->jprobe_saved_rsp,
+ struct pt_regs, rsp);
printk("current rsp %p does not match saved rsp %p\n",
- (long *)regs->rsp, jprobe_saved_rsp);
+ (long *)regs->rsp, kcb->jprobe_saved_rsp);
printk("Saved registers for jprobe %p\n", jp);
show_registers(saved_regs);
printk("Current registers\n");
show_registers(regs);
BUG();
}
- *regs = jprobe_saved_regs;
- memcpy((kprobe_opcode_t *) stack_addr, jprobes_stack,
+ *regs = kcb->jprobe_saved_regs;
+ memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack,
MIN_STACK_SIZE(stack_addr));
+ preempt_enable_no_resched();
return 1;
}
return 0;
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index bbf64b59a21e..a87b6cebe80f 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -313,48 +313,11 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
}
-asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
long i, ret;
unsigned ui;
- /* This lock_kernel fixes a subtle race with suid exec */
- lock_kernel();
- ret = -EPERM;
- if (request == PTRACE_TRACEME) {
- /* are we already being traced? */
- if (current->ptrace & PT_PTRACED)
- goto out;
- ret = security_ptrace(current->parent, current);
- if (ret)
- goto out;
- /* set the ptrace bit in the process flags. */
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out_tsk;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
- ret = ptrace_check_attach(child, request == PTRACE_KILL);
- if (ret < 0)
- goto out_tsk;
-
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
@@ -608,10 +571,6 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
ret = ptrace_request(child, request, addr, data);
break;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
return ret;
}
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 658a81b33f3b..4b5b088ec102 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -65,8 +65,6 @@ int smp_num_siblings = 1;
/* Package ID of each logical CPU */
u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
-EXPORT_SYMBOL(phys_proc_id);
-EXPORT_SYMBOL(cpu_core_id);
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map __read_mostly;
diff --git a/arch/x86_64/oprofile/Kconfig b/arch/x86_64/oprofile/Kconfig
index 5ade19801b97..d8a84088471a 100644
--- a/arch/x86_64/oprofile/Kconfig
+++ b/arch/x86_64/oprofile/Kconfig
@@ -1,7 +1,3 @@
-
-menu "Profiling support"
- depends on EXPERIMENTAL
-
config PROFILING
bool "Profiling support (EXPERIMENTAL)"
help
@@ -19,5 +15,3 @@ config OPROFILE
If unsure, say N.
-endmenu
-
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 14460743de07..ab5c4c65b5c4 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -45,58 +45,10 @@ void ptrace_disable(struct task_struct *child)
/* Nothing to do.. */
}
-long sys_ptrace(long request, long pid, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
- struct task_struct *child;
int ret = -EPERM;
- lock_kernel();
-
-#if 0
- if ((int)request != 1)
- printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
- (int) request, (int) pid, (unsigned long) addr,
- (unsigned long) data);
-#endif
-
- if (request == PTRACE_TRACEME) {
-
- /* Are we already being traced? */
-
- if (current->ptrace & PT_PTRACED)
- goto out;
-
- if ((ret = security_ptrace(current->parent, current)))
- goto out;
-
- /* Set the ptrace bit in the process flags. */
-
- current->ptrace |= PT_PTRACED;
- ret = 0;
- goto out;
- }
-
- ret = -ESRCH;
- read_lock(&tasklist_lock);
- child = find_task_by_pid(pid);
- if (child)
- get_task_struct(child);
- read_unlock(&tasklist_lock);
- if (!child)
- goto out;
-
- ret = -EPERM;
- if (pid == 1) /* you may not mess with init */
- goto out;
-
- if (request == PTRACE_ATTACH) {
- ret = ptrace_attach(child);
- goto out_tsk;
- }
-
- if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0)
- goto out_tsk;
-
switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA:
@@ -375,10 +327,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data);
goto out;
}
-out_tsk:
- put_task_struct(child);
-out:
- unlock_kernel();
+ out:
return ret;
}
diff --git a/drivers/Makefile b/drivers/Makefile
index 65670be6ff1a..fac1e1603097 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_PCI) += pci/ usb/
obj-$(CONFIG_PARISC) += parisc/
+obj-$(CONFIG_RAPIDIO) += rapidio/
obj-y += video/
obj-$(CONFIG_ACPI) += acpi/
# PnP must come after ACPI since it will eventually need to check if acpi
@@ -67,3 +68,4 @@ obj-$(CONFIG_INFINIBAND) += infiniband/
obj-$(CONFIG_SGI_IOC4) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
+obj-$(CONFIG_SUPERH) += sh/
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 10dd695a1dd9..27ec12c1fab0 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -118,11 +118,9 @@ static int acpi_container_remove(struct acpi_device *device, int type)
{
acpi_status status = AE_OK;
struct acpi_container *pc = NULL;
- pc = (struct acpi_container *)acpi_driver_data(device);
-
- if (pc)
- kfree(pc);
+ pc = (struct acpi_container *)acpi_driver_data(device);
+ kfree(pc);
return status;
}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index d528c750a380..e3cd0b16031a 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -313,8 +313,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
void acpi_os_sleep(acpi_integer ms)
{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(((signed long)ms * HZ) / 1000);
+ schedule_timeout_interruptible(msecs_to_jiffies(ms));
}
EXPORT_SYMBOL(acpi_os_sleep);
@@ -838,8 +837,7 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
ret = down_trylock(sem);
for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
ret = down_trylock(sem);
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index c6db591479de..23e2c6968a11 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -28,8 +28,7 @@ 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);
- if (dev->pnp.cid_list)
- kfree(dev->pnp.cid_list);
+ kfree(dev->pnp.cid_list);
kfree(dev);
}
@@ -1117,8 +1116,7 @@ acpi_add_single_object(struct acpi_device **child,
if (!result)
*child = device;
else {
- if (device->pnp.cid_list)
- kfree(device->pnp.cid_list);
+ kfree(device->pnp.cid_list);
kfree(device);
}
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index e383d6109ae1..f051b151580d 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -334,8 +334,7 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
return_VALUE(0);
err:
- if (buffer.pointer)
- kfree(buffer.pointer);
+ kfree(buffer.pointer);
return_VALUE(status);
}
@@ -1488,8 +1487,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
}
active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END;
- if (video->attached_array)
- kfree(video->attached_array);
+ kfree(video->attached_array);
video->attached_array = active_device_list;
video->attached_count = count;
@@ -1645,8 +1643,7 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
printk(KERN_WARNING PREFIX
"hhuuhhuu bug in acpi video driver.\n");
- if (data->brightness)
- kfree(data->brightness);
+ kfree(data->brightness);
kfree(data);
}
@@ -1831,8 +1828,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
acpi_video_bus_put_devices(video);
acpi_video_bus_remove_fs(device);
- if (video->attached_array)
- kfree(video->attached_array);
+ kfree(video->attached_array);
kfree(video);
return_VALUE(0);
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 89c57875f3e5..f3a0c562bcb5 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -3,6 +3,7 @@
*/
#include <linux/device.h>
+#include <linux/string.h>
#include "power.h"
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 3760edfdc65c..70eaa5c7ac08 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -417,14 +417,12 @@ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller)
* Remember the beginning of the group, but don't free it
* until we've reached the beginning of the next group.
*/
- if (CommandGroup != NULL)
- kfree(CommandGroup);
- CommandGroup = Command;
+ kfree(CommandGroup);
+ CommandGroup = Command;
}
Controller->Commands[i] = NULL;
}
- if (CommandGroup != NULL)
- kfree(CommandGroup);
+ kfree(CommandGroup);
if (Controller->CombinedStatusBuffer != NULL)
{
@@ -435,30 +433,23 @@ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller)
if (ScatterGatherPool != NULL)
pci_pool_destroy(ScatterGatherPool);
- if (Controller->FirmwareType == DAC960_V1_Controller) return;
+ if (Controller->FirmwareType == DAC960_V1_Controller)
+ return;
if (RequestSensePool != NULL)
pci_pool_destroy(RequestSensePool);
- for (i = 0; i < DAC960_MaxLogicalDrives; i++)
- if (Controller->V2.LogicalDeviceInformation[i] != NULL)
- {
+ for (i = 0; i < DAC960_MaxLogicalDrives; i++) {
kfree(Controller->V2.LogicalDeviceInformation[i]);
Controller->V2.LogicalDeviceInformation[i] = NULL;
- }
+ }
for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++)
{
- if (Controller->V2.PhysicalDeviceInformation[i] != NULL)
- {
- kfree(Controller->V2.PhysicalDeviceInformation[i]);
- Controller->V2.PhysicalDeviceInformation[i] = NULL;
- }
- if (Controller->V2.InquiryUnitSerialNumber[i] != NULL)
- {
- kfree(Controller->V2.InquiryUnitSerialNumber[i]);
- Controller->V2.InquiryUnitSerialNumber[i] = NULL;
- }
+ kfree(Controller->V2.PhysicalDeviceInformation[i]);
+ Controller->V2.PhysicalDeviceInformation[i] = NULL;
+ kfree(Controller->V2.InquiryUnitSerialNumber[i]);
+ Controller->V2.InquiryUnitSerialNumber[i] = NULL;
}
}
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index c6744ff38294..a78e160b59a3 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -4,7 +4,7 @@
* Anticipatory & deadline i/o scheduler.
*
* Copyright (C) 2002 Jens Axboe <axboe@suse.de>
- * Nick Piggin <piggin@cyberone.com.au>
+ * Nick Piggin <nickpiggin@yahoo.com.au>
*
*/
#include <linux/kernel.h>
@@ -69,7 +69,7 @@
/* Bits in as_io_context.state */
enum as_io_states {
- AS_TASK_RUNNING=0, /* Process has not exitted */
+ AS_TASK_RUNNING=0, /* Process has not exited */
AS_TASK_IOSTARTED, /* Process has started some IO */
AS_TASK_IORUNNING, /* Process has completed some IO */
};
@@ -102,6 +102,9 @@ struct as_data {
unsigned long exit_prob; /* probability a task will exit while
being waited on */
+ unsigned long exit_no_coop; /* probablility an exited task will
+ not be part of a later cooperating
+ request */
unsigned long new_ttime_total; /* mean thinktime on new proc */
unsigned long new_ttime_mean;
u64 new_seek_total; /* mean seek on new proc */
@@ -636,37 +639,152 @@ static void as_antic_timeout(unsigned long data)
kblockd_schedule_work(&ad->antic_work);
if (aic->ttime_samples == 0) {
- /* process anticipated on has exitted or timed out*/
+ /* process anticipated on has exited or timed out*/
ad->exit_prob = (7*ad->exit_prob + 256)/8;
}
+ if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
+ /* process not "saved" by a cooperating request */
+ ad->exit_no_coop = (7*ad->exit_no_coop + 256)/8;
+ }
}
spin_unlock_irqrestore(q->queue_lock, flags);
}
+static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic,
+ unsigned long ttime)
+{
+ /* fixed point: 1.0 == 1<<8 */
+ if (aic->ttime_samples == 0) {
+ ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8;
+ ad->new_ttime_mean = ad->new_ttime_total / 256;
+
+ ad->exit_prob = (7*ad->exit_prob)/8;
+ }
+ aic->ttime_samples = (7*aic->ttime_samples + 256) / 8;
+ aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8;
+ aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples;
+}
+
+static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic,
+ sector_t sdist)
+{
+ u64 total;
+
+ if (aic->seek_samples == 0) {
+ ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8;
+ ad->new_seek_mean = ad->new_seek_total / 256;
+ }
+
+ /*
+ * Don't allow the seek distance to get too large from the
+ * odd fragment, pagein, etc
+ */
+ if (aic->seek_samples <= 60) /* second&third seek */
+ sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024);
+ else
+ sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64);
+
+ aic->seek_samples = (7*aic->seek_samples + 256) / 8;
+ aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8;
+ total = aic->seek_total + (aic->seek_samples/2);
+ do_div(total, aic->seek_samples);
+ aic->seek_mean = (sector_t)total;
+}
+
+/*
+ * as_update_iohist keeps a decaying histogram of IO thinktimes, and
+ * updates @aic->ttime_mean based on that. It is called when a new
+ * request is queued.
+ */
+static void as_update_iohist(struct as_data *ad, struct as_io_context *aic,
+ struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+ int data_dir = arq->is_sync;
+ unsigned long thinktime = 0;
+ sector_t seek_dist;
+
+ if (aic == NULL)
+ return;
+
+ if (data_dir == REQ_SYNC) {
+ unsigned long in_flight = atomic_read(&aic->nr_queued)
+ + atomic_read(&aic->nr_dispatched);
+ spin_lock(&aic->lock);
+ if (test_bit(AS_TASK_IORUNNING, &aic->state) ||
+ test_bit(AS_TASK_IOSTARTED, &aic->state)) {
+ /* Calculate read -> read thinktime */
+ if (test_bit(AS_TASK_IORUNNING, &aic->state)
+ && in_flight == 0) {
+ thinktime = jiffies - aic->last_end_request;
+ thinktime = min(thinktime, MAX_THINKTIME-1);
+ }
+ as_update_thinktime(ad, aic, thinktime);
+
+ /* Calculate read -> read seek distance */
+ if (aic->last_request_pos < rq->sector)
+ seek_dist = rq->sector - aic->last_request_pos;
+ else
+ seek_dist = aic->last_request_pos - rq->sector;
+ as_update_seekdist(ad, aic, seek_dist);
+ }
+ aic->last_request_pos = rq->sector + rq->nr_sectors;
+ set_bit(AS_TASK_IOSTARTED, &aic->state);
+ spin_unlock(&aic->lock);
+ }
+}
+
/*
* as_close_req decides if one request is considered "close" to the
* previous one issued.
*/
-static int as_close_req(struct as_data *ad, struct as_rq *arq)
+static int as_close_req(struct as_data *ad, struct as_io_context *aic,
+ struct as_rq *arq)
{
unsigned long delay; /* milliseconds */
sector_t last = ad->last_sector[ad->batch_data_dir];
sector_t next = arq->request->sector;
sector_t delta; /* acceptable close offset (in sectors) */
+ sector_t s;
if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished)
delay = 0;
else
delay = ((jiffies - ad->antic_start) * 1000) / HZ;
- if (delay <= 1)
- delta = 64;
+ if (delay == 0)
+ delta = 8192;
else if (delay <= 20 && delay <= ad->antic_expire)
- delta = 64 << (delay-1);
+ delta = 8192 << delay;
else
return 1;
- return (last - (delta>>1) <= next) && (next <= last + delta);
+ if ((last <= next + (delta>>1)) && (next <= last + delta))
+ return 1;
+
+ if (last < next)
+ s = next - last;
+ else
+ s = last - next;
+
+ if (aic->seek_samples == 0) {
+ /*
+ * Process has just started IO. Use past statistics to
+ * gauge success possibility
+ */
+ if (ad->new_seek_mean > s) {
+ /* this request is better than what we're expecting */
+ return 1;
+ }
+
+ } else {
+ if (aic->seek_mean > s) {
+ /* this request is better than what we're expecting */
+ return 1;
+ }
+ }
+
+ return 0;
}
/*
@@ -678,7 +796,7 @@ static int as_close_req(struct as_data *ad, struct as_rq *arq)
* dispatch it ASAP, because we know that application will not be submitting
* any new reads.
*
- * If the task which has submitted the request has exitted, break anticipation.
+ * If the task which has submitted the request has exited, break anticipation.
*
* If this task has queued some other IO, do not enter enticipation.
*/
@@ -686,7 +804,6 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
{
struct io_context *ioc;
struct as_io_context *aic;
- sector_t s;
ioc = ad->io_context;
BUG_ON(!ioc);
@@ -708,13 +825,6 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
if (!aic)
return 0;
- if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
- /* process anticipated on has exitted */
- if (aic->ttime_samples == 0)
- ad->exit_prob = (7*ad->exit_prob + 256)/8;
- return 1;
- }
-
if (atomic_read(&aic->nr_queued) > 0) {
/* process has more requests queued */
return 1;
@@ -725,57 +835,45 @@ static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
return 1;
}
- if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, arq)) {
+ if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, aic, arq)) {
/*
* Found a close request that is not one of ours.
*
- * This makes close requests from another process reset
- * our thinktime delay. Is generally useful when there are
+ * This makes close requests from another process update
+ * our IO history. Is generally useful when there are
* two or more cooperating processes working in the same
* area.
*/
- spin_lock(&aic->lock);
- aic->last_end_request = jiffies;
- spin_unlock(&aic->lock);
+ if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
+ if (aic->ttime_samples == 0)
+ ad->exit_prob = (7*ad->exit_prob + 256)/8;
+
+ ad->exit_no_coop = (7*ad->exit_no_coop)/8;
+ }
+
+ as_update_iohist(ad, aic, arq->request);
return 1;
}
+ if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
+ /* process anticipated on has exited */
+ if (aic->ttime_samples == 0)
+ ad->exit_prob = (7*ad->exit_prob + 256)/8;
+
+ if (ad->exit_no_coop > 128)
+ return 1;
+ }
if (aic->ttime_samples == 0) {
if (ad->new_ttime_mean > ad->antic_expire)
return 1;
- if (ad->exit_prob > 128)
+ if (ad->exit_prob * ad->exit_no_coop > 128*256)
return 1;
} else if (aic->ttime_mean > ad->antic_expire) {
/* the process thinks too much between requests */
return 1;
}
- if (!arq)
- return 0;
-
- if (ad->last_sector[REQ_SYNC] < arq->request->sector)
- s = arq->request->sector - ad->last_sector[REQ_SYNC];
- else
- s = ad->last_sector[REQ_SYNC] - arq->request->sector;
-
- if (aic->seek_samples == 0) {
- /*
- * Process has just started IO. Use past statistics to
- * guage success possibility
- */
- if (ad->new_seek_mean > s) {
- /* this request is better than what we're expecting */
- return 1;
- }
-
- } else {
- if (aic->seek_mean > s) {
- /* this request is better than what we're expecting */
- return 1;
- }
- }
-
return 0;
}
@@ -809,94 +907,11 @@ static int as_can_anticipate(struct as_data *ad, struct as_rq *arq)
* Status is either ANTIC_OFF so start waiting,
* ANTIC_WAIT_REQ so continue waiting for request to finish
* or ANTIC_WAIT_NEXT so continue waiting for an acceptable request.
- *
*/
return 1;
}
-static void as_update_thinktime(struct as_data *ad, struct as_io_context *aic, unsigned long ttime)
-{
- /* fixed point: 1.0 == 1<<8 */
- if (aic->ttime_samples == 0) {
- ad->new_ttime_total = (7*ad->new_ttime_total + 256*ttime) / 8;
- ad->new_ttime_mean = ad->new_ttime_total / 256;
-
- ad->exit_prob = (7*ad->exit_prob)/8;
- }
- aic->ttime_samples = (7*aic->ttime_samples + 256) / 8;
- aic->ttime_total = (7*aic->ttime_total + 256*ttime) / 8;
- aic->ttime_mean = (aic->ttime_total + 128) / aic->ttime_samples;
-}
-
-static void as_update_seekdist(struct as_data *ad, struct as_io_context *aic, sector_t sdist)
-{
- u64 total;
-
- if (aic->seek_samples == 0) {
- ad->new_seek_total = (7*ad->new_seek_total + 256*(u64)sdist)/8;
- ad->new_seek_mean = ad->new_seek_total / 256;
- }
-
- /*
- * Don't allow the seek distance to get too large from the
- * odd fragment, pagein, etc
- */
- if (aic->seek_samples <= 60) /* second&third seek */
- sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*1024);
- else
- sdist = min(sdist, (aic->seek_mean * 4) + 2*1024*64);
-
- aic->seek_samples = (7*aic->seek_samples + 256) / 8;
- aic->seek_total = (7*aic->seek_total + (u64)256*sdist) / 8;
- total = aic->seek_total + (aic->seek_samples/2);
- do_div(total, aic->seek_samples);
- aic->seek_mean = (sector_t)total;
-}
-
-/*
- * as_update_iohist keeps a decaying histogram of IO thinktimes, and
- * updates @aic->ttime_mean based on that. It is called when a new
- * request is queued.
- */
-static void as_update_iohist(struct as_data *ad, struct as_io_context *aic, struct request *rq)
-{
- struct as_rq *arq = RQ_DATA(rq);
- int data_dir = arq->is_sync;
- unsigned long thinktime;
- sector_t seek_dist;
-
- if (aic == NULL)
- return;
-
- if (data_dir == REQ_SYNC) {
- unsigned long in_flight = atomic_read(&aic->nr_queued)
- + atomic_read(&aic->nr_dispatched);
- spin_lock(&aic->lock);
- if (test_bit(AS_TASK_IORUNNING, &aic->state) ||
- test_bit(AS_TASK_IOSTARTED, &aic->state)) {
- /* Calculate read -> read thinktime */
- if (test_bit(AS_TASK_IORUNNING, &aic->state)
- && in_flight == 0) {
- thinktime = jiffies - aic->last_end_request;
- thinktime = min(thinktime, MAX_THINKTIME-1);
- } else
- thinktime = 0;
- as_update_thinktime(ad, aic, thinktime);
-
- /* Calculate read -> read seek distance */
- if (aic->last_request_pos < rq->sector)
- seek_dist = rq->sector - aic->last_request_pos;
- else
- seek_dist = aic->last_request_pos - rq->sector;
- as_update_seekdist(ad, aic, seek_dist);
- }
- aic->last_request_pos = rq->sector + rq->nr_sectors;
- set_bit(AS_TASK_IOSTARTED, &aic->state);
- spin_unlock(&aic->lock);
- }
-}
-
/*
* as_update_arq must be called whenever a request (arq) is added to
* the sort_list. This function keeps caches up to date, and checks if the
@@ -1201,7 +1216,7 @@ static int as_dispatch_request(request_queue_t *q, int force)
|| ad->changed_batch)
return 0;
- if (!(reads && writes && as_batch_expired(ad)) ) {
+ if (!(reads && writes && as_batch_expired(ad))) {
/*
* batch is still running or no reads or no writes
*/
@@ -1316,7 +1331,8 @@ fifo_expired:
* Add arq to a list behind alias
*/
static inline void
-as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alias)
+as_add_aliased_request(struct as_data *ad, struct as_rq *arq,
+ struct as_rq *alias)
{
struct request *req = arq->request;
struct list_head *insert = alias->request->queuelist.prev;
@@ -1441,8 +1457,8 @@ static int as_queue_empty(request_queue_t *q)
&& list_empty(&ad->fifo_list[REQ_SYNC]);
}
-static struct request *
-as_former_request(request_queue_t *q, struct request *rq)
+static struct request *as_former_request(request_queue_t *q,
+ struct request *rq)
{
struct as_rq *arq = RQ_DATA(rq);
struct rb_node *rbprev = rb_prev(&arq->rb_node);
@@ -1454,8 +1470,8 @@ as_former_request(request_queue_t *q, struct request *rq)
return ret;
}
-static struct request *
-as_latter_request(request_queue_t *q, struct request *rq)
+static struct request *as_latter_request(request_queue_t *q,
+ struct request *rq)
{
struct as_rq *arq = RQ_DATA(rq);
struct rb_node *rbnext = rb_next(&arq->rb_node);
@@ -1537,7 +1553,7 @@ static void as_merged_request(request_queue_t *q, struct request *req)
* currently don't bother. Ditto the next function.
*/
as_del_arq_rb(ad, arq);
- if ((alias = as_add_arq_rb(ad, arq)) ) {
+ if ((alias = as_add_arq_rb(ad, arq))) {
list_del_init(&arq->fifo);
as_add_aliased_request(ad, arq, alias);
if (next_arq)
@@ -1551,9 +1567,8 @@ static void as_merged_request(request_queue_t *q, struct request *req)
}
}
-static void
-as_merged_requests(request_queue_t *q, struct request *req,
- struct request *next)
+static void as_merged_requests(request_queue_t *q, struct request *req,
+ struct request *next)
{
struct as_data *ad = q->elevator->elevator_data;
struct as_rq *arq = RQ_DATA(req);
@@ -1576,7 +1591,7 @@ as_merged_requests(request_queue_t *q, struct request *req,
next_arq = as_find_next_arq(ad, arq);
as_del_arq_rb(ad, arq);
- if ((alias = as_add_arq_rb(ad, arq)) ) {
+ if ((alias = as_add_arq_rb(ad, arq))) {
list_del_init(&arq->fifo);
as_add_aliased_request(ad, arq, alias);
if (next_arq)
@@ -1806,9 +1821,14 @@ static ssize_t as_est_show(struct as_data *ad, char *page)
{
int pos = 0;
- pos += sprintf(page+pos, "%lu %% exit probability\n", 100*ad->exit_prob/256);
+ pos += sprintf(page+pos, "%lu %% exit probability\n",
+ 100*ad->exit_prob/256);
+ pos += sprintf(page+pos, "%lu %% probability of exiting without a "
+ "cooperating process submitting IO\n",
+ 100*ad->exit_no_coop/256);
pos += sprintf(page+pos, "%lu ms new thinktime\n", ad->new_ttime_mean);
- pos += sprintf(page+pos, "%llu sectors new seek distance\n", (unsigned long long)ad->new_seek_mean);
+ pos += sprintf(page+pos, "%llu sectors new seek distance\n",
+ (unsigned long long)ad->new_seek_mean);
return pos;
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 486b6e1c7dfb..a97c80b57737 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1096,14 +1096,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
cleanup1:
if (buff) {
for(i=0; i<sg_used; i++)
- if(buff[i] != NULL)
- kfree(buff[i]);
+ kfree(buff[i]);
kfree(buff);
}
- if (buff_size)
- kfree(buff_size);
- if (ioc)
- kfree(ioc);
+ kfree(buff_size);
+ kfree(ioc);
return(status);
}
default:
@@ -3034,8 +3031,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
return(1);
clean4:
- if(hba[i]->cmd_pool_bits)
- kfree(hba[i]->cmd_pool_bits);
+ kfree(hba[i]->cmd_pool_bits);
if(hba[i]->cmd_pool)
pci_free_consistent(hba[i]->pdev,
NR_CMDS * sizeof(CommandList_struct),
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 2747741677fb..5f52e30b43f8 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -706,7 +706,6 @@ EXPORT_SYMBOL(blk_queue_dma_alignment);
/**
* blk_queue_find_tag - find a request by its tag and queue
- *
* @q: The request queue for the device
* @tag: The tag of the request
*
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 5fd3e4cb7525..8e7fb3551775 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -179,14 +179,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
if (ignore || (intf->cur_altsetting->desc.bInterfaceNumber != 0))
return -ENODEV;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate memory for data structure");
return -ENOMEM;
}
- memset(data, 0, sizeof(*data));
-
data->udev = udev;
data->state = BCM203X_LOAD_MINIDRV;
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 1e9db0156ea7..067e27893e4a 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -673,13 +673,11 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
}
/* Initialize control structure and load firmware */
- if (!(bfusb = kmalloc(sizeof(struct bfusb), GFP_KERNEL))) {
+ if (!(bfusb = kzalloc(sizeof(struct bfusb), GFP_KERNEL))) {
BT_ERR("Can't allocate memory for control structure");
goto done;
}
- memset(bfusb, 0, sizeof(struct bfusb));
-
bfusb->udev = udev;
bfusb->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress;
bfusb->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress;
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 26fe9c0e1d20..f36c563d72c4 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -870,10 +870,9 @@ static dev_link_t *bluecard_attach(void)
int ret;
/* Create new info device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return NULL;
- memset(info, 0, sizeof(*info));
link = &info->link;
link->priv = info;
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 0db0400519c9..ecbeb7eaba8e 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -553,14 +553,12 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
return -ENODEV;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
BT_ERR("Can't allocate data structure");
return -ENOMEM;
}
- memset(data, 0, sizeof(*data));
-
data->udev = udev;
rwlock_init(&data->lock);
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 2e0338d80f32..d2a0add19cc8 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -671,10 +671,9 @@ static dev_link_t *bt3c_attach(void)
int ret;
/* Create new info device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return NULL;
- memset(info, 0, sizeof(*info));
link = &info->link;
link->priv = info;
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 89486ea7a021..529a28a3209d 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -590,10 +590,9 @@ static dev_link_t *btuart_attach(void)
int ret;
/* Create new info device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return NULL;
- memset(info, 0, sizeof(*info));
link = &info->link;
link->priv = info;
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 84c1f8839422..dec5980a1cd6 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -569,10 +569,9 @@ static dev_link_t *dtl1_attach(void)
int ret;
/* Create new info device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return NULL;
- memset(info, 0, sizeof(*info));
link = &info->link;
link->priv = info;
diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c
index 0a4761415ac3..8fddfdfd0fbd 100644
--- a/drivers/bluetooth/hci_bcsp.c
+++ b/drivers/bluetooth/hci_bcsp.c
@@ -715,10 +715,9 @@ static int bcsp_open(struct hci_uart *hu)
BT_DBG("hu %p", hu);
- bcsp = kmalloc(sizeof(*bcsp), GFP_ATOMIC);
+ bcsp = kzalloc(sizeof(*bcsp), GFP_ATOMIC);
if (!bcsp)
return -ENOMEM;
- memset(bcsp, 0, sizeof(*bcsp));
hu->priv = bcsp;
skb_queue_head_init(&bcsp->unack);
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index 12e369a66fc2..4804d474dc87 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -76,12 +76,10 @@ static int h4_open(struct hci_uart *hu)
BT_DBG("hu %p", hu);
- h4 = kmalloc(sizeof(*h4), GFP_ATOMIC);
+ h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
if (!h4)
return -ENOMEM;
- memset(h4, 0, sizeof(*h4));
-
skb_queue_head_init(&h4->txq);
hu->priv = h4;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 4a775f6ea390..573ff6c1be5f 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -272,13 +272,11 @@ static int hci_uart_tty_open(struct tty_struct *tty)
if (hu)
return -EEXIST;
- if (!(hu = kmalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
+ if (!(hu = kzalloc(sizeof(struct hci_uart), GFP_KERNEL))) {
BT_ERR("Can't allocate controll structure");
return -ENFILE;
}
- memset(hu, 0, sizeof(struct hci_uart));
-
tty->disc_data = hu;
hu->tty = tty;
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 6756cb20b753..f510b25b2c59 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -875,13 +875,11 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
goto done;
}
- if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) {
+ if (!(husb = kzalloc(sizeof(struct hci_usb), GFP_KERNEL))) {
BT_ERR("Can't allocate: control structure");
goto done;
}
- memset(husb, 0, sizeof(struct hci_usb));
-
husb->udev = udev;
husb->bulk_out_ep = bulk_out_ep;
husb->bulk_in_ep = bulk_in_ep;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 52cbd45c308f..85738223ff0c 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -261,12 +261,10 @@ static int vhci_open(struct inode *inode, struct file *file)
struct vhci_data *vhci;
struct hci_dev *hdev;
- vhci = kmalloc(sizeof(struct vhci_data), GFP_KERNEL);
+ vhci = kzalloc(sizeof(struct vhci_data), GFP_KERNEL);
if (!vhci)
return -ENOMEM;
- memset(vhci, 0, sizeof(struct vhci_data));
-
skb_queue_head_init(&vhci->readq);
init_waitqueue_head(&vhci->read_wait);
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index b89420e6d704..a0b580c22d80 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -1085,7 +1085,7 @@ static int __init mcdx_init_drive(int drive)
xtrace(INIT, "kmalloc space for stuffpt's\n");
xtrace(MALLOC, "init() malloc %d bytes\n", size);
- if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
+ if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
xwarn("init() malloc failed\n");
return 1;
}
@@ -1101,8 +1101,6 @@ static int __init mcdx_init_drive(int drive)
sizeof(*stuffp), stuffp);
/* set default values */
- memset(stuffp, 0, sizeof(*stuffp));
-
stuffp->present = 0; /* this should be 0 already */
stuffp->toc = NULL; /* this should be NULL already */
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 0e6c3a31d344..78ce98a69f37 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
+#include <linux/mmzone.h>
#include <asm/page.h> /* PAGE_SIZE */
#include "agp.h"
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 406dea914635..c85a4fa60da7 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -345,17 +345,15 @@ static void con_release_unimap(struct uni_pagedir *p)
for (i = 0; i < 32; i++) {
if ((p1 = p->uni_pgdir[i]) != NULL) {
for (j = 0; j < 32; j++)
- if (p1[j])
- kfree(p1[j]);
+ kfree(p1[j]);
kfree(p1);
}
p->uni_pgdir[i] = NULL;
}
- for (i = 0; i < 4; i++)
- if (p->inverse_translations[i]) {
- kfree(p->inverse_translations[i]);
- p->inverse_translations[i] = NULL;
- }
+ for (i = 0; i < 4; i++) {
+ kfree(p->inverse_translations[i]);
+ p->inverse_translations[i] = NULL;
+ }
}
void con_free_unimap(struct vc_data *vc)
diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
index 8a6cc2751bc9..1383727b443a 100644
--- a/drivers/char/drm/ffb_context.c
+++ b/drivers/char/drm/ffb_context.c
@@ -526,10 +526,8 @@ int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
if (idx < 0 || idx >= FFB_MAX_CTXS)
return -EINVAL;
- if (fpriv->hw_state[idx] != NULL) {
- kfree(fpriv->hw_state[idx]);
- fpriv->hw_state[idx] = NULL;
- }
+ kfree(fpriv->hw_state[idx]);
+ fpriv->hw_state[idx] = NULL;
return 0;
}
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
index 5c121d6df9f2..c13f9abb41e9 100644
--- a/drivers/char/drm/ffb_drv.c
+++ b/drivers/char/drm/ffb_drv.c
@@ -245,14 +245,12 @@ static void ffb_driver_release(drm_device_t * dev, struct file *filp)
static void ffb_driver_pretakedown(drm_device_t * dev)
{
- if (dev->dev_private)
- kfree(dev->dev_private);
+ kfree(dev->dev_private);
}
static int ffb_driver_postcleanup(drm_device_t * dev)
{
- if (ffb_position != NULL)
- kfree(ffb_position);
+ kfree(ffb_position);
return 0;
}
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c
index f834d05ccc97..dd761a1e4f08 100644
--- a/drivers/char/ip2/i2ellis.c
+++ b/drivers/char/ip2/i2ellis.c
@@ -106,9 +106,7 @@ iiEllisInit(void)
static void
iiEllisCleanup(void)
{
- if ( pDelayTimer != NULL ) {
- kfree ( pDelayTimer );
- }
+ kfree(pDelayTimer);
}
//******************************************************************************
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 33862670e285..58dcdee1cd71 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -28,6 +28,8 @@
#include <linux/kernel.h> /* For printk. */
#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
@@ -36,6 +38,8 @@ static int bt_debug = 0x00; /* Production value 0, see following flags */
#define BT_DEBUG_ENABLE 1
#define BT_DEBUG_MSG 2
#define BT_DEBUG_STATES 4
+module_param(bt_debug, int, 0644);
+MODULE_PARM_DESC(bt_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
/* Typical "Get BT Capabilities" values are 2-3 retries, 5-10 seconds,
and 64 byte buffers. However, one HP implementation wants 255 bytes of
@@ -43,7 +47,7 @@ static int bt_debug = 0x00; /* Production value 0, see following flags */
Since the Open IPMI architecture is single-message oriented at this
stage, the queue depth of BT is of no concern. */
-#define BT_NORMAL_TIMEOUT 2000000 /* seconds in microseconds */
+#define BT_NORMAL_TIMEOUT 5000000 /* seconds in microseconds */
#define BT_RETRY_LIMIT 2
#define BT_RESET_DELAY 6000000 /* 6 seconds after warm reset */
@@ -202,7 +206,7 @@ static int bt_get_result(struct si_sm_data *bt,
msg_len = bt->read_count - 2; /* account for length & seq */
/* Always NetFn, Cmd, cCode */
if (msg_len < 3 || msg_len > IPMI_MAX_MSG_LENGTH) {
- printk(KERN_WARNING "BT results: bad msg_len = %d\n", msg_len);
+ printk(KERN_DEBUG "BT results: bad msg_len = %d\n", msg_len);
data[0] = bt->write_data[1] | 0x4; /* Kludge a response */
data[1] = bt->write_data[3];
data[2] = IPMI_ERR_UNSPECIFIED;
@@ -240,7 +244,7 @@ static void reset_flags(struct si_sm_data *bt)
BT_CONTROL(BT_B_BUSY);
BT_CONTROL(BT_CLR_WR_PTR);
BT_CONTROL(BT_SMS_ATN);
-#ifdef DEVELOPMENT_ONLY_NOT_FOR_PRODUCTION
+
if (BT_STATUS & BT_B2H_ATN) {
int i;
BT_CONTROL(BT_H_BUSY);
@@ -250,7 +254,6 @@ static void reset_flags(struct si_sm_data *bt)
BMC2HOST;
BT_CONTROL(BT_H_BUSY);
}
-#endif
}
static inline void write_all_bytes(struct si_sm_data *bt)
@@ -295,7 +298,7 @@ static inline int read_all_bytes(struct si_sm_data *bt)
printk ("\n");
}
if (bt->seq != bt->write_data[2]) /* idiot check */
- printk(KERN_WARNING "BT: internal error: sequence mismatch\n");
+ printk(KERN_DEBUG "BT: internal error: sequence mismatch\n");
/* per the spec, the (NetFn, Seq, Cmd) tuples should match */
if ((bt->read_data[3] == bt->write_data[3]) && /* Cmd */
@@ -321,18 +324,17 @@ static void error_recovery(struct si_sm_data *bt, char *reason)
bt->timeout = BT_NORMAL_TIMEOUT; /* various places want to retry */
status = BT_STATUS;
- printk(KERN_WARNING "BT: %s in %s %s ", reason, STATE2TXT,
+ printk(KERN_DEBUG "BT: %s in %s %s\n", reason, STATE2TXT,
STATUS2TXT(buf));
(bt->error_retries)++;
if (bt->error_retries > BT_RETRY_LIMIT) {
- printk("retry limit (%d) exceeded\n", BT_RETRY_LIMIT);
+ printk(KERN_DEBUG "retry limit (%d) exceeded\n", BT_RETRY_LIMIT);
bt->state = BT_STATE_HOSED;
if (!bt->nonzero_status)
printk(KERN_ERR "IPMI: BT stuck, try power cycle\n");
- else if (bt->seq == FIRST_SEQ + BT_RETRY_LIMIT) {
- /* most likely during insmod */
- printk(KERN_WARNING "IPMI: BT reset (takes 5 secs)\n");
+ else if (bt->error_retries <= BT_RETRY_LIMIT + 1) {
+ printk(KERN_DEBUG "IPMI: BT reset (takes 5 secs)\n");
bt->state = BT_STATE_RESET1;
}
return;
@@ -340,11 +342,11 @@ static void error_recovery(struct si_sm_data *bt, char *reason)
/* Sometimes the BMC queues get in an "off-by-one" state...*/
if ((bt->state == BT_STATE_B2H_WAIT) && (status & BT_B2H_ATN)) {
- printk("retry B2H_WAIT\n");
+ printk(KERN_DEBUG "retry B2H_WAIT\n");
return;
}
- printk("restart command\n");
+ printk(KERN_DEBUG "restart command\n");
bt->state = BT_STATE_RESTART;
}
@@ -372,17 +374,6 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
return SI_SM_HOSED;
if (bt->state != BT_STATE_IDLE) { /* do timeout test */
-
- /* Certain states, on error conditions, can lock up a CPU
- because they are effectively in an infinite loop with
- CALL_WITHOUT_DELAY (right back here with time == 0).
- Prevent infinite lockup by ALWAYS decrementing timeout. */
-
- /* FIXME: bt_event is sometimes called with time > BT_NORMAL_TIMEOUT
- (noticed in ipmi_smic_sm.c January 2004) */
-
- if ((time <= 0) || (time >= BT_NORMAL_TIMEOUT))
- time = 100;
bt->timeout -= time;
if ((bt->timeout < 0) && (bt->state < BT_STATE_RESET1)) {
error_recovery(bt, "timed out");
@@ -483,6 +474,7 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time)
break;
case BT_STATE_RESTART: /* don't reset retries! */
+ reset_flags(bt);
bt->write_data[2] = ++bt->seq;
bt->read_count = 0;
bt->nonzero_status = 0;
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index d21853a594a3..da1554194d3d 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -38,16 +38,25 @@
*/
#include <linux/kernel.h> /* For printk. */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/string.h>
+#include <linux/jiffies.h>
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
-/* Set this if you want a printout of why the state machine was hosed
- when it gets hosed. */
-#define DEBUG_HOSED_REASON
+/* kcs_debug is a bit-field
+ * KCS_DEBUG_ENABLE - turned on for now
+ * KCS_DEBUG_MSG - commands and their responses
+ * KCS_DEBUG_STATES - state machine
+ */
+#define KCS_DEBUG_STATES 4
+#define KCS_DEBUG_MSG 2
+#define KCS_DEBUG_ENABLE 1
-/* Print the state machine state on entry every time. */
-#undef DEBUG_STATE
+static int kcs_debug;
+module_param(kcs_debug, int, 0644);
+MODULE_PARM_DESC(kcs_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
/* The states the KCS driver may be in. */
enum kcs_states {
@@ -91,6 +100,7 @@ enum kcs_states {
#define IBF_RETRY_TIMEOUT 1000000
#define OBF_RETRY_TIMEOUT 1000000
#define MAX_ERROR_RETRIES 10
+#define ERROR0_OBF_WAIT_JIFFIES (2*HZ)
struct si_sm_data
{
@@ -107,6 +117,7 @@ struct si_sm_data
unsigned int error_retries;
long ibf_timeout;
long obf_timeout;
+ unsigned long error0_timeout;
};
static unsigned int init_kcs_data(struct si_sm_data *kcs,
@@ -175,11 +186,11 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
{
(kcs->error_retries)++;
if (kcs->error_retries > MAX_ERROR_RETRIES) {
-#ifdef DEBUG_HOSED_REASON
- printk("ipmi_kcs_sm: kcs hosed: %s\n", reason);
-#endif
+ if (kcs_debug & KCS_DEBUG_ENABLE)
+ printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n", reason);
kcs->state = KCS_HOSED;
} else {
+ kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES;
kcs->state = KCS_ERROR0;
}
}
@@ -248,14 +259,21 @@ static void restart_kcs_transaction(struct si_sm_data *kcs)
static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
unsigned int size)
{
+ unsigned int i;
+
if ((size < 2) || (size > MAX_KCS_WRITE_SIZE)) {
return -1;
}
-
if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
return -2;
}
-
+ if (kcs_debug & KCS_DEBUG_MSG) {
+ printk(KERN_DEBUG "start_kcs_transaction -");
+ for (i = 0; i < size; i ++) {
+ printk(" %02x", (unsigned char) (data [i]));
+ }
+ printk ("\n");
+ }
kcs->error_retries = 0;
memcpy(kcs->write_data, data, size);
kcs->write_count = size;
@@ -305,9 +323,9 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
status = read_status(kcs);
-#ifdef DEBUG_STATE
- printk(" State = %d, %x\n", kcs->state, status);
-#endif
+ if (kcs_debug & KCS_DEBUG_STATES)
+ printk(KERN_DEBUG "KCS: State = %d, %x\n", kcs->state, status);
+
/* All states wait for ibf, so just do it here. */
if (!check_ibf(kcs, status, time))
return SI_SM_CALL_WITH_DELAY;
@@ -409,6 +427,10 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
case KCS_ERROR0:
clear_obf(kcs, status);
+ status = read_status(kcs);
+ if (GET_STATUS_OBF(status)) /* controller isn't responding */
+ if (time_before(jiffies, kcs->error0_timeout))
+ return SI_SM_CALL_WITH_TICK_DELAY;
write_cmd(kcs, KCS_GET_STATUS_ABORT);
kcs->state = KCS_ERROR1;
break;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 32fa82c78c73..c1d06ba449b6 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -38,13 +38,13 @@
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
-#include <linux/rwsem.h>
#include <linux/slab.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#include <linux/notifier.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/rcupdate.h>
#define PFX "IPMI message handler: "
@@ -65,10 +65,19 @@ struct proc_dir_entry *proc_ipmi_root = NULL;
the max message timer. This is in milliseconds. */
#define MAX_MSG_TIMEOUT 60000
+
+/*
+ * The main "user" data structure.
+ */
struct ipmi_user
{
struct list_head link;
+ /* Set to "0" when the user is destroyed. */
+ int valid;
+
+ struct kref refcount;
+
/* The upper layer that handles receive messages. */
struct ipmi_user_hndl *handler;
void *handler_data;
@@ -87,6 +96,15 @@ struct cmd_rcvr
ipmi_user_t user;
unsigned char netfn;
unsigned char cmd;
+
+ /*
+ * This is used to form a linked lised during mass deletion.
+ * Since this is in an RCU list, we cannot use the link above
+ * or change any data until the RCU period completes. So we
+ * use this next variable during mass deletion so we can have
+ * a list and don't have to wait and restart the search on
+ * every individual deletion of a command. */
+ struct cmd_rcvr *next;
};
struct seq_table
@@ -150,13 +168,11 @@ struct ipmi_smi
/* What interface number are we? */
int intf_num;
- /* The list of upper layers that are using me. We read-lock
- this when delivering messages to the upper layer to keep
- the user from going away while we are processing the
- message. This means that you cannot add or delete a user
- from the receive callback. */
- rwlock_t users_lock;
- struct list_head users;
+ struct kref refcount;
+
+ /* The list of upper layers that are using me. seq_lock
+ * protects this. */
+ struct list_head users;
/* Used for wake ups at startup. */
wait_queue_head_t waitq;
@@ -193,7 +209,7 @@ struct ipmi_smi
/* The list of command receivers that are registered for commands
on this interface. */
- rwlock_t cmd_rcvr_lock;
+ struct semaphore cmd_rcvrs_lock;
struct list_head cmd_rcvrs;
/* Events that were queues because no one was there to receive
@@ -296,16 +312,17 @@ struct ipmi_smi
unsigned int events;
};
+/* Used to mark an interface entry that cannot be used but is not a
+ * free entry, either, primarily used at creation and deletion time so
+ * a slot doesn't get reused too quickly. */
+#define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1))
+#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \
+ || (i == IPMI_INVALID_INTERFACE_ENTRY))
+
#define MAX_IPMI_INTERFACES 4
static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES];
-/* Used to keep interfaces from going away while operations are
- operating on interfaces. Grab read if you are not modifying the
- interfaces, write if you are. */
-static DECLARE_RWSEM(interfaces_sem);
-
-/* Directly protects the ipmi_interfaces data structure. This is
- claimed in the timer interrupt. */
+/* Directly protects the ipmi_interfaces data structure. */
static DEFINE_SPINLOCK(interfaces_lock);
/* List of watchers that want to know when smi's are added and
@@ -313,20 +330,72 @@ static DEFINE_SPINLOCK(interfaces_lock);
static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers);
static DECLARE_RWSEM(smi_watchers_sem);
+
+static void free_recv_msg_list(struct list_head *q)
+{
+ struct ipmi_recv_msg *msg, *msg2;
+
+ list_for_each_entry_safe(msg, msg2, q, link) {
+ list_del(&msg->link);
+ ipmi_free_recv_msg(msg);
+ }
+}
+
+static void clean_up_interface_data(ipmi_smi_t intf)
+{
+ int i;
+ struct cmd_rcvr *rcvr, *rcvr2;
+ struct list_head list;
+
+ free_recv_msg_list(&intf->waiting_msgs);
+ free_recv_msg_list(&intf->waiting_events);
+
+ /* Wholesale remove all the entries from the list in the
+ * interface and wait for RCU to know that none are in use. */
+ down(&intf->cmd_rcvrs_lock);
+ list_add_rcu(&list, &intf->cmd_rcvrs);
+ list_del_rcu(&intf->cmd_rcvrs);
+ up(&intf->cmd_rcvrs_lock);
+ synchronize_rcu();
+
+ list_for_each_entry_safe(rcvr, rcvr2, &list, link)
+ kfree(rcvr);
+
+ for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
+ if ((intf->seq_table[i].inuse)
+ && (intf->seq_table[i].recv_msg))
+ {
+ ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
+ }
+ }
+}
+
+static void intf_free(struct kref *ref)
+{
+ ipmi_smi_t intf = container_of(ref, struct ipmi_smi, refcount);
+
+ clean_up_interface_data(intf);
+ kfree(intf);
+}
+
int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
{
- int i;
+ int i;
+ unsigned long flags;
- down_read(&interfaces_sem);
down_write(&smi_watchers_sem);
list_add(&(watcher->link), &smi_watchers);
+ up_write(&smi_watchers_sem);
+ spin_lock_irqsave(&interfaces_lock, flags);
for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
- if (ipmi_interfaces[i] != NULL) {
- watcher->new_smi(i);
- }
+ ipmi_smi_t intf = ipmi_interfaces[i];
+ if (IPMI_INVALID_INTERFACE(intf))
+ continue;
+ spin_unlock_irqrestore(&interfaces_lock, flags);
+ watcher->new_smi(i);
+ spin_lock_irqsave(&interfaces_lock, flags);
}
- up_write(&smi_watchers_sem);
- up_read(&interfaces_sem);
+ spin_unlock_irqrestore(&interfaces_lock, flags);
return 0;
}
@@ -471,8 +540,8 @@ static void deliver_response(struct ipmi_recv_msg *msg)
}
ipmi_free_recv_msg(msg);
} else {
- msg->user->handler->ipmi_recv_hndl(msg,
- msg->user->handler_data);
+ ipmi_user_t user = msg->user;
+ user->handler->ipmi_recv_hndl(msg, user->handler_data);
}
}
@@ -662,15 +731,18 @@ int ipmi_create_user(unsigned int if_num,
if (! new_user)
return -ENOMEM;
- down_read(&interfaces_sem);
- if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
- {
- rv = -EINVAL;
- goto out_unlock;
+ spin_lock_irqsave(&interfaces_lock, flags);
+ intf = ipmi_interfaces[if_num];
+ if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) {
+ spin_unlock_irqrestore(&interfaces_lock, flags);
+ return -EINVAL;
}
- intf = ipmi_interfaces[if_num];
+ /* Note that each existing user holds a refcount to the interface. */
+ kref_get(&intf->refcount);
+ spin_unlock_irqrestore(&interfaces_lock, flags);
+ kref_init(&new_user->refcount);
new_user->handler = handler;
new_user->handler_data = handler_data;
new_user->intf = intf;
@@ -678,98 +750,92 @@ int ipmi_create_user(unsigned int if_num,
if (!try_module_get(intf->handlers->owner)) {
rv = -ENODEV;
- goto out_unlock;
+ goto out_err;
}
if (intf->handlers->inc_usecount) {
rv = intf->handlers->inc_usecount(intf->send_info);
if (rv) {
module_put(intf->handlers->owner);
- goto out_unlock;
+ goto out_err;
}
}
- write_lock_irqsave(&intf->users_lock, flags);
- list_add_tail(&new_user->link, &intf->users);
- write_unlock_irqrestore(&intf->users_lock, flags);
-
- out_unlock:
- if (rv) {
- kfree(new_user);
- } else {
- *user = new_user;
- }
+ new_user->valid = 1;
+ spin_lock_irqsave(&intf->seq_lock, flags);
+ list_add_rcu(&new_user->link, &intf->users);
+ spin_unlock_irqrestore(&intf->seq_lock, flags);
+ *user = new_user;
+ return 0;
- up_read(&interfaces_sem);
+ out_err:
+ kfree(new_user);
+ kref_put(&intf->refcount, intf_free);
return rv;
}
-static int ipmi_destroy_user_nolock(ipmi_user_t user)
+static void free_user(struct kref *ref)
+{
+ ipmi_user_t user = container_of(ref, struct ipmi_user, refcount);
+ kfree(user);
+}
+
+int ipmi_destroy_user(ipmi_user_t user)
{
int rv = -ENODEV;
- ipmi_user_t t_user;
- struct cmd_rcvr *rcvr, *rcvr2;
+ ipmi_smi_t intf = user->intf;
int i;
unsigned long flags;
+ struct cmd_rcvr *rcvr;
+ struct list_head *entry1, *entry2;
+ struct cmd_rcvr *rcvrs = NULL;
- /* Find the user and delete them from the list. */
- list_for_each_entry(t_user, &(user->intf->users), link) {
- if (t_user == user) {
- list_del(&t_user->link);
- rv = 0;
- break;
- }
- }
+ user->valid = 1;
- if (rv) {
- goto out_unlock;
- }
+ /* Remove the user from the interface's sequence table. */
+ spin_lock_irqsave(&intf->seq_lock, flags);
+ list_del_rcu(&user->link);
- /* Remove the user from the interfaces sequence table. */
- spin_lock_irqsave(&(user->intf->seq_lock), flags);
for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
- if (user->intf->seq_table[i].inuse
- && (user->intf->seq_table[i].recv_msg->user == user))
+ if (intf->seq_table[i].inuse
+ && (intf->seq_table[i].recv_msg->user == user))
{
- user->intf->seq_table[i].inuse = 0;
+ intf->seq_table[i].inuse = 0;
}
}
- spin_unlock_irqrestore(&(user->intf->seq_lock), flags);
-
- /* Remove the user from the command receiver's table. */
- write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
- list_for_each_entry_safe(rcvr, rcvr2, &(user->intf->cmd_rcvrs), link) {
+ spin_unlock_irqrestore(&intf->seq_lock, flags);
+
+ /*
+ * Remove the user from the command receiver's table. First
+ * we build a list of everything (not using the standard link,
+ * since other things may be using it till we do
+ * synchronize_rcu()) then free everything in that list.
+ */
+ down(&intf->cmd_rcvrs_lock);
+ list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) {
+ rcvr = list_entry(entry1, struct cmd_rcvr, link);
if (rcvr->user == user) {
- list_del(&rcvr->link);
- kfree(rcvr);
+ list_del_rcu(&rcvr->link);
+ rcvr->next = rcvrs;
+ rcvrs = rcvr;
}
}
- write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
+ up(&intf->cmd_rcvrs_lock);
+ synchronize_rcu();
+ while (rcvrs) {
+ rcvr = rcvrs;
+ rcvrs = rcvr->next;
+ kfree(rcvr);
+ }
- kfree(user);
+ module_put(intf->handlers->owner);
+ if (intf->handlers->dec_usecount)
+ intf->handlers->dec_usecount(intf->send_info);
- out_unlock:
+ kref_put(&intf->refcount, intf_free);
- return rv;
-}
-
-int ipmi_destroy_user(ipmi_user_t user)
-{
- int rv;
- ipmi_smi_t intf = user->intf;
- unsigned long flags;
+ kref_put(&user->refcount, free_user);
- down_read(&interfaces_sem);
- write_lock_irqsave(&intf->users_lock, flags);
- rv = ipmi_destroy_user_nolock(user);
- if (!rv) {
- module_put(intf->handlers->owner);
- if (intf->handlers->dec_usecount)
- intf->handlers->dec_usecount(intf->send_info);
- }
-
- write_unlock_irqrestore(&intf->users_lock, flags);
- up_read(&interfaces_sem);
return rv;
}
@@ -823,62 +889,78 @@ int ipmi_get_my_LUN(ipmi_user_t user,
int ipmi_set_gets_events(ipmi_user_t user, int val)
{
- unsigned long flags;
- struct ipmi_recv_msg *msg, *msg2;
+ unsigned long flags;
+ ipmi_smi_t intf = user->intf;
+ struct ipmi_recv_msg *msg, *msg2;
+ struct list_head msgs;
- read_lock(&(user->intf->users_lock));
- spin_lock_irqsave(&(user->intf->events_lock), flags);
+ INIT_LIST_HEAD(&msgs);
+
+ spin_lock_irqsave(&intf->events_lock, flags);
user->gets_events = val;
if (val) {
/* Deliver any queued events. */
- list_for_each_entry_safe(msg, msg2, &(user->intf->waiting_events), link) {
+ list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) {
list_del(&msg->link);
- msg->user = user;
- deliver_response(msg);
+ list_add_tail(&msg->link, &msgs);
}
}
-
- spin_unlock_irqrestore(&(user->intf->events_lock), flags);
- read_unlock(&(user->intf->users_lock));
+
+ /* Hold the events lock while doing this to preserve order. */
+ list_for_each_entry_safe(msg, msg2, &msgs, link) {
+ msg->user = user;
+ kref_get(&user->refcount);
+ deliver_response(msg);
+ }
+
+ spin_unlock_irqrestore(&intf->events_lock, flags);
return 0;
}
+static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf,
+ unsigned char netfn,
+ unsigned char cmd)
+{
+ struct cmd_rcvr *rcvr;
+
+ list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
+ if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd))
+ return rcvr;
+ }
+ return NULL;
+}
+
int ipmi_register_for_cmd(ipmi_user_t user,
unsigned char netfn,
unsigned char cmd)
{
- struct cmd_rcvr *cmp;
- unsigned long flags;
- struct cmd_rcvr *rcvr;
- int rv = 0;
+ ipmi_smi_t intf = user->intf;
+ struct cmd_rcvr *rcvr;
+ struct cmd_rcvr *entry;
+ int rv = 0;
rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL);
if (! rcvr)
return -ENOMEM;
+ rcvr->cmd = cmd;
+ rcvr->netfn = netfn;
+ rcvr->user = user;
- read_lock(&(user->intf->users_lock));
- write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
+ down(&intf->cmd_rcvrs_lock);
/* Make sure the command/netfn is not already registered. */
- list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) {
- if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) {
- rv = -EBUSY;
- break;
- }
- }
-
- if (! rv) {
- rcvr->cmd = cmd;
- rcvr->netfn = netfn;
- rcvr->user = user;
- list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs));
+ entry = find_cmd_rcvr(intf, netfn, cmd);
+ if (entry) {
+ rv = -EBUSY;
+ goto out_unlock;
}
- write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
- read_unlock(&(user->intf->users_lock));
+ list_add_rcu(&rcvr->link, &intf->cmd_rcvrs);
+ out_unlock:
+ up(&intf->cmd_rcvrs_lock);
if (rv)
kfree(rcvr);
@@ -889,31 +971,28 @@ int ipmi_unregister_for_cmd(ipmi_user_t user,
unsigned char netfn,
unsigned char cmd)
{
- unsigned long flags;
- struct cmd_rcvr *rcvr;
- int rv = -ENOENT;
+ ipmi_smi_t intf = user->intf;
+ struct cmd_rcvr *rcvr;
- read_lock(&(user->intf->users_lock));
- write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags);
+ down(&intf->cmd_rcvrs_lock);
/* Make sure the command/netfn is not already registered. */
- list_for_each_entry(rcvr, &(user->intf->cmd_rcvrs), link) {
- if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
- rv = 0;
- list_del(&rcvr->link);
- kfree(rcvr);
- break;
- }
+ rcvr = find_cmd_rcvr(intf, netfn, cmd);
+ if ((rcvr) && (rcvr->user == user)) {
+ list_del_rcu(&rcvr->link);
+ up(&intf->cmd_rcvrs_lock);
+ synchronize_rcu();
+ kfree(rcvr);
+ return 0;
+ } else {
+ up(&intf->cmd_rcvrs_lock);
+ return -ENOENT;
}
- write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags);
- read_unlock(&(user->intf->users_lock));
-
- return rv;
}
void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
{
- user->intf->handlers->set_run_to_completion(user->intf->send_info,
- val);
+ ipmi_smi_t intf = user->intf;
+ intf->handlers->set_run_to_completion(intf->send_info, val);
}
static unsigned char
@@ -1010,19 +1089,19 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg,
supplied in certain circumstances (mainly at panic time). If
messages are supplied, they will be freed, even if an error
occurs. */
-static inline int i_ipmi_request(ipmi_user_t user,
- ipmi_smi_t intf,
- struct ipmi_addr *addr,
- long msgid,
- struct kernel_ipmi_msg *msg,
- void *user_msg_data,
- void *supplied_smi,
- struct ipmi_recv_msg *supplied_recv,
- int priority,
- unsigned char source_address,
- unsigned char source_lun,
- int retries,
- unsigned int retry_time_ms)
+static int i_ipmi_request(ipmi_user_t user,
+ ipmi_smi_t intf,
+ struct ipmi_addr *addr,
+ long msgid,
+ struct kernel_ipmi_msg *msg,
+ void *user_msg_data,
+ void *supplied_smi,
+ struct ipmi_recv_msg *supplied_recv,
+ int priority,
+ unsigned char source_address,
+ unsigned char source_lun,
+ int retries,
+ unsigned int retry_time_ms)
{
int rv = 0;
struct ipmi_smi_msg *smi_msg;
@@ -1051,6 +1130,8 @@ static inline int i_ipmi_request(ipmi_user_t user,
}
recv_msg->user = user;
+ if (user)
+ kref_get(&user->refcount);
recv_msg->msgid = msgid;
/* Store the message to send in the receive message so timeout
responses can get the proper response data. */
@@ -1725,11 +1806,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
unsigned char version_major,
unsigned char version_minor,
unsigned char slave_addr,
- ipmi_smi_t *intf)
+ ipmi_smi_t *new_intf)
{
int i, j;
int rv;
- ipmi_smi_t new_intf;
+ ipmi_smi_t intf;
unsigned long flags;
@@ -1745,189 +1826,142 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
return -ENODEV;
}
- new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL);
- if (!new_intf)
+ intf = kmalloc(sizeof(*intf), GFP_KERNEL);
+ if (!intf)
return -ENOMEM;
- memset(new_intf, 0, sizeof(*new_intf));
-
- new_intf->proc_dir = NULL;
+ memset(intf, 0, sizeof(*intf));
+ intf->intf_num = -1;
+ kref_init(&intf->refcount);
+ intf->version_major = version_major;
+ intf->version_minor = version_minor;
+ for (j = 0; j < IPMI_MAX_CHANNELS; j++) {
+ intf->channels[j].address = IPMI_BMC_SLAVE_ADDR;
+ intf->channels[j].lun = 2;
+ }
+ if (slave_addr != 0)
+ intf->channels[0].address = slave_addr;
+ INIT_LIST_HEAD(&intf->users);
+ intf->handlers = handlers;
+ intf->send_info = send_info;
+ spin_lock_init(&intf->seq_lock);
+ for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
+ intf->seq_table[j].inuse = 0;
+ intf->seq_table[j].seqid = 0;
+ }
+ intf->curr_seq = 0;
+#ifdef CONFIG_PROC_FS
+ spin_lock_init(&intf->proc_entry_lock);
+#endif
+ spin_lock_init(&intf->waiting_msgs_lock);
+ INIT_LIST_HEAD(&intf->waiting_msgs);
+ spin_lock_init(&intf->events_lock);
+ INIT_LIST_HEAD(&intf->waiting_events);
+ intf->waiting_events_count = 0;
+ init_MUTEX(&intf->cmd_rcvrs_lock);
+ INIT_LIST_HEAD(&intf->cmd_rcvrs);
+ init_waitqueue_head(&intf->waitq);
+
+ spin_lock_init(&intf->counter_lock);
+ intf->proc_dir = NULL;
rv = -ENOMEM;
-
- down_write(&interfaces_sem);
+ spin_lock_irqsave(&interfaces_lock, flags);
for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
if (ipmi_interfaces[i] == NULL) {
- new_intf->intf_num = i;
- new_intf->version_major = version_major;
- new_intf->version_minor = version_minor;
- for (j = 0; j < IPMI_MAX_CHANNELS; j++) {
- new_intf->channels[j].address
- = IPMI_BMC_SLAVE_ADDR;
- new_intf->channels[j].lun = 2;
- }
- if (slave_addr != 0)
- new_intf->channels[0].address = slave_addr;
- rwlock_init(&(new_intf->users_lock));
- INIT_LIST_HEAD(&(new_intf->users));
- new_intf->handlers = handlers;
- new_intf->send_info = send_info;
- spin_lock_init(&(new_intf->seq_lock));
- for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
- new_intf->seq_table[j].inuse = 0;
- new_intf->seq_table[j].seqid = 0;
- }
- new_intf->curr_seq = 0;
-#ifdef CONFIG_PROC_FS
- spin_lock_init(&(new_intf->proc_entry_lock));
-#endif
- spin_lock_init(&(new_intf->waiting_msgs_lock));
- INIT_LIST_HEAD(&(new_intf->waiting_msgs));
- spin_lock_init(&(new_intf->events_lock));
- INIT_LIST_HEAD(&(new_intf->waiting_events));
- new_intf->waiting_events_count = 0;
- rwlock_init(&(new_intf->cmd_rcvr_lock));
- init_waitqueue_head(&new_intf->waitq);
- INIT_LIST_HEAD(&(new_intf->cmd_rcvrs));
-
- spin_lock_init(&(new_intf->counter_lock));
-
- spin_lock_irqsave(&interfaces_lock, flags);
- ipmi_interfaces[i] = new_intf;
- spin_unlock_irqrestore(&interfaces_lock, flags);
-
+ intf->intf_num = i;
+ /* Reserve the entry till we are done. */
+ ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY;
rv = 0;
- *intf = new_intf;
break;
}
}
+ spin_unlock_irqrestore(&interfaces_lock, flags);
+ if (rv)
+ goto out;
- downgrade_write(&interfaces_sem);
-
- if (rv == 0)
- rv = add_proc_entries(*intf, i);
-
- if (rv == 0) {
- if ((version_major > 1)
- || ((version_major == 1) && (version_minor >= 5)))
- {
- /* Start scanning the channels to see what is
- available. */
- (*intf)->null_user_handler = channel_handler;
- (*intf)->curr_channel = 0;
- rv = send_channel_info_cmd(*intf, 0);
- if (rv)
- goto out;
+ /* FIXME - this is an ugly kludge, this sets the intf for the
+ caller before sending any messages with it. */
+ *new_intf = intf;
- /* Wait for the channel info to be read. */
- up_read(&interfaces_sem);
- wait_event((*intf)->waitq,
- ((*intf)->curr_channel>=IPMI_MAX_CHANNELS));
- down_read(&interfaces_sem);
+ if ((version_major > 1)
+ || ((version_major == 1) && (version_minor >= 5)))
+ {
+ /* Start scanning the channels to see what is
+ available. */
+ intf->null_user_handler = channel_handler;
+ intf->curr_channel = 0;
+ rv = send_channel_info_cmd(intf, 0);
+ if (rv)
+ goto out;
- if (ipmi_interfaces[i] != new_intf)
- /* Well, it went away. Just return. */
- goto out;
- } else {
- /* Assume a single IPMB channel at zero. */
- (*intf)->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB;
- (*intf)->channels[0].protocol
- = IPMI_CHANNEL_PROTOCOL_IPMB;
- }
-
- /* Call all the watcher interfaces to tell
- them that a new interface is available. */
- call_smi_watchers(i);
+ /* Wait for the channel info to be read. */
+ wait_event(intf->waitq,
+ intf->curr_channel >= IPMI_MAX_CHANNELS);
+ } else {
+ /* Assume a single IPMB channel at zero. */
+ intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB;
+ intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB;
}
- out:
- up_read(&interfaces_sem);
+ if (rv == 0)
+ rv = add_proc_entries(intf, i);
+ out:
if (rv) {
- if (new_intf->proc_dir)
- remove_proc_entries(new_intf);
- kfree(new_intf);
+ if (intf->proc_dir)
+ remove_proc_entries(intf);
+ kref_put(&intf->refcount, intf_free);
+ if (i < MAX_IPMI_INTERFACES) {
+ spin_lock_irqsave(&interfaces_lock, flags);
+ ipmi_interfaces[i] = NULL;
+ spin_unlock_irqrestore(&interfaces_lock, flags);
+ }
+ } else {
+ spin_lock_irqsave(&interfaces_lock, flags);
+ ipmi_interfaces[i] = intf;
+ spin_unlock_irqrestore(&interfaces_lock, flags);
+ call_smi_watchers(i);
}
return rv;
}
-static void free_recv_msg_list(struct list_head *q)
-{
- struct ipmi_recv_msg *msg, *msg2;
-
- list_for_each_entry_safe(msg, msg2, q, link) {
- list_del(&msg->link);
- ipmi_free_recv_msg(msg);
- }
-}
-
-static void free_cmd_rcvr_list(struct list_head *q)
-{
- struct cmd_rcvr *rcvr, *rcvr2;
-
- list_for_each_entry_safe(rcvr, rcvr2, q, link) {
- list_del(&rcvr->link);
- kfree(rcvr);
- }
-}
-
-static void clean_up_interface_data(ipmi_smi_t intf)
-{
- int i;
-
- free_recv_msg_list(&(intf->waiting_msgs));
- free_recv_msg_list(&(intf->waiting_events));
- free_cmd_rcvr_list(&(intf->cmd_rcvrs));
-
- for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) {
- if ((intf->seq_table[i].inuse)
- && (intf->seq_table[i].recv_msg))
- {
- ipmi_free_recv_msg(intf->seq_table[i].recv_msg);
- }
- }
-}
-
int ipmi_unregister_smi(ipmi_smi_t intf)
{
- int rv = -ENODEV;
int i;
struct ipmi_smi_watcher *w;
unsigned long flags;
- down_write(&interfaces_sem);
- if (list_empty(&(intf->users)))
- {
- for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
- if (ipmi_interfaces[i] == intf) {
- remove_proc_entries(intf);
- spin_lock_irqsave(&interfaces_lock, flags);
- ipmi_interfaces[i] = NULL;
- clean_up_interface_data(intf);
- spin_unlock_irqrestore(&interfaces_lock,flags);
- kfree(intf);
- rv = 0;
- goto out_call_watcher;
- }
+ spin_lock_irqsave(&interfaces_lock, flags);
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
+ if (ipmi_interfaces[i] == intf) {
+ /* Set the interface number reserved until we
+ * are done. */
+ ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY;
+ intf->intf_num = -1;
+ break;
}
- } else {
- rv = -EBUSY;
}
- up_write(&interfaces_sem);
+ spin_unlock_irqrestore(&interfaces_lock,flags);
- return rv;
+ if (i == MAX_IPMI_INTERFACES)
+ return -ENODEV;
- out_call_watcher:
- downgrade_write(&interfaces_sem);
+ remove_proc_entries(intf);
/* Call all the watcher interfaces to tell them that
an interface is gone. */
down_read(&smi_watchers_sem);
- list_for_each_entry(w, &smi_watchers, link) {
+ list_for_each_entry(w, &smi_watchers, link)
w->smi_gone(i);
- }
up_read(&smi_watchers_sem);
- up_read(&interfaces_sem);
+
+ /* Allow the entry to be reused now. */
+ spin_lock_irqsave(&interfaces_lock, flags);
+ ipmi_interfaces[i] = NULL;
+ spin_unlock_irqrestore(&interfaces_lock,flags);
+
+ kref_put(&intf->refcount, intf_free);
return 0;
}
@@ -1998,14 +2032,14 @@ static int handle_ipmb_get_msg_rsp(ipmi_smi_t intf,
static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
struct ipmi_smi_msg *msg)
{
- struct cmd_rcvr *rcvr;
- int rv = 0;
- unsigned char netfn;
- unsigned char cmd;
- ipmi_user_t user = NULL;
- struct ipmi_ipmb_addr *ipmb_addr;
- struct ipmi_recv_msg *recv_msg;
- unsigned long flags;
+ struct cmd_rcvr *rcvr;
+ int rv = 0;
+ unsigned char netfn;
+ unsigned char cmd;
+ ipmi_user_t user = NULL;
+ struct ipmi_ipmb_addr *ipmb_addr;
+ struct ipmi_recv_msg *recv_msg;
+ unsigned long flags;
if (msg->rsp_size < 10) {
/* Message not big enough, just ignore it. */
@@ -2023,16 +2057,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
netfn = msg->rsp[4] >> 2;
cmd = msg->rsp[8];
- read_lock(&(intf->cmd_rcvr_lock));
-
- /* Find the command/netfn. */
- list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
- if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
- user = rcvr->user;
- break;
- }
- }
- read_unlock(&(intf->cmd_rcvr_lock));
+ rcu_read_lock();
+ rcvr = find_cmd_rcvr(intf, netfn, cmd);
+ if (rcvr) {
+ user = rcvr->user;
+ kref_get(&user->refcount);
+ } else
+ user = NULL;
+ rcu_read_unlock();
if (user == NULL) {
/* We didn't find a user, deliver an error response. */
@@ -2079,6 +2111,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf,
message, so requeue it for handling
later. */
rv = 1;
+ kref_put(&user->refcount, free_user);
} else {
/* Extract the source address from the data. */
ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
@@ -2179,14 +2212,14 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t intf,
static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
struct ipmi_smi_msg *msg)
{
- struct cmd_rcvr *rcvr;
- int rv = 0;
- unsigned char netfn;
- unsigned char cmd;
- ipmi_user_t user = NULL;
- struct ipmi_lan_addr *lan_addr;
- struct ipmi_recv_msg *recv_msg;
- unsigned long flags;
+ struct cmd_rcvr *rcvr;
+ int rv = 0;
+ unsigned char netfn;
+ unsigned char cmd;
+ ipmi_user_t user = NULL;
+ struct ipmi_lan_addr *lan_addr;
+ struct ipmi_recv_msg *recv_msg;
+ unsigned long flags;
if (msg->rsp_size < 12) {
/* Message not big enough, just ignore it. */
@@ -2204,19 +2237,17 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
netfn = msg->rsp[6] >> 2;
cmd = msg->rsp[10];
- read_lock(&(intf->cmd_rcvr_lock));
-
- /* Find the command/netfn. */
- list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) {
- if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) {
- user = rcvr->user;
- break;
- }
- }
- read_unlock(&(intf->cmd_rcvr_lock));
+ rcu_read_lock();
+ rcvr = find_cmd_rcvr(intf, netfn, cmd);
+ if (rcvr) {
+ user = rcvr->user;
+ kref_get(&user->refcount);
+ } else
+ user = NULL;
+ rcu_read_unlock();
if (user == NULL) {
- /* We didn't find a user, deliver an error response. */
+ /* We didn't find a user, just give up. */
spin_lock_irqsave(&intf->counter_lock, flags);
intf->unhandled_commands++;
spin_unlock_irqrestore(&intf->counter_lock, flags);
@@ -2235,6 +2266,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf,
message, so requeue it for handling
later. */
rv = 1;
+ kref_put(&user->refcount, free_user);
} else {
/* Extract the source address from the data. */
lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr;
@@ -2286,8 +2318,6 @@ static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
recv_msg->msg.data_len = msg->rsp_size - 3;
}
-/* This will be called with the intf->users_lock read-locked, so no need
- to do that here. */
static int handle_read_event_rsp(ipmi_smi_t intf,
struct ipmi_smi_msg *msg)
{
@@ -2313,7 +2343,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
INIT_LIST_HEAD(&msgs);
- spin_lock_irqsave(&(intf->events_lock), flags);
+ spin_lock_irqsave(&intf->events_lock, flags);
spin_lock(&intf->counter_lock);
intf->events++;
@@ -2321,12 +2351,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
/* Allocate and fill in one message for every user that is getting
events. */
- list_for_each_entry(user, &(intf->users), link) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(user, &intf->users, link) {
if (! user->gets_events)
continue;
recv_msg = ipmi_alloc_recv_msg();
if (! recv_msg) {
+ rcu_read_unlock();
list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) {
list_del(&recv_msg->link);
ipmi_free_recv_msg(recv_msg);
@@ -2342,8 +2374,10 @@ static int handle_read_event_rsp(ipmi_smi_t intf,
copy_event_into_recv_msg(recv_msg, msg);
recv_msg->user = user;
+ kref_get(&user->refcount);
list_add_tail(&(recv_msg->link), &msgs);
}
+ rcu_read_unlock();
if (deliver_count) {
/* Now deliver all the messages. */
@@ -2382,9 +2416,8 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
struct ipmi_smi_msg *msg)
{
struct ipmi_recv_msg *recv_msg;
- int found = 0;
- struct ipmi_user *user;
unsigned long flags;
+ struct ipmi_user *user;
recv_msg = (struct ipmi_recv_msg *) msg->user_data;
if (recv_msg == NULL)
@@ -2396,16 +2429,9 @@ static int handle_bmc_rsp(ipmi_smi_t intf,
return 0;
}
+ user = recv_msg->user;
/* Make sure the user still exists. */
- list_for_each_entry(user, &(intf->users), link) {
- if (user == recv_msg->user) {
- /* Found it, so we can deliver it */
- found = 1;
- break;
- }
- }
-
- if ((! found) && recv_msg->user) {
+ if (user && !user->valid) {
/* The user for the message went away, so give up. */
spin_lock_irqsave(&intf->counter_lock, flags);
intf->unhandled_local_responses++;
@@ -2486,7 +2512,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
{
/* It's a response to a response we sent. For this we
deliver a send message response to the user. */
- struct ipmi_recv_msg *recv_msg = msg->user_data;
+ struct ipmi_recv_msg *recv_msg = msg->user_data;
requeue = 0;
if (msg->rsp_size < 2)
@@ -2498,13 +2524,18 @@ static int handle_new_recv_msg(ipmi_smi_t intf,
/* Invalid channel number */
goto out;
- if (recv_msg) {
- recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE;
- recv_msg->msg.data = recv_msg->msg_data;
- recv_msg->msg.data_len = 1;
- recv_msg->msg_data[0] = msg->rsp[2];
- deliver_response(recv_msg);
- }
+ if (!recv_msg)
+ goto out;
+
+ /* Make sure the user still exists. */
+ if (!recv_msg->user || !recv_msg->user->valid)
+ goto out;
+
+ recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE;
+ recv_msg->msg.data = recv_msg->msg_data;
+ recv_msg->msg.data_len = 1;
+ recv_msg->msg_data[0] = msg->rsp[2];
+ deliver_response(recv_msg);
} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
&& (msg->rsp[1] == IPMI_GET_MSG_CMD))
{
@@ -2570,14 +2601,11 @@ void ipmi_smi_msg_received(ipmi_smi_t intf,
int rv;
- /* Lock the user lock so the user can't go away while we are
- working on it. */
- read_lock(&(intf->users_lock));
-
if ((msg->data_size >= 2)
&& (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2))
&& (msg->data[1] == IPMI_SEND_MSG_CMD)
- && (msg->user_data == NULL)) {
+ && (msg->user_data == NULL))
+ {
/* This is the local response to a command send, start
the timer for these. The user_data will not be
NULL if this is a response send, and we will let
@@ -2612,46 +2640,46 @@ void ipmi_smi_msg_received(ipmi_smi_t intf,
}
ipmi_free_smi_msg(msg);
- goto out_unlock;
+ goto out;
}
/* To preserve message order, if the list is not empty, we
tack this message onto the end of the list. */
- spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
- if (!list_empty(&(intf->waiting_msgs))) {
- list_add_tail(&(msg->link), &(intf->waiting_msgs));
- spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
- goto out_unlock;
+ spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+ if (!list_empty(&intf->waiting_msgs)) {
+ list_add_tail(&msg->link, &intf->waiting_msgs);
+ spin_unlock(&intf->waiting_msgs_lock);
+ goto out;
}
- spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
+ spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
rv = handle_new_recv_msg(intf, msg);
if (rv > 0) {
/* Could not handle the message now, just add it to a
list to handle later. */
- spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
- list_add_tail(&(msg->link), &(intf->waiting_msgs));
- spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
+ spin_lock(&intf->waiting_msgs_lock);
+ list_add_tail(&msg->link, &intf->waiting_msgs);
+ spin_unlock(&intf->waiting_msgs_lock);
} else if (rv == 0) {
ipmi_free_smi_msg(msg);
}
- out_unlock:
- read_unlock(&(intf->users_lock));
+ out:
+ return;
}
void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf)
{
ipmi_user_t user;
- read_lock(&(intf->users_lock));
- list_for_each_entry(user, &(intf->users), link) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(user, &intf->users, link) {
if (! user->handler->ipmi_watchdog_pretimeout)
continue;
user->handler->ipmi_watchdog_pretimeout(user->handler_data);
}
- read_unlock(&(intf->users_lock));
+ rcu_read_unlock();
}
static void
@@ -2691,8 +2719,65 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
return smi_msg;
}
-static void
-ipmi_timeout_handler(long timeout_period)
+static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent,
+ struct list_head *timeouts, long timeout_period,
+ int slot, unsigned long *flags)
+{
+ struct ipmi_recv_msg *msg;
+
+ if (!ent->inuse)
+ return;
+
+ ent->timeout -= timeout_period;
+ if (ent->timeout > 0)
+ return;
+
+ if (ent->retries_left == 0) {
+ /* The message has used all its retries. */
+ ent->inuse = 0;
+ msg = ent->recv_msg;
+ list_add_tail(&msg->link, timeouts);
+ spin_lock(&intf->counter_lock);
+ if (ent->broadcast)
+ intf->timed_out_ipmb_broadcasts++;
+ else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE)
+ intf->timed_out_lan_commands++;
+ else
+ intf->timed_out_ipmb_commands++;
+ spin_unlock(&intf->counter_lock);
+ } else {
+ struct ipmi_smi_msg *smi_msg;
+ /* More retries, send again. */
+
+ /* Start with the max timer, set to normal
+ timer after the message is sent. */
+ ent->timeout = MAX_MSG_TIMEOUT;
+ ent->retries_left--;
+ spin_lock(&intf->counter_lock);
+ if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE)
+ intf->retransmitted_lan_commands++;
+ else
+ intf->retransmitted_ipmb_commands++;
+ spin_unlock(&intf->counter_lock);
+
+ smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot,
+ ent->seqid);
+ if (! smi_msg)
+ return;
+
+ spin_unlock_irqrestore(&intf->seq_lock, *flags);
+ /* Send the new message. We send with a zero
+ * priority. It timed out, I doubt time is
+ * that critical now, and high priority
+ * messages are really only for messages to the
+ * local MC, which don't get resent. */
+ intf->handlers->sender(intf->send_info,
+ smi_msg, 0);
+ spin_lock_irqsave(&intf->seq_lock, *flags);
+ }
+}
+
+static void ipmi_timeout_handler(long timeout_period)
{
ipmi_smi_t intf;
struct list_head timeouts;
@@ -2706,14 +2791,14 @@ ipmi_timeout_handler(long timeout_period)
spin_lock(&interfaces_lock);
for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
- if (intf == NULL)
+ if (IPMI_INVALID_INTERFACE(intf))
continue;
-
- read_lock(&(intf->users_lock));
+ kref_get(&intf->refcount);
+ spin_unlock(&interfaces_lock);
/* See if any waiting messages need to be processed. */
- spin_lock_irqsave(&(intf->waiting_msgs_lock), flags);
- list_for_each_entry_safe(smi_msg, smi_msg2, &(intf->waiting_msgs), link) {
+ spin_lock_irqsave(&intf->waiting_msgs_lock, flags);
+ list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) {
if (! handle_new_recv_msg(intf, smi_msg)) {
list_del(&smi_msg->link);
ipmi_free_smi_msg(smi_msg);
@@ -2723,73 +2808,23 @@ ipmi_timeout_handler(long timeout_period)
break;
}
}
- spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags);
+ spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags);
/* Go through the seq table and find any messages that
have timed out, putting them in the timeouts
list. */
- spin_lock_irqsave(&(intf->seq_lock), flags);
- for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) {
- struct seq_table *ent = &(intf->seq_table[j]);
- if (!ent->inuse)
- continue;
-
- ent->timeout -= timeout_period;
- if (ent->timeout > 0)
- continue;
-
- if (ent->retries_left == 0) {
- /* The message has used all its retries. */
- ent->inuse = 0;
- msg = ent->recv_msg;
- list_add_tail(&(msg->link), &timeouts);
- spin_lock(&intf->counter_lock);
- if (ent->broadcast)
- intf->timed_out_ipmb_broadcasts++;
- else if (ent->recv_msg->addr.addr_type
- == IPMI_LAN_ADDR_TYPE)
- intf->timed_out_lan_commands++;
- else
- intf->timed_out_ipmb_commands++;
- spin_unlock(&intf->counter_lock);
- } else {
- struct ipmi_smi_msg *smi_msg;
- /* More retries, send again. */
-
- /* Start with the max timer, set to normal
- timer after the message is sent. */
- ent->timeout = MAX_MSG_TIMEOUT;
- ent->retries_left--;
- spin_lock(&intf->counter_lock);
- if (ent->recv_msg->addr.addr_type
- == IPMI_LAN_ADDR_TYPE)
- intf->retransmitted_lan_commands++;
- else
- intf->retransmitted_ipmb_commands++;
- spin_unlock(&intf->counter_lock);
- smi_msg = smi_from_recv_msg(intf,
- ent->recv_msg, j, ent->seqid);
- if (! smi_msg)
- continue;
-
- spin_unlock_irqrestore(&(intf->seq_lock),flags);
- /* Send the new message. We send with a zero
- * priority. It timed out, I doubt time is
- * that critical now, and high priority
- * messages are really only for messages to the
- * local MC, which don't get resent. */
- intf->handlers->sender(intf->send_info,
- smi_msg, 0);
- spin_lock_irqsave(&(intf->seq_lock), flags);
- }
- }
- spin_unlock_irqrestore(&(intf->seq_lock), flags);
-
- list_for_each_entry_safe(msg, msg2, &timeouts, link) {
+ spin_lock_irqsave(&intf->seq_lock, flags);
+ for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++)
+ check_msg_timeout(intf, &(intf->seq_table[j]),
+ &timeouts, timeout_period, j,
+ &flags);
+ spin_unlock_irqrestore(&intf->seq_lock, flags);
+
+ list_for_each_entry_safe(msg, msg2, &timeouts, link)
handle_msg_timeout(msg);
- }
- read_unlock(&(intf->users_lock));
+ kref_put(&intf->refcount, intf_free);
+ spin_lock(&interfaces_lock);
}
spin_unlock(&interfaces_lock);
}
@@ -2802,7 +2837,7 @@ static void ipmi_request_event(void)
spin_lock(&interfaces_lock);
for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
- if (intf == NULL)
+ if (IPMI_INVALID_INTERFACE(intf))
continue;
intf->handlers->request_events(intf->send_info);
@@ -2884,6 +2919,13 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
return rv;
}
+void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
+{
+ if (msg->user)
+ kref_put(&msg->user->refcount, free_user);
+ msg->done(msg);
+}
+
#ifdef CONFIG_IPMI_PANIC_EVENT
static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
@@ -2964,7 +3006,7 @@ static void send_panic_events(char *str)
/* For every registered interface, send the event. */
for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
- if (intf == NULL)
+ if (IPMI_INVALID_INTERFACE(intf))
continue;
/* Send the event announcing the panic. */
@@ -2995,7 +3037,7 @@ static void send_panic_events(char *str)
int j;
intf = ipmi_interfaces[i];
- if (intf == NULL)
+ if (IPMI_INVALID_INTERFACE(intf))
continue;
/* First job here is to figure out where to send the
@@ -3131,7 +3173,7 @@ static int panic_event(struct notifier_block *this,
/* For every registered interface, set it to run to completion. */
for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
intf = ipmi_interfaces[i];
- if (intf == NULL)
+ if (IPMI_INVALID_INTERFACE(intf))
continue;
intf->handlers->set_run_to_completion(intf->send_info, 1);
@@ -3160,9 +3202,8 @@ static int ipmi_init_msghandler(void)
printk(KERN_INFO "ipmi message handler version "
IPMI_DRIVER_VERSION "\n");
- for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
+ for (i = 0; i < MAX_IPMI_INTERFACES; i++)
ipmi_interfaces[i] = NULL;
- }
#ifdef CONFIG_PROC_FS
proc_ipmi_root = proc_mkdir("ipmi", NULL);
@@ -3258,3 +3299,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN);
EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
EXPORT_SYMBOL(proc_ipmi_root);
EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
+EXPORT_SYMBOL(ipmi_free_recv_msg);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index f66947722e12..e053eade0366 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -56,7 +56,7 @@ static int poweroff_powercycle;
/* parameter definition to allow user to flag power cycle */
module_param(poweroff_powercycle, int, 0644);
-MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
+MODULE_PARM_DESC(poweroff_powercycle, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
/* Stuff from the get device id command. */
static unsigned int mfg_id;
@@ -611,9 +611,7 @@ static int ipmi_poweroff_init (void)
}
#endif
-#ifdef CONFIG_PROC_FS
rv = ipmi_smi_watcher_register(&smi_watcher);
-#endif
if (rv) {
unregister_sysctl_table(ipmi_table_header);
printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index b6e5cbfb09f8..ea89dca3dbb5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -51,6 +51,8 @@
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/ioport.h>
+#include <linux/notifier.h>
+#include <linux/kthread.h>
#include <asm/irq.h>
#ifdef CONFIG_HIGH_RES_TIMERS
#include <linux/hrtime.h>
@@ -125,6 +127,7 @@ struct ipmi_device_id {
struct smi_info
{
+ int intf_num;
ipmi_smi_t intf;
struct si_sm_data *si_sm;
struct si_sm_handlers *handlers;
@@ -192,8 +195,7 @@ struct smi_info
unsigned long last_timeout_jiffies;
/* Used to gracefully stop the timer without race conditions. */
- volatile int stop_operation;
- volatile int timer_stopped;
+ atomic_t stop_operation;
/* The driver will disable interrupts when it gets into a
situation where it cannot handle messages due to lack of
@@ -220,8 +222,16 @@ struct smi_info
unsigned long events;
unsigned long watchdog_pretimeouts;
unsigned long incoming_messages;
+
+ struct task_struct *thread;
};
+static struct notifier_block *xaction_notifier_list;
+static int register_xaction_notifier(struct notifier_block * nb)
+{
+ return notifier_chain_register(&xaction_notifier_list, nb);
+}
+
static void si_restart_short_timer(struct smi_info *smi_info);
static void deliver_recv_msg(struct smi_info *smi_info,
@@ -281,6 +291,11 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
do_gettimeofday(&t);
printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec);
#endif
+ err = notifier_call_chain(&xaction_notifier_list, 0, smi_info);
+ if (err & NOTIFY_STOP_MASK) {
+ rv = SI_SM_CALL_WITHOUT_DELAY;
+ goto out;
+ }
err = smi_info->handlers->start_transaction(
smi_info->si_sm,
smi_info->curr_msg->data,
@@ -291,6 +306,7 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info)
rv = SI_SM_CALL_WITHOUT_DELAY;
}
+ out:
spin_unlock(&(smi_info->msg_lock));
return rv;
@@ -766,6 +782,29 @@ static void set_run_to_completion(void *send_info, int i_run_to_completion)
spin_unlock_irqrestore(&(smi_info->si_lock), flags);
}
+static int ipmi_thread(void *data)
+{
+ struct smi_info *smi_info = data;
+ unsigned long flags;
+ enum si_sm_result smi_result;
+
+ set_user_nice(current, 19);
+ while (!kthread_should_stop()) {
+ spin_lock_irqsave(&(smi_info->si_lock), flags);
+ smi_result=smi_event_handler(smi_info, 0);
+ spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+ if (smi_result == SI_SM_CALL_WITHOUT_DELAY) {
+ /* do nothing */
+ }
+ else if (smi_result == SI_SM_CALL_WITH_DELAY)
+ udelay(1);
+ else
+ schedule_timeout_interruptible(1);
+ }
+ return 0;
+}
+
+
static void poll(void *send_info)
{
struct smi_info *smi_info = send_info;
@@ -819,15 +858,13 @@ static void smi_timeout(unsigned long data)
enum si_sm_result smi_result;
unsigned long flags;
unsigned long jiffies_now;
- unsigned long time_diff;
+ long time_diff;
#ifdef DEBUG_TIMING
struct timeval t;
#endif
- if (smi_info->stop_operation) {
- smi_info->timer_stopped = 1;
+ if (atomic_read(&smi_info->stop_operation))
return;
- }
spin_lock_irqsave(&(smi_info->si_lock), flags);
#ifdef DEBUG_TIMING
@@ -835,7 +872,7 @@ static void smi_timeout(unsigned long data)
printk("**Timer: %d.%9.9d\n", t.tv_sec, t.tv_usec);
#endif
jiffies_now = jiffies;
- time_diff = ((jiffies_now - smi_info->last_timeout_jiffies)
+ time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
* SI_USEC_PER_JIFFY);
smi_result = smi_event_handler(smi_info, time_diff);
@@ -900,7 +937,7 @@ static irqreturn_t si_irq_handler(int irq, void *data, struct pt_regs *regs)
smi_info->interrupts++;
spin_unlock(&smi_info->count_lock);
- if (smi_info->stop_operation)
+ if (atomic_read(&smi_info->stop_operation))
goto out;
#ifdef DEBUG_TIMING
@@ -1419,7 +1456,7 @@ static u32 ipmi_acpi_gpe(void *context)
smi_info->interrupts++;
spin_unlock(&smi_info->count_lock);
- if (smi_info->stop_operation)
+ if (atomic_read(&smi_info->stop_operation))
goto out;
#ifdef DEBUG_TIMING
@@ -1919,7 +1956,8 @@ static int try_get_dev_id(struct smi_info *smi_info)
smi_result = smi_info->handlers->event(smi_info->si_sm, 0);
for (;;)
{
- if (smi_result == SI_SM_CALL_WITH_DELAY) {
+ if (smi_result == SI_SM_CALL_WITH_DELAY ||
+ smi_result == SI_SM_CALL_WITH_TICK_DELAY) {
schedule_timeout_uninterruptible(1);
smi_result = smi_info->handlers->event(
smi_info->si_sm, 100);
@@ -2052,6 +2090,9 @@ static int oem_data_avail_to_receive_msg_avail(struct smi_info *smi_info)
* IPMI Version = 0x51 IPMI 1.5
* Manufacturer ID = A2 02 00 Dell IANA
*
+ * Additionally, PowerEdge systems with IPMI < 1.5 may also assert
+ * OEM0_DATA_AVAIL and needs to be treated as RECEIVE_MSG_AVAIL.
+ *
*/
#define DELL_POWEREDGE_8G_BMC_DEVICE_ID 0x20
#define DELL_POWEREDGE_8G_BMC_DEVICE_REV 0x80
@@ -2061,16 +2102,87 @@ static void setup_dell_poweredge_oem_data_handler(struct smi_info *smi_info)
{
struct ipmi_device_id *id = &smi_info->device_id;
const char mfr[3]=DELL_IANA_MFR_ID;
- if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))
- && (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID)
- && (id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV)
- && (id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION))
- {
- smi_info->oem_data_avail_handler =
- oem_data_avail_to_receive_msg_avail;
+ if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr))) {
+ if (id->device_id == DELL_POWEREDGE_8G_BMC_DEVICE_ID &&
+ id->device_revision == DELL_POWEREDGE_8G_BMC_DEVICE_REV &&
+ id->ipmi_version == DELL_POWEREDGE_8G_BMC_IPMI_VERSION) {
+ smi_info->oem_data_avail_handler =
+ oem_data_avail_to_receive_msg_avail;
+ }
+ else if (ipmi_version_major(id) < 1 ||
+ (ipmi_version_major(id) == 1 &&
+ ipmi_version_minor(id) < 5)) {
+ smi_info->oem_data_avail_handler =
+ oem_data_avail_to_receive_msg_avail;
+ }
}
}
+#define CANNOT_RETURN_REQUESTED_LENGTH 0xCA
+static void return_hosed_msg_badsize(struct smi_info *smi_info)
+{
+ struct ipmi_smi_msg *msg = smi_info->curr_msg;
+
+ /* Make it a reponse */
+ msg->rsp[0] = msg->data[0] | 4;
+ msg->rsp[1] = msg->data[1];
+ msg->rsp[2] = CANNOT_RETURN_REQUESTED_LENGTH;
+ msg->rsp_size = 3;
+ smi_info->curr_msg = NULL;
+ deliver_recv_msg(smi_info, msg);
+}
+
+/*
+ * dell_poweredge_bt_xaction_handler
+ * @info - smi_info.device_id must be populated
+ *
+ * Dell PowerEdge servers with the BT interface (x6xx and 1750) will
+ * not respond to a Get SDR command if the length of the data
+ * requested is exactly 0x3A, which leads to command timeouts and no
+ * data returned. This intercepts such commands, and causes userspace
+ * callers to try again with a different-sized buffer, which succeeds.
+ */
+
+#define STORAGE_NETFN 0x0A
+#define STORAGE_CMD_GET_SDR 0x23
+static int dell_poweredge_bt_xaction_handler(struct notifier_block *self,
+ unsigned long unused,
+ void *in)
+{
+ struct smi_info *smi_info = in;
+ unsigned char *data = smi_info->curr_msg->data;
+ unsigned int size = smi_info->curr_msg->data_size;
+ if (size >= 8 &&
+ (data[0]>>2) == STORAGE_NETFN &&
+ data[1] == STORAGE_CMD_GET_SDR &&
+ data[7] == 0x3A) {
+ return_hosed_msg_badsize(smi_info);
+ return NOTIFY_STOP;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block dell_poweredge_bt_xaction_notifier = {
+ .notifier_call = dell_poweredge_bt_xaction_handler,
+};
+
+/*
+ * setup_dell_poweredge_bt_xaction_handler
+ * @info - smi_info.device_id must be filled in already
+ *
+ * Fills in smi_info.device_id.start_transaction_pre_hook
+ * when we know what function to use there.
+ */
+static void
+setup_dell_poweredge_bt_xaction_handler(struct smi_info *smi_info)
+{
+ struct ipmi_device_id *id = &smi_info->device_id;
+ const char mfr[3]=DELL_IANA_MFR_ID;
+ if (! memcmp(mfr, id->manufacturer_id, sizeof(mfr)) &&
+ smi_info->si_type == SI_BT)
+ register_xaction_notifier(&dell_poweredge_bt_xaction_notifier);
+}
+
/*
* setup_oem_data_handler
* @info - smi_info.device_id must be filled in already
@@ -2084,6 +2196,18 @@ static void setup_oem_data_handler(struct smi_info *smi_info)
setup_dell_poweredge_oem_data_handler(smi_info);
}
+static void setup_xaction_handlers(struct smi_info *smi_info)
+{
+ setup_dell_poweredge_bt_xaction_handler(smi_info);
+}
+
+static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
+{
+ if (smi_info->thread != ERR_PTR(-ENOMEM))
+ kthread_stop(smi_info->thread);
+ del_timer_sync(&smi_info->si_timer);
+}
+
/* Returns 0 if initialized, or negative on an error. */
static int init_one_smi(int intf_num, struct smi_info **smi)
{
@@ -2179,6 +2303,7 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
goto out_err;
setup_oem_data_handler(new_smi);
+ setup_xaction_handlers(new_smi);
/* Try to claim any interrupts. */
new_smi->irq_setup(new_smi);
@@ -2190,8 +2315,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi->run_to_completion = 0;
new_smi->interrupt_disabled = 0;
- new_smi->timer_stopped = 0;
- new_smi->stop_operation = 0;
+ atomic_set(&new_smi->stop_operation, 0);
+ new_smi->intf_num = intf_num;
/* Start clearing the flags before we enable interrupts or the
timer to avoid racing with the timer. */
@@ -2209,7 +2334,11 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
new_smi->si_timer.function = smi_timeout;
new_smi->last_timeout_jiffies = jiffies;
new_smi->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
+
add_timer(&(new_smi->si_timer));
+ if (new_smi->si_type != SI_BT)
+ new_smi->thread = kthread_run(ipmi_thread, new_smi,
+ "kipmi%d", new_smi->intf_num);
rv = ipmi_register_smi(&handlers,
new_smi,
@@ -2251,12 +2380,8 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
return 0;
out_err_stop_timer:
- new_smi->stop_operation = 1;
-
- /* Wait for the timer to stop. This avoids problems with race
- conditions removing the timer here. */
- while (!new_smi->timer_stopped)
- schedule_timeout_uninterruptible(1);
+ atomic_inc(&new_smi->stop_operation);
+ wait_for_timer_and_thread(new_smi);
out_err:
if (new_smi->intf)
@@ -2362,8 +2487,7 @@ static void __exit cleanup_one_si(struct smi_info *to_clean)
spin_lock_irqsave(&(to_clean->si_lock), flags);
spin_lock(&(to_clean->msg_lock));
- to_clean->stop_operation = 1;
-
+ atomic_inc(&to_clean->stop_operation);
to_clean->irq_cleanup(to_clean);
spin_unlock(&(to_clean->msg_lock));
@@ -2374,10 +2498,7 @@ static void __exit cleanup_one_si(struct smi_info *to_clean)
interrupt. */
synchronize_sched();
- /* Wait for the timer to stop. This avoids problems with race
- conditions removing the timer here. */
- while (!to_clean->timer_stopped)
- schedule_timeout_uninterruptible(1);
+ wait_for_timer_and_thread(to_clean);
/* Interrupts and timeouts are stopped, now make sure the
interface is in a clean state. */
diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h
index 62791dd42985..bf3d4962d6a5 100644
--- a/drivers/char/ipmi/ipmi_si_sm.h
+++ b/drivers/char/ipmi/ipmi_si_sm.h
@@ -62,6 +62,7 @@ enum si_sm_result
{
SI_SM_CALL_WITHOUT_DELAY, /* Call the driver again immediately */
SI_SM_CALL_WITH_DELAY, /* Delay some before calling again. */
+ SI_SM_CALL_WITH_TICK_DELAY, /* Delay at least 1 tick before calling again. */
SI_SM_TRANSACTION_COMPLETE, /* A transaction is finished. */
SI_SM_IDLE, /* The SM is in idle state. */
SI_SM_HOSED, /* The hardware violated the state machine. */
diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
index add2aa2732f0..39d7e5ef1a2b 100644
--- a/drivers/char/ipmi/ipmi_smic_sm.c
+++ b/drivers/char/ipmi/ipmi_smic_sm.c
@@ -43,6 +43,8 @@
#include <linux/kernel.h> /* For printk. */
#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/ipmi_msgdefs.h> /* for completion codes */
#include "ipmi_si_sm.h"
@@ -56,6 +58,8 @@
#define SMIC_DEBUG_ENABLE 1
static int smic_debug = 1;
+module_param(smic_debug, int, 0644);
+MODULE_PARM_DESC(smic_debug, "debug bitmask, 1=enable, 2=messages, 4=states");
enum smic_states {
SMIC_IDLE,
@@ -76,11 +80,17 @@ enum smic_states {
#define SMIC_MAX_ERROR_RETRIES 3
/* Timeouts in microseconds. */
-#define SMIC_RETRY_TIMEOUT 100000
+#define SMIC_RETRY_TIMEOUT 2000000
/* SMIC Flags Register Bits */
#define SMIC_RX_DATA_READY 0x80
#define SMIC_TX_DATA_READY 0x40
+/*
+ * SMIC_SMI and SMIC_EVM_DATA_AVAIL are only used by
+ * a few systems, and then only by Systems Management
+ * Interrupts, not by the OS. Always ignore these bits.
+ *
+ */
#define SMIC_SMI 0x10
#define SMIC_EVM_DATA_AVAIL 0x08
#define SMIC_SMS_DATA_AVAIL 0x04
@@ -364,8 +374,7 @@ static enum si_sm_result smic_event (struct si_sm_data *smic, long time)
switch (smic->state) {
case SMIC_IDLE:
/* in IDLE we check for available messages */
- if (flags & (SMIC_SMI |
- SMIC_EVM_DATA_AVAIL | SMIC_SMS_DATA_AVAIL))
+ if (flags & SMIC_SMS_DATA_AVAIL)
{
return SI_SM_ATTN;
}
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 2da64bf7469c..1f3159eb1ede 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -47,6 +47,9 @@
#include <linux/reboot.h>
#include <linux/wait.h>
#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <asm/atomic.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/apic.h>
#endif
@@ -158,27 +161,120 @@ static struct fasync_struct *fasync_q = NULL;
static char pretimeout_since_last_heartbeat = 0;
static char expect_close;
+static DECLARE_RWSEM(register_sem);
+
+/* Parameters to ipmi_set_timeout */
+#define IPMI_SET_TIMEOUT_NO_HB 0
+#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
+#define IPMI_SET_TIMEOUT_FORCE_HB 2
+
+static int ipmi_set_timeout(int do_heartbeat);
+
/* If true, the driver will start running as soon as it is configured
and ready. */
static int start_now = 0;
-module_param(timeout, int, 0);
+static int set_param_int(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ int l;
+ int rv = 0;
+
+ if (!val)
+ return -EINVAL;
+ l = simple_strtoul(val, &endp, 0);
+ if (endp == val)
+ return -EINVAL;
+
+ down_read(&register_sem);
+ *((int *)kp->arg) = l;
+ if (watchdog_user)
+ rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
+ up_read(&register_sem);
+
+ return rv;
+}
+
+static int get_param_int(char *buffer, struct kernel_param *kp)
+{
+ return sprintf(buffer, "%i", *((int *)kp->arg));
+}
+
+typedef int (*action_fn)(const char *intval, char *outval);
+
+static int action_op(const char *inval, char *outval);
+static int preaction_op(const char *inval, char *outval);
+static int preop_op(const char *inval, char *outval);
+static void check_parms(void);
+
+static int set_param_str(const char *val, struct kernel_param *kp)
+{
+ action_fn fn = (action_fn) kp->arg;
+ int rv = 0;
+ const char *end;
+ char valcp[16];
+ int len;
+
+ /* Truncate leading and trailing spaces. */
+ while (isspace(*val))
+ val++;
+ end = val + strlen(val) - 1;
+ while ((end >= val) && isspace(*end))
+ end--;
+ len = end - val + 1;
+ if (len > sizeof(valcp) - 1)
+ return -EINVAL;
+ memcpy(valcp, val, len);
+ valcp[len] = '\0';
+
+ down_read(&register_sem);
+ rv = fn(valcp, NULL);
+ if (rv)
+ goto out_unlock;
+
+ check_parms();
+ if (watchdog_user)
+ rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
+
+ out_unlock:
+ up_read(&register_sem);
+ return rv;
+}
+
+static int get_param_str(char *buffer, struct kernel_param *kp)
+{
+ action_fn fn = (action_fn) kp->arg;
+ int rv;
+
+ rv = fn(NULL, buffer);
+ if (rv)
+ return rv;
+ return strlen(buffer);
+}
+
+module_param_call(timeout, set_param_int, get_param_int, &timeout, 0644);
MODULE_PARM_DESC(timeout, "Timeout value in seconds.");
-module_param(pretimeout, int, 0);
+
+module_param_call(pretimeout, set_param_int, get_param_int, &pretimeout, 0644);
MODULE_PARM_DESC(pretimeout, "Pretimeout value in seconds.");
-module_param_string(action, action, sizeof(action), 0);
+
+module_param_call(action, set_param_str, get_param_str, action_op, 0644);
MODULE_PARM_DESC(action, "Timeout action. One of: "
"reset, none, power_cycle, power_off.");
-module_param_string(preaction, preaction, sizeof(preaction), 0);
+
+module_param_call(preaction, set_param_str, get_param_str, preaction_op, 0644);
MODULE_PARM_DESC(preaction, "Pretimeout action. One of: "
"pre_none, pre_smi, pre_nmi, pre_int.");
-module_param_string(preop, preop, sizeof(preop), 0);
+
+module_param_call(preop, set_param_str, get_param_str, preop_op, 0644);
MODULE_PARM_DESC(preop, "Pretimeout driver operation. One of: "
"preop_none, preop_panic, preop_give_data.");
+
module_param(start_now, int, 0);
MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as"
"soon as the driver is loaded.");
-module_param(nowayout, int, 0);
+
+module_param(nowayout, int, 0644);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
/* Default state of the timer. */
@@ -200,6 +296,8 @@ static int ipmi_start_timer_on_heartbeat = 0;
static unsigned char ipmi_version_major;
static unsigned char ipmi_version_minor;
+/* If a pretimeout occurs, this is used to allow only one panic to happen. */
+static atomic_t preop_panic_excl = ATOMIC_INIT(-1);
static int ipmi_heartbeat(void);
static void panic_halt_ipmi_heartbeat(void);
@@ -294,11 +392,6 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg,
return rv;
}
-/* Parameters to ipmi_set_timeout */
-#define IPMI_SET_TIMEOUT_NO_HB 0
-#define IPMI_SET_TIMEOUT_HB_IF_NECESSARY 1
-#define IPMI_SET_TIMEOUT_FORCE_HB 2
-
static int ipmi_set_timeout(int do_heartbeat)
{
int send_heartbeat_now;
@@ -732,8 +825,6 @@ static struct miscdevice ipmi_wdog_miscdev = {
.fops = &ipmi_wdog_fops
};
-static DECLARE_RWSEM(register_sem);
-
static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
void *handler_data)
{
@@ -749,9 +840,10 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
static void ipmi_wdog_pretimeout_handler(void *handler_data)
{
if (preaction_val != WDOG_PRETIMEOUT_NONE) {
- if (preop_val == WDOG_PREOP_PANIC)
- panic("Watchdog pre-timeout");
- else if (preop_val == WDOG_PREOP_GIVE_DATA) {
+ if (preop_val == WDOG_PREOP_PANIC) {
+ if (atomic_inc_and_test(&preop_panic_excl))
+ panic("Watchdog pre-timeout");
+ } else if (preop_val == WDOG_PREOP_GIVE_DATA) {
spin_lock(&ipmi_read_lock);
data_to_read = 1;
wake_up_interruptible(&read_q);
@@ -825,7 +917,8 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
an error and not work unless we re-enable
the timer. So do so. */
pretimeout_since_last_heartbeat = 1;
- panic(PFX "pre-timeout");
+ if (atomic_inc_and_test(&preop_panic_excl))
+ panic(PFX "pre-timeout");
}
return NOTIFY_DONE;
@@ -839,6 +932,7 @@ static struct nmi_handler ipmi_nmi_handler =
.handler = ipmi_nmi,
.priority = 0, /* Call us last. */
};
+int nmi_handler_registered;
#endif
static int wdog_reboot_handler(struct notifier_block *this,
@@ -921,59 +1015,86 @@ static struct ipmi_smi_watcher smi_watcher =
.smi_gone = ipmi_smi_gone
};
-static int __init ipmi_wdog_init(void)
+static int action_op(const char *inval, char *outval)
{
- int rv;
+ if (outval)
+ strcpy(outval, action);
+
+ if (!inval)
+ return 0;
- if (strcmp(action, "reset") == 0) {
+ if (strcmp(inval, "reset") == 0)
action_val = WDOG_TIMEOUT_RESET;
- } else if (strcmp(action, "none") == 0) {
+ else if (strcmp(inval, "none") == 0)
action_val = WDOG_TIMEOUT_NONE;
- } else if (strcmp(action, "power_cycle") == 0) {
+ else if (strcmp(inval, "power_cycle") == 0)
action_val = WDOG_TIMEOUT_POWER_CYCLE;
- } else if (strcmp(action, "power_off") == 0) {
+ else if (strcmp(inval, "power_off") == 0)
action_val = WDOG_TIMEOUT_POWER_DOWN;
- } else {
- action_val = WDOG_TIMEOUT_RESET;
- printk(KERN_INFO PFX "Unknown action '%s', defaulting to"
- " reset\n", action);
- }
+ else
+ return -EINVAL;
+ strcpy(action, inval);
+ return 0;
+}
+
+static int preaction_op(const char *inval, char *outval)
+{
+ if (outval)
+ strcpy(outval, preaction);
- if (strcmp(preaction, "pre_none") == 0) {
+ if (!inval)
+ return 0;
+
+ if (strcmp(inval, "pre_none") == 0)
preaction_val = WDOG_PRETIMEOUT_NONE;
- } else if (strcmp(preaction, "pre_smi") == 0) {
+ else if (strcmp(inval, "pre_smi") == 0)
preaction_val = WDOG_PRETIMEOUT_SMI;
#ifdef HAVE_NMI_HANDLER
- } else if (strcmp(preaction, "pre_nmi") == 0) {
+ else if (strcmp(inval, "pre_nmi") == 0)
preaction_val = WDOG_PRETIMEOUT_NMI;
#endif
- } else if (strcmp(preaction, "pre_int") == 0) {
+ else if (strcmp(inval, "pre_int") == 0)
preaction_val = WDOG_PRETIMEOUT_MSG_INT;
- } else {
- preaction_val = WDOG_PRETIMEOUT_NONE;
- printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to"
- " none\n", preaction);
- }
+ else
+ return -EINVAL;
+ strcpy(preaction, inval);
+ return 0;
+}
+
+static int preop_op(const char *inval, char *outval)
+{
+ if (outval)
+ strcpy(outval, preop);
- if (strcmp(preop, "preop_none") == 0) {
+ if (!inval)
+ return 0;
+
+ if (strcmp(inval, "preop_none") == 0)
preop_val = WDOG_PREOP_NONE;
- } else if (strcmp(preop, "preop_panic") == 0) {
+ else if (strcmp(inval, "preop_panic") == 0)
preop_val = WDOG_PREOP_PANIC;
- } else if (strcmp(preop, "preop_give_data") == 0) {
+ else if (strcmp(inval, "preop_give_data") == 0)
preop_val = WDOG_PREOP_GIVE_DATA;
- } else {
- preop_val = WDOG_PREOP_NONE;
- printk(KERN_INFO PFX "Unknown preop '%s', defaulting to"
- " none\n", preop);
- }
+ else
+ return -EINVAL;
+ strcpy(preop, inval);
+ return 0;
+}
+static void check_parms(void)
+{
#ifdef HAVE_NMI_HANDLER
+ int do_nmi = 0;
+ int rv;
+
if (preaction_val == WDOG_PRETIMEOUT_NMI) {
+ do_nmi = 1;
if (preop_val == WDOG_PREOP_GIVE_DATA) {
printk(KERN_WARNING PFX "Pretimeout op is to give data"
" but NMI pretimeout is enabled, setting"
" pretimeout op to none\n");
- preop_val = WDOG_PREOP_NONE;
+ preop_op("preop_none", NULL);
+ do_nmi = 0;
}
#ifdef CONFIG_X86_LOCAL_APIC
if (nmi_watchdog == NMI_IO_APIC) {
@@ -983,18 +1104,48 @@ static int __init ipmi_wdog_init(void)
" Disabling IPMI nmi pretimeout.\n",
nmi_watchdog);
preaction_val = WDOG_PRETIMEOUT_NONE;
- } else {
+ do_nmi = 0;
+ }
#endif
+ }
+ if (do_nmi && !nmi_handler_registered) {
rv = request_nmi(&ipmi_nmi_handler);
if (rv) {
- printk(KERN_WARNING PFX "Can't register nmi handler\n");
- return rv;
- }
-#ifdef CONFIG_X86_LOCAL_APIC
- }
-#endif
+ printk(KERN_WARNING PFX
+ "Can't register nmi handler\n");
+ return;
+ } else
+ nmi_handler_registered = 1;
+ } else if (!do_nmi && nmi_handler_registered) {
+ release_nmi(&ipmi_nmi_handler);
+ nmi_handler_registered = 0;
}
#endif
+}
+
+static int __init ipmi_wdog_init(void)
+{
+ int rv;
+
+ if (action_op(action, NULL)) {
+ action_op("reset", NULL);
+ printk(KERN_INFO PFX "Unknown action '%s', defaulting to"
+ " reset\n", action);
+ }
+
+ if (preaction_op(preaction, NULL)) {
+ preaction_op("pre_none", NULL);
+ printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to"
+ " none\n", preaction);
+ }
+
+ if (preop_op(preop, NULL)) {
+ preop_op("preop_none", NULL);
+ printk(KERN_INFO PFX "Unknown preop '%s', defaulting to"
+ " none\n", preop);
+ }
+
+ check_parms();
rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
@@ -1021,7 +1172,7 @@ static __exit void ipmi_unregister_watchdog(void)
down_write(&register_sem);
#ifdef HAVE_NMI_HANDLER
- if (preaction_val == WDOG_PRETIMEOUT_NMI)
+ if (nmi_handler_registered)
release_nmi(&ipmi_nmi_handler);
#endif
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index e3ddbdb85a2f..ce3bc0d45f1f 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -860,10 +860,9 @@ static void __exit istallion_module_exit(void)
if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
printk("STALLION: failed to un-register serial memory device, "
"errno=%d\n", -i);
- if (stli_tmpwritebuf != (char *) NULL)
- kfree(stli_tmpwritebuf);
- if (stli_txcookbuf != (char *) NULL)
- kfree(stli_txcookbuf);
+
+ kfree(stli_tmpwritebuf);
+ kfree(stli_txcookbuf);
for (i = 0; (i < stli_nrbrds); i++) {
if ((brdp = stli_brds[i]) == (stlibrd_t *) NULL)
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 45d012d85e8c..3b965a651da4 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -470,6 +470,8 @@ static struct tty_operations mxser_ops = {
.stop = mxser_stop,
.start = mxser_start,
.hangup = mxser_hangup,
+ .break_ctl = mxser_rs_break,
+ .wait_until_sent = mxser_wait_until_sent,
.tiocmget = mxser_tiocmget,
.tiocmset = mxser_tiocmset,
};
@@ -492,14 +494,18 @@ static int __init mxser_module_init(void)
static void __exit mxser_module_exit(void)
{
- int i, err = 0;
+ int i, err;
if (verbose)
printk(KERN_DEBUG "Unloading module mxser ...\n");
- if ((err |= tty_unregister_driver(mxvar_sdriver)))
+ err = tty_unregister_driver(mxvar_sdriver);
+ if (!err)
+ put_tty_driver(mxvar_sdriver);
+ else
printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n");
+
for (i = 0; i < MXSER_BOARDS; i++) {
struct pci_dev *pdev;
@@ -688,7 +694,6 @@ static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxs
static int mxser_init(void)
{
int i, m, retval, b, n;
- int ret1;
struct pci_dev *pdev = NULL;
int index;
unsigned char busnum, devnum;
@@ -722,24 +727,6 @@ static int mxser_init(void)
mxvar_sdriver->termios = mxvar_termios;
mxvar_sdriver->termios_locked = mxvar_termios_locked;
- mxvar_sdriver->open = mxser_open;
- mxvar_sdriver->close = mxser_close;
- mxvar_sdriver->write = mxser_write;
- mxvar_sdriver->put_char = mxser_put_char;
- mxvar_sdriver->flush_chars = mxser_flush_chars;
- mxvar_sdriver->write_room = mxser_write_room;
- mxvar_sdriver->chars_in_buffer = mxser_chars_in_buffer;
- mxvar_sdriver->flush_buffer = mxser_flush_buffer;
- mxvar_sdriver->ioctl = mxser_ioctl;
- mxvar_sdriver->throttle = mxser_throttle;
- mxvar_sdriver->unthrottle = mxser_unthrottle;
- mxvar_sdriver->set_termios = mxser_set_termios;
- mxvar_sdriver->stop = mxser_stop;
- mxvar_sdriver->start = mxser_start;
- mxvar_sdriver->hangup = mxser_hangup;
- mxvar_sdriver->break_ctl = mxser_rs_break;
- mxvar_sdriver->wait_until_sent = mxser_wait_until_sent;
-
mxvar_diagflag = 0;
memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct));
memset(&mxvar_log, 0, sizeof(struct mxser_log));
@@ -870,14 +857,11 @@ static int mxser_init(void)
}
#endif
- ret1 = 0;
- if (!(ret1 = tty_register_driver(mxvar_sdriver))) {
- return 0;
- } else
+ retval = tty_register_driver(mxvar_sdriver);
+ if (retval) {
printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family driver !\n");
+ put_tty_driver(mxvar_sdriver);
-
- if (ret1) {
for (i = 0; i < MXSER_BOARDS; i++) {
if (mxsercfg[i].board_type == -1)
continue;
@@ -886,10 +870,10 @@ static int mxser_init(void)
//todo: release io, vector
}
}
- return -1;
+ return retval;
}
- return (0);
+ return 0;
}
static void mxser_do_softint(void *private_)
@@ -933,6 +917,9 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
struct mxser_struct *info;
int retval, line;
+ /* initialize driver_data in case something fails */
+ tty->driver_data = NULL;
+
line = tty->index;
if (line == MXSER_PORTS)
return 0;
@@ -995,7 +982,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
if (tty->index == MXSER_PORTS)
return;
if (!info)
- BUG();
+ return;
spin_lock_irqsave(&info->slock, flags);
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 5079beda69b5..c3660d8781a4 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -264,8 +264,7 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc)
} else
break;
}
- if (n_hdlc->tbuf)
- kfree(n_hdlc->tbuf);
+ kfree(n_hdlc->tbuf);
kfree(n_hdlc);
} /* end of n_hdlc_release() */
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 02d7f046c10a..2c326ea53421 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2994,8 +2994,7 @@ int rx_alloc_buffers(MGSLPC_INFO *info)
void rx_free_buffers(MGSLPC_INFO *info)
{
- if (info->rx_buf)
- kfree(info->rx_buf);
+ kfree(info->rx_buf);
info->rx_buf = NULL;
}
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 928b850cc679..d3bc731fbb27 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -2512,10 +2512,8 @@ static void rp_cleanup_module(void)
"rocketport driver\n", -retval);
put_tty_driver(rocket_driver);
- for (i = 0; i < MAX_RP_PORTS; i++) {
- if (rp_table[i])
- kfree(rp_table[i]);
- }
+ for (i = 0; i < MAX_RP_PORTS; i++)
+ kfree(rp_table[i]);
for (i = 0; i < NUM_BOARDS; i++) {
if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 16d630f58bb4..5b187c895c18 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -246,8 +246,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
clear_selection();
return -ENOMEM;
}
- if (sel_buffer)
- kfree(sel_buffer);
+ kfree(sel_buffer);
sel_buffer = bp;
obp = bp;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 1c686414e0a1..95af2a941595 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -785,8 +785,7 @@ static void __exit stallion_module_exit(void)
"errno=%d\n", -i);
class_destroy(stallion_class);
- if (stl_tmpwritebuf != (char *) NULL)
- kfree(stl_tmpwritebuf);
+ kfree(stl_tmpwritebuf);
for (i = 0; (i < stl_nrbrds); i++) {
if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
@@ -804,8 +803,7 @@ static void __exit stallion_module_exit(void)
continue;
if (portp->tty != (struct tty_struct *) NULL)
stl_hangup(portp->tty);
- if (portp->tx.buf != (char *) NULL)
- kfree(portp->tx.buf);
+ kfree(portp->tx.buf);
kfree(portp);
}
kfree(panelp);
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 0133dc0e25d0..5d1ffa3bd4c3 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -4016,9 +4016,7 @@ static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
*/
static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
{
- if ( info->intermediate_rxbuffer )
- kfree(info->intermediate_rxbuffer);
-
+ kfree(info->intermediate_rxbuffer);
info->intermediate_rxbuffer = NULL;
} /* end of mgsl_free_intermediate_rxbuffer_memory() */
@@ -4072,10 +4070,8 @@ static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
int i;
for ( i=0; i<info->num_tx_holding_buffers; ++i ) {
- if ( info->tx_holding_buffers[i].buffer ) {
- kfree(info->tx_holding_buffers[i].buffer);
- info->tx_holding_buffers[i].buffer=NULL;
- }
+ kfree(info->tx_holding_buffers[i].buffer);
+ info->tx_holding_buffers[i].buffer = NULL;
}
info->get_tx_holding_index = 0;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index f185724448b1..7c063c5abc55 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -2788,10 +2788,8 @@ static void shutdown(SLMP_INFO * info)
del_timer(&info->tx_timer);
del_timer(&info->status_timer);
- if (info->tx_buf) {
- kfree(info->tx_buf);
- info->tx_buf = NULL;
- }
+ kfree(info->tx_buf);
+ info->tx_buf = NULL;
spin_lock_irqsave(&info->lock,flags);
@@ -3611,8 +3609,7 @@ int alloc_tmp_rx_buf(SLMP_INFO *info)
void free_tmp_rx_buf(SLMP_INFO *info)
{
- if (info->tmp_rx_buf)
- kfree(info->tmp_rx_buf);
+ kfree(info->tmp_rx_buf);
info->tmp_rx_buf = NULL;
}
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 8d125c974a2d..680a8e331887 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -287,10 +287,6 @@ static int __init init_nsc(void)
int lo, hi;
int nscAddrBase = TPM_ADDR;
- driver_register(&nsc_drv);
-
- /* select PM channel 1 */
- tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
/* verify that it is a National part (SID) */
if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
@@ -300,6 +296,8 @@ static int __init init_nsc(void)
return -ENODEV;
}
+ driver_register(&nsc_drv);
+
hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
tpm_nsc.base = (hi<<8) | lo;
@@ -307,11 +305,11 @@ static int __init init_nsc(void)
/* enable the DPM module */
tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
- pdev = kmalloc(sizeof(struct platform_device), GFP_KERNEL);
- if ( !pdev )
- return -ENOMEM;
-
- memset(pdev, 0, sizeof(struct platform_device));
+ pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ if (!pdev) {
+ rc = -ENOMEM;
+ goto err_unreg_drv;
+ }
pdev->name = "tpm_nscl0";
pdev->id = -1;
@@ -319,26 +317,16 @@ static int __init init_nsc(void)
pdev->dev.release = tpm_nsc_remove;
pdev->dev.driver = &nsc_drv;
- if ((rc=platform_device_register(pdev)) < 0) {
- kfree(pdev);
- pdev = NULL;
- return rc;
- }
+ if ((rc = platform_device_register(pdev)) < 0)
+ goto err_free_dev;
if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
- platform_device_unregister(pdev);
- kfree(pdev);
- pdev = NULL;
- return -EBUSY;
+ rc = -EBUSY;
+ goto err_unreg_dev;
}
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) {
- release_region(tpm_nsc.base, 2);
- platform_device_unregister(pdev);
- kfree(pdev);
- pdev = NULL;
- return rc;
- }
+ if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
+ goto err_rel_reg;
dev_dbg(&pdev->dev, "NSC TPM detected\n");
dev_dbg(&pdev->dev,
@@ -374,6 +362,16 @@ static int __init init_nsc(void)
tpm_read_index(nscAddrBase, 0x27) & 0x1F);
return 0;
+
+err_rel_reg:
+ release_region(tpm_nsc.base, 2);
+err_unreg_dev:
+ platform_device_unregister(pdev);
+err_free_dev:
+ kfree(pdev);
+err_unreg_drv:
+ driver_unregister(&nsc_drv);
+ return rc;
}
static void __exit cleanup_nsc(void)
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index c586bfa852ee..4b1eef51ec59 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1416,14 +1416,11 @@ end_init:
/* Release locally allocated memory ... nothing placed in slots */
free_mem_out:
- if (o_tp)
- kfree(o_tp);
+ kfree(o_tp);
if (o_tty)
free_tty_struct(o_tty);
- if (ltp)
- kfree(ltp);
- if (tp)
- kfree(tp);
+ kfree(ltp);
+ kfree(tp);
free_tty_struct(tty);
fail_no_mem:
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 003dda147cd0..24011e7c81ff 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -80,6 +80,9 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str
if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
return -EFAULT;
+ if (!capable(CAP_SYS_TTY_CONFIG))
+ perm = 0;
+
switch (cmd) {
case KDGKBENT:
key_map = key_maps[s];
@@ -193,7 +196,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
int ret;
if (!capable(CAP_SYS_TTY_CONFIG))
- return -EPERM;
+ perm = 0;
kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
if (!kbs) {
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
index 0bc2059c1e08..e0bdc0db9640 100644
--- a/drivers/connector/Kconfig
+++ b/drivers/connector/Kconfig
@@ -10,4 +10,12 @@ config CONNECTOR
Connector support can also be built as a module. If so, the module
will be called cn.ko.
+config PROC_EVENTS
+ boolean "Report process events to userspace"
+ depends on CONNECTOR=y
+ default y
+ ---help---
+ Provide a connector that reports process events to userspace. Send
+ events such as fork, exec, id change (uid, gid, suid, etc), and exit.
+
endmenu
diff --git a/drivers/connector/Makefile b/drivers/connector/Makefile
index 12ca79e8234d..1f255e46e916 100644
--- a/drivers/connector/Makefile
+++ b/drivers/connector/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_CONNECTOR) += cn.o
+obj-$(CONFIG_PROC_EVENTS) += cn_proc.o
cn-y += cn_queue.o connector.o
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
new file mode 100644
index 000000000000..fcdf0fff13a6
--- /dev/null
+++ b/drivers/connector/cn_proc.c
@@ -0,0 +1,222 @@
+/*
+ * cn_proc.c - process events connector
+ *
+ * Copyright (C) Matt Helsley, IBM Corp. 2005
+ * Based on cn_fork.c by Guillaume Thouvenin <guillaume.thouvenin@bull.net>
+ * Original copyright notice follows:
+ * Copyright (C) 2005 BULL SA.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+
+#include <linux/cn_proc.h>
+
+#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event))
+
+static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
+static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
+
+/* proc_counts is used as the sequence number of the netlink message */
+static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 };
+
+static inline void get_seq(__u32 *ts, int *cpu)
+{
+ *ts = get_cpu_var(proc_event_counts)++;
+ *cpu = smp_processor_id();
+ put_cpu_var(proc_counts);
+}
+
+void proc_fork_connector(struct task_struct *task)
+{
+ struct cn_msg *msg;
+ struct proc_event *ev;
+ __u8 buffer[CN_PROC_MSG_SIZE];
+
+ if (atomic_read(&proc_event_num_listeners) < 1)
+ return;
+
+ msg = (struct cn_msg*)buffer;
+ ev = (struct proc_event*)msg->data;
+ get_seq(&msg->seq, &ev->cpu);
+ ev->what = PROC_EVENT_FORK;
+ ev->event_data.fork.parent_pid = task->real_parent->pid;
+ ev->event_data.fork.parent_tgid = task->real_parent->tgid;
+ ev->event_data.fork.child_pid = task->pid;
+ ev->event_data.fork.child_tgid = task->tgid;
+
+ memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+ msg->ack = 0; /* not used */
+ msg->len = sizeof(*ev);
+ /* If cn_netlink_send() failed, the data is not sent */
+ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
+void proc_exec_connector(struct task_struct *task)
+{
+ struct cn_msg *msg;
+ struct proc_event *ev;
+ __u8 buffer[CN_PROC_MSG_SIZE];
+
+ if (atomic_read(&proc_event_num_listeners) < 1)
+ return;
+
+ msg = (struct cn_msg*)buffer;
+ ev = (struct proc_event*)msg->data;
+ get_seq(&msg->seq, &ev->cpu);
+ ev->what = PROC_EVENT_EXEC;
+ ev->event_data.exec.process_pid = task->pid;
+ ev->event_data.exec.process_tgid = task->tgid;
+
+ memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+ msg->ack = 0; /* not used */
+ msg->len = sizeof(*ev);
+ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
+void proc_id_connector(struct task_struct *task, int which_id)
+{
+ struct cn_msg *msg;
+ struct proc_event *ev;
+ __u8 buffer[CN_PROC_MSG_SIZE];
+
+ if (atomic_read(&proc_event_num_listeners) < 1)
+ return;
+
+ msg = (struct cn_msg*)buffer;
+ ev = (struct proc_event*)msg->data;
+ ev->what = which_id;
+ ev->event_data.id.process_pid = task->pid;
+ ev->event_data.id.process_tgid = task->tgid;
+ if (which_id == PROC_EVENT_UID) {
+ ev->event_data.id.r.ruid = task->uid;
+ ev->event_data.id.e.euid = task->euid;
+ } else if (which_id == PROC_EVENT_GID) {
+ ev->event_data.id.r.rgid = task->gid;
+ ev->event_data.id.e.egid = task->egid;
+ } else
+ return;
+ get_seq(&msg->seq, &ev->cpu);
+
+ memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+ msg->ack = 0; /* not used */
+ msg->len = sizeof(*ev);
+ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
+void proc_exit_connector(struct task_struct *task)
+{
+ struct cn_msg *msg;
+ struct proc_event *ev;
+ __u8 buffer[CN_PROC_MSG_SIZE];
+
+ if (atomic_read(&proc_event_num_listeners) < 1)
+ return;
+
+ msg = (struct cn_msg*)buffer;
+ ev = (struct proc_event*)msg->data;
+ get_seq(&msg->seq, &ev->cpu);
+ ev->what = PROC_EVENT_EXIT;
+ ev->event_data.exit.process_pid = task->pid;
+ ev->event_data.exit.process_tgid = task->tgid;
+ ev->event_data.exit.exit_code = task->exit_code;
+ ev->event_data.exit.exit_signal = task->exit_signal;
+
+ memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+ msg->ack = 0; /* not used */
+ msg->len = sizeof(*ev);
+ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
+/*
+ * Send an acknowledgement message to userspace
+ *
+ * Use 0 for success, EFOO otherwise.
+ * Note: this is the negative of conventional kernel error
+ * values because it's not being returned via syscall return
+ * mechanisms.
+ */
+static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
+{
+ struct cn_msg *msg;
+ struct proc_event *ev;
+ __u8 buffer[CN_PROC_MSG_SIZE];
+
+ if (atomic_read(&proc_event_num_listeners) < 1)
+ return;
+
+ msg = (struct cn_msg*)buffer;
+ ev = (struct proc_event*)msg->data;
+ msg->seq = rcvd_seq;
+ ev->cpu = -1;
+ ev->what = PROC_EVENT_NONE;
+ ev->event_data.ack.err = err;
+ memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
+ msg->ack = rcvd_ack + 1;
+ msg->len = sizeof(*ev);
+ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
+}
+
+/**
+ * cn_proc_mcast_ctl
+ * @data: message sent from userspace via the connector
+ */
+static void cn_proc_mcast_ctl(void *data)
+{
+ struct cn_msg *msg = data;
+ enum proc_cn_mcast_op *mc_op = NULL;
+ int err = 0;
+
+ if (msg->len != sizeof(*mc_op))
+ return;
+
+ mc_op = (enum proc_cn_mcast_op*)msg->data;
+ switch (*mc_op) {
+ case PROC_CN_MCAST_LISTEN:
+ atomic_inc(&proc_event_num_listeners);
+ break;
+ case PROC_CN_MCAST_IGNORE:
+ atomic_dec(&proc_event_num_listeners);
+ break;
+ default:
+ err = EINVAL;
+ break;
+ }
+ cn_proc_ack(err, msg->seq, msg->ack);
+}
+
+/*
+ * cn_proc_init - initialization entry point
+ *
+ * Adds the connector callback to the connector driver.
+ */
+static int __init cn_proc_init(void)
+{
+ int err;
+
+ if ((err = cn_add_callback(&cn_proc_event_id, "cn_proc",
+ &cn_proc_mcast_ctl))) {
+ printk(KERN_WARNING "cn_proc failed to register\n");
+ return err;
+ }
+ return 0;
+}
+
+module_init(cn_proc_init);
diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
index a620f7d9ac8e..17502d6efae7 100644
--- a/drivers/dio/dio.c
+++ b/drivers/dio/dio.c
@@ -224,11 +224,10 @@ static int __init dio_init(void)
set_fs(fs);
/* Found a board, allocate it an entry in the list */
- dev = kmalloc(sizeof(struct dio_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct dio_dev), GFP_KERNEL);
if (!dev)
return 0;
- memset(dev, 0, sizeof(struct dio_dev));
dev->bus = &dio_bus;
dev->dev.parent = &dio_bus.dev;
dev->dev.bus = &dio_bus_type;
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 1937743c8e29..4196137e66de 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -281,13 +281,11 @@ static int __init eisa_probe (struct eisa_root_device *root)
/* First try to get hold of slot 0. If there is no device
* here, simply fail, unless root->force_probe is set. */
- if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) {
+ if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) {
printk (KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
return -ENOMEM;
}
- memset (edev, 0, sizeof (*edev));
-
if (eisa_request_resources (root, edev, 0)) {
printk (KERN_WARNING \
"EISA: Cannot allocate resource for mainboard\n");
@@ -317,13 +315,11 @@ static int __init eisa_probe (struct eisa_root_device *root)
force_probe:
for (c = 0, i = 1; i <= root->slots; i++) {
- if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) {
+ if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) {
printk (KERN_ERR "EISA: Out of memory for slot %d\n",
i);
continue;
}
-
- memset (edev, 0, sizeof (*edev));
if (eisa_request_resources (root, edev, i)) {
printk (KERN_WARNING \
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index e4710d1d1f9d..5c8943509cc1 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -266,13 +266,12 @@ static void fcp_report_map_done(fc_channel *fc, int i, int status)
printk ("FC: Bad magic from REPORT_AL_MAP on %s - %08x\n", fc->name, p->magic);
fc->state = FC_STATE_OFFLINE;
} else {
- fc->posmap = (fcp_posmap *)kmalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
+ fc->posmap = (fcp_posmap *)kzalloc(sizeof(fcp_posmap)+p->len, GFP_KERNEL);
if (!fc->posmap) {
printk("FC: Not enough memory, offlining channel\n");
fc->state = FC_STATE_OFFLINE;
} else {
int k;
- memset(fc->posmap, 0, sizeof(fcp_posmap)+p->len);
/* FIXME: This is where SOCAL transfers our AL-PA.
Keep it here till we found out what other cards do... */
fc->sid = (p->magic & 0xff);
@@ -351,14 +350,12 @@ void fcp_register(fc_channel *fc, u8 type, int unregister)
fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd);
fc->scsi_bitmap_end = (slots + 63) & ~63;
size = fc->scsi_bitmap_end / 8;
- fc->scsi_bitmap = kmalloc (size, GFP_KERNEL);
- memset (fc->scsi_bitmap, 0, size);
+ fc->scsi_bitmap = kzalloc (size, GFP_KERNEL);
set_bit (0, fc->scsi_bitmap);
for (i = fc->can_queue; i < fc->scsi_bitmap_end; i++)
set_bit (i, fc->scsi_bitmap);
fc->scsi_free = fc->can_queue;
- fc->cmd_slots = (fcp_cmnd **)kmalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
- memset(fc->cmd_slots, 0, slots * sizeof(fcp_cmnd*));
+ fc->cmd_slots = (fcp_cmnd **)kzalloc(slots * sizeof(fcp_cmnd*), GFP_KERNEL);
fc->abort_count = 0;
} else {
fc->scsi_name[0] = 0;
@@ -541,12 +538,11 @@ int fcp_initialize(fc_channel *fcchain, int count)
FCND(("fcp_inititialize %08lx\n", (long)fcp_init))
FCND(("fc_channels %08lx\n", (long)fc_channels))
FCND((" SID %d DID %d\n", fcchain->sid, fcchain->did))
- l = kmalloc(sizeof (ls) + count, GFP_KERNEL);
+ l = kzalloc(sizeof (ls) + count, GFP_KERNEL);
if (!l) {
printk ("FC: Cannot allocate memory for initialization\n");
return -ENOMEM;
}
- memset (l, 0, sizeof(ls) + count);
l->magic = LSMAGIC;
l->count = count;
FCND(("FCP Init for %d channels\n", count))
@@ -555,17 +551,15 @@ int fcp_initialize(fc_channel *fcchain, int count)
l->timer.function = fcp_login_timeout;
l->timer.data = (unsigned long)l;
atomic_set (&l->todo, count);
- l->logi = kmalloc (count * 3 * sizeof(logi), GFP_KERNEL);
- l->fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
+ l->logi = kzalloc (count * 3 * sizeof(logi), GFP_KERNEL);
+ l->fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
if (!l->logi || !l->fcmds) {
- if (l->logi) kfree (l->logi);
- if (l->fcmds) kfree (l->fcmds);
+ kfree (l->logi);
+ kfree (l->fcmds);
kfree (l);
printk ("FC: Cannot allocate DMA memory for initialization\n");
return -ENOMEM;
}
- memset (l->logi, 0, count * 3 * sizeof(logi));
- memset (l->fcmds, 0, count * sizeof(fcp_cmnd));
for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
fc->state = FC_STATE_UNINITED;
fc->rst_pkt = NULL; /* kmalloc when first used */
@@ -678,13 +672,11 @@ int fcp_forceoffline(fc_channel *fcchain, int count)
l.timer.function = fcp_login_timeout;
l.timer.data = (unsigned long)&l;
atomic_set (&l.todo, count);
- l.fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
+ l.fcmds = kzalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
if (!l.fcmds) {
- kfree (l.fcmds);
printk ("FC: Cannot allocate memory for forcing offline\n");
return -ENOMEM;
}
- memset (l.fcmds, 0, count * sizeof(fcp_cmnd));
FCND(("Initializing OFFLINE packets\n"))
for (fc = fcchain, i = 0; fc && i < count; fc = fc->next, i++) {
fc->state = FC_STATE_UNINITED;
@@ -1114,9 +1106,8 @@ int fc_do_plogi(fc_channel *fc, unsigned char alpa, fc_wwn *node, fc_wwn *nport)
logi *l;
int status;
- l = (logi *)kmalloc(2 * sizeof(logi), GFP_KERNEL);
+ l = (logi *)kzalloc(2 * sizeof(logi), GFP_KERNEL);
if (!l) return -ENOMEM;
- memset(l, 0, 2 * sizeof(logi));
l->code = LS_PLOGI;
memcpy (&l->nport_wwn, &fc->wwn_nport, sizeof(fc_wwn));
memcpy (&l->node_wwn, &fc->wwn_node, sizeof(fc_wwn));
@@ -1149,9 +1140,8 @@ int fc_do_prli(fc_channel *fc, unsigned char alpa)
prli *p;
int status;
- p = (prli *)kmalloc(2 * sizeof(prli), GFP_KERNEL);
+ p = (prli *)kzalloc(2 * sizeof(prli), GFP_KERNEL);
if (!p) return -ENOMEM;
- memset(p, 0, 2 * sizeof(prli));
p->code = LS_PRLI;
p->params[0] = 0x08002000;
p->params[3] = 0x00000022;
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
index 247b46302777..ec1f94738c59 100644
--- a/drivers/fc4/soc.c
+++ b/drivers/fc4/soc.c
@@ -556,10 +556,9 @@ static inline void soc_init(struct sbus_dev *sdev, int no)
int size, i;
int irq;
- s = kmalloc (sizeof (struct soc), GFP_KERNEL);
+ s = kzalloc (sizeof (struct soc), GFP_KERNEL);
if (s == NULL)
return;
- memset (s, 0, sizeof(struct soc));
spin_lock_init(&s->lock);
s->soc_no = no;
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
index b2377dbd84a1..922e9613b2cf 100644
--- a/drivers/fc4/socal.c
+++ b/drivers/fc4/socal.c
@@ -665,9 +665,8 @@ static inline void socal_init(struct sbus_dev *sdev, int no)
int size, i;
int irq, node;
- s = kmalloc (sizeof (struct socal), GFP_KERNEL);
+ s = kzalloc (sizeof (struct socal), GFP_KERNEL);
if (!s) return;
- memset (s, 0, sizeof(struct socal));
spin_lock_init(&s->lock);
s->socal_no = no;
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 125929c9048f..ba17292eb290 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -50,7 +50,7 @@
MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
MODULE_LICENSE("GPL");
-MODULE_VERSION("3.0");
+MODULE_VERSION("3.1");
#define BIOS_SCAN_LIMIT 0xffffffff
#define MAX_IMAGE_LENGTH 16
@@ -73,6 +73,11 @@ module_param_string(image_type, image_type, sizeof (image_type), 0);
MODULE_PARM_DESC(image_type,
"BIOS image type. choose- mono or packet or init");
+static unsigned long allocation_floor = 0x100000;
+module_param(allocation_floor, ulong, 0644);
+MODULE_PARM_DESC(allocation_floor,
+ "Minimum address for allocations when using Packet mode");
+
struct packet_data {
struct list_head list;
size_t length;
@@ -99,61 +104,122 @@ static int create_packet(void *data, size_t length)
{
struct packet_data *newpacket;
int ordernum = 0;
+ int retval = 0;
+ unsigned int packet_array_size = 0;
+ void **invalid_addr_packet_array = 0;
+ void *packet_data_temp_buf = 0;
+ unsigned int idx = 0;
pr_debug("create_packet: entry \n");
if (!rbu_data.packetsize) {
pr_debug("create_packet: packetsize not specified\n");
- return -EINVAL;
+ retval = -EINVAL;
+ goto out_noalloc;
}
+
spin_unlock(&rbu_data.lock);
- newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL);
- spin_lock(&rbu_data.lock);
+
+ newpacket = kzalloc(sizeof (struct packet_data), GFP_KERNEL);
if (!newpacket) {
printk(KERN_WARNING
"dell_rbu:%s: failed to allocate new "
"packet\n", __FUNCTION__);
- return -ENOMEM;
+ retval = -ENOMEM;
+ spin_lock(&rbu_data.lock);
+ goto out_noalloc;
}
ordernum = get_order(length);
+
/*
- * there is no upper limit on memory
- * address for packetized mechanism
+ * BIOS errata mean we cannot allocate packets below 1MB or they will
+ * be overwritten by BIOS.
+ *
+ * array to temporarily hold packets
+ * that are below the allocation floor
+ *
+ * NOTE: very simplistic because we only need the floor to be at 1MB
+ * due to BIOS errata. This shouldn't be used for higher floors
+ * or you will run out of mem trying to allocate the array.
*/
- spin_unlock(&rbu_data.lock);
- newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL,
- ordernum);
- spin_lock(&rbu_data.lock);
+ packet_array_size = max(
+ (unsigned int)(allocation_floor / rbu_data.packetsize),
+ (unsigned int)1);
+ invalid_addr_packet_array = kzalloc(packet_array_size * sizeof(void*),
+ GFP_KERNEL);
- pr_debug("create_packet: newpacket %p\n", newpacket->data);
-
- if (!newpacket->data) {
+ if (!invalid_addr_packet_array) {
printk(KERN_WARNING
- "dell_rbu:%s: failed to allocate new "
- "packet\n", __FUNCTION__);
- kfree(newpacket);
- return -ENOMEM;
+ "dell_rbu:%s: failed to allocate "
+ "invalid_addr_packet_array \n",
+ __FUNCTION__);
+ retval = -ENOMEM;
+ spin_lock(&rbu_data.lock);
+ goto out_alloc_packet;
}
+ while (!packet_data_temp_buf) {
+ packet_data_temp_buf = (unsigned char *)
+ __get_free_pages(GFP_KERNEL, ordernum);
+ if (!packet_data_temp_buf) {
+ printk(KERN_WARNING
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
+ retval = -ENOMEM;
+ spin_lock(&rbu_data.lock);
+ goto out_alloc_packet_array;
+ }
+
+ if ((unsigned long)virt_to_phys(packet_data_temp_buf)
+ < allocation_floor) {
+ pr_debug("packet 0x%lx below floor at 0x%lx.\n",
+ (unsigned long)virt_to_phys(
+ packet_data_temp_buf),
+ allocation_floor);
+ invalid_addr_packet_array[idx++] = packet_data_temp_buf;
+ packet_data_temp_buf = 0;
+ }
+ }
+ spin_lock(&rbu_data.lock);
+
+ newpacket->data = packet_data_temp_buf;
+
+ pr_debug("create_packet: newpacket at physical addr %lx\n",
+ (unsigned long)virt_to_phys(newpacket->data));
+
+ /* packets may not have fixed size */
+ newpacket->length = length;
newpacket->ordernum = ordernum;
++rbu_data.num_packets;
- /*
- * initialize the newly created packet headers
- */
+
+ /* initialize the newly created packet headers */
INIT_LIST_HEAD(&newpacket->list);
list_add_tail(&newpacket->list, &packet_data_head.list);
- /*
- * packets may not have fixed size
- */
- newpacket->length = length;
memcpy(newpacket->data, data, length);
pr_debug("create_packet: exit \n");
- return 0;
+out_alloc_packet_array:
+ /* always free packet array */
+ for (;idx>0;idx--) {
+ pr_debug("freeing unused packet below floor 0x%lx.\n",
+ (unsigned long)virt_to_phys(
+ invalid_addr_packet_array[idx-1]));
+ free_pages((unsigned long)invalid_addr_packet_array[idx-1],
+ ordernum);
+ }
+ kfree(invalid_addr_packet_array);
+
+out_alloc_packet:
+ /* if error, free data */
+ if (retval)
+ kfree(newpacket);
+
+out_noalloc:
+ return retval;
}
static int packetize_data(void *data, size_t length)
@@ -693,3 +759,6 @@ static __exit void dcdrbu_exit(void)
module_exit(dcdrbu_exit);
module_init(dcdrbu_init);
+
+/* vim:noet:ts=8:sw=8
+*/
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 6996476669f1..b4502ed65793 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -715,7 +715,6 @@ edd_device_register(struct edd_device *edev, int i)
if (!edev)
return 1;
- memset(edev, 0, sizeof (*edev));
edd_dev_set_info(edev, i);
kobject_set_name(&edev->kobj, "int13_dev%02x",
0x80 + i);
@@ -756,7 +755,7 @@ edd_init(void)
return rc;
for (i = 0; i < edd_num_devices() && !rc; i++) {
- edev = kmalloc(sizeof (*edev), GFP_KERNEL);
+ edev = kzalloc(sizeof (*edev), GFP_KERNEL);
if (!edev)
return -ENOMEM;
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 33b17c6a46fb..bda5bce681b6 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -614,16 +614,14 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
char *short_name;
struct efivar_entry *new_efivar;
- short_name = kmalloc(short_name_size + 1, GFP_KERNEL);
- new_efivar = kmalloc(sizeof(struct efivar_entry), GFP_KERNEL);
+ short_name = kzalloc(short_name_size + 1, GFP_KERNEL);
+ new_efivar = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
if (!short_name || !new_efivar) {
kfree(short_name);
kfree(new_efivar);
return 1;
}
- memset(short_name, 0, short_name_size+1);
- memset(new_efivar, 0, sizeof(struct efivar_entry));
memcpy(new_efivar->var.VariableName, variable_name,
variable_name_size);
@@ -674,14 +672,12 @@ efivars_init(void)
if (!efi_enabled)
return -ENODEV;
- variable_name = kmalloc(variable_name_size, GFP_KERNEL);
+ variable_name = kzalloc(variable_name_size, GFP_KERNEL);
if (!variable_name) {
printk(KERN_ERR "efivars: Memory allocation failed.\n");
return -ENOMEM;
}
- memset(variable_name, 0, variable_name_size);
-
printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
EFIVARS_DATE);
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 6f48579799b5..dddd3eb9b387 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -16,6 +16,7 @@
#include <linux/kdev_t.h>
#include <linux/idr.h>
#include <linux/hwmon.h>
+#include <linux/gfp.h>
#define HWMON_ID_PREFIX "hwmon"
#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 6a82ffae1bfd..69e7e125683b 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -193,7 +193,7 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
int err = 0;
const char *name = "";
u8 reg_config=0, reg_convrate=0, reg_status=0;
- u8 man_id, chip_id;
+
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
@@ -238,16 +238,15 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (kind <= 0) { /* identification */
+ u8 man_id, chip_id;
man_id = i2c_smbus_read_byte_data(new_client,
MAX1619_REG_R_MAN_ID);
chip_id = i2c_smbus_read_byte_data(new_client,
MAX1619_REG_R_CHIP_ID);
- if ((man_id == 0x4D) && (chip_id == 0x04)){
- kind = max1619;
- }
- }
+ if ((man_id == 0x4D) && (chip_id == 0x04))
+ kind = max1619;
if (kind <= 0) { /* identification failed */
dev_info(&adapter->dev,
@@ -255,11 +254,10 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
"chip_id=0x%02X).\n", man_id, chip_id);
goto exit_free;
}
-
+ }
- if (kind == max1619){
+ if (kind == max1619)
name = "max1619";
- }
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 9265f32122fa..ffdb3a03e2b5 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -976,11 +976,9 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
ERROR_SC_3:
i2c_detach_client(data->lm75[0]);
ERROR_SC_2:
- if (data->lm75[1])
- kfree(data->lm75[1]);
+ kfree(data->lm75[1]);
ERROR_SC_1:
- if (data->lm75[0])
- kfree(data->lm75[0]);
+ kfree(data->lm75[0]);
ERROR_SC_0:
return err;
}
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index f51ab652300a..56c7d987590f 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -245,10 +245,8 @@ static void __exit amd756_s4882_exit(void)
kfree(s4882_adapter);
s4882_adapter = NULL;
}
- if (s4882_algo) {
- kfree(s4882_algo);
- s4882_algo = NULL;
- }
+ kfree(s4882_algo);
+ s4882_algo = NULL;
/* Restore physical bus */
if (i2c_add_adapter(&amd756_smbus))
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 8b9d85526596..c2f47923d174 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -3292,12 +3292,9 @@ static void ide_cd_release(struct kref *kref)
ide_drive_t *drive = info->drive;
struct gendisk *g = info->disk;
- if (info->buffer != NULL)
- kfree(info->buffer);
- if (info->toc != NULL)
- kfree(info->toc);
- if (info->changer_info != NULL)
- kfree(info->changer_info);
+ kfree(info->buffer);
+ kfree(info->toc);
+ kfree(info->changer_info);
if (devinfo->handle == drive && unregister_cdrom(devinfo))
printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
"driver.\n", __FUNCTION__, drive->name);
@@ -3455,7 +3452,7 @@ static int ide_cd_probe(struct device *dev)
printk(KERN_INFO "ide-cd: passing drive %s to ide-scsi emulation.\n", drive->name);
goto failed;
}
- info = kmalloc(sizeof(struct cdrom_info), GFP_KERNEL);
+ info = kzalloc(sizeof(struct cdrom_info), GFP_KERNEL);
if (info == NULL) {
printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
goto failed;
@@ -3469,8 +3466,6 @@ static int ide_cd_probe(struct device *dev)
ide_register_subdriver(drive, &ide_cdrom_driver);
- memset(info, 0, sizeof (struct cdrom_info));
-
kref_init(&info->kref);
info->drive = drive;
@@ -3489,12 +3484,9 @@ static int ide_cd_probe(struct device *dev)
if (ide_cdrom_setup(drive)) {
struct cdrom_device_info *devinfo = &info->devinfo;
ide_unregister_subdriver(drive, &ide_cdrom_driver);
- if (info->buffer != NULL)
- kfree(info->buffer);
- if (info->toc != NULL)
- kfree(info->toc);
- if (info->changer_info != NULL)
- kfree(info->changer_info);
+ kfree(info->buffer);
+ kfree(info->toc);
+ kfree(info->changer_info);
if (devinfo->handle == drive && unregister_cdrom(devinfo))
printk (KERN_ERR "%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name);
kfree(info);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 234f5de3e929..e827b39e4b3c 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1215,7 +1215,7 @@ static int ide_disk_probe(struct device *dev)
if (drive->media != ide_disk)
goto failed;
- idkp = kmalloc(sizeof(*idkp), GFP_KERNEL);
+ idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
if (!idkp)
goto failed;
@@ -1228,8 +1228,6 @@ static int ide_disk_probe(struct device *dev)
ide_register_subdriver(drive, &idedisk_driver);
- memset(idkp, 0, sizeof(*idkp));
-
kref_init(&idkp->kref);
idkp->drive = drive;
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 29c22fc278c6..e83f54d37f96 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -2146,7 +2146,7 @@ static int ide_floppy_probe(struct device *dev)
printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
goto failed;
}
- if ((floppy = (idefloppy_floppy_t *) kmalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
+ if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
goto failed;
}
@@ -2159,8 +2159,6 @@ static int ide_floppy_probe(struct device *dev)
ide_register_subdriver(drive, &idefloppy_driver);
- memset(floppy, 0, sizeof(*floppy));
-
kref_init(&floppy->kref);
floppy->drive = drive;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index c1128ae5cd2f..02167a5b751d 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -596,14 +596,13 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
* Also note that 0 everywhere means "can't do X"
*/
- drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL);
+ drive->id = kzalloc(SECTOR_WORDS *4, GFP_KERNEL);
drive->id_read = 0;
if(drive->id == NULL)
{
printk(KERN_ERR "ide: out of memory for id data.\n");
return 0;
}
- memset(drive->id, 0, SECTOR_WORDS * 4);
strcpy(drive->id->model, "UNKNOWN");
/* skip probing? */
@@ -1316,10 +1315,8 @@ static void drive_release_dev (struct device *dev)
drive->devfs_name[0] = '\0';
}
ide_remove_drive_from_hwgroup(drive);
- if (drive->id != NULL) {
- kfree(drive->id);
- drive->id = NULL;
- }
+ kfree(drive->id);
+ drive->id = NULL;
drive->present = 0;
/* Messed up locking ... */
spin_unlock_irq(&ide_lock);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 47f2b832555f..0ac7eb8f40d5 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4850,7 +4850,7 @@ static int ide_tape_probe(struct device *dev)
printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
}
- tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL);
+ tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL);
if (tape == NULL) {
printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
goto failed;
@@ -4864,8 +4864,6 @@ static int ide_tape_probe(struct device *dev)
ide_register_subdriver(drive, &idetape_driver);
- memset(tape, 0, sizeof(*tape));
-
kref_init(&tape->kref);
tape->drive = drive;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index ace8edad6e96..7ec18fa3b5ff 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -528,9 +528,8 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
// printk("IDE Taskfile ...\n");
- req_task = kmalloc(tasksize, GFP_KERNEL);
+ req_task = kzalloc(tasksize, GFP_KERNEL);
if (req_task == NULL) return -ENOMEM;
- memset(req_task, 0, tasksize);
if (copy_from_user(req_task, buf, tasksize)) {
kfree(req_task);
return -EFAULT;
@@ -541,12 +540,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
if (taskout) {
int outtotal = tasksize;
- outbuf = kmalloc(taskout, GFP_KERNEL);
+ outbuf = kzalloc(taskout, GFP_KERNEL);
if (outbuf == NULL) {
err = -ENOMEM;
goto abort;
}
- memset(outbuf, 0, taskout);
if (copy_from_user(outbuf, buf + outtotal, taskout)) {
err = -EFAULT;
goto abort;
@@ -555,12 +553,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
if (taskin) {
int intotal = tasksize + taskout;
- inbuf = kmalloc(taskin, GFP_KERNEL);
+ inbuf = kzalloc(taskin, GFP_KERNEL);
if (inbuf == NULL) {
err = -ENOMEM;
goto abort;
}
- memset(inbuf, 0, taskin);
if (copy_from_user(inbuf, buf + intotal, taskin)) {
err = -EFAULT;
goto abort;
@@ -649,10 +646,8 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
}
abort:
kfree(req_task);
- if (outbuf != NULL)
- kfree(outbuf);
- if (inbuf != NULL)
- kfree(inbuf);
+ kfree(outbuf);
+ kfree(inbuf);
// printk("IDE Taskfile ioctl ended. rc = %i\n", err);
@@ -709,10 +704,9 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
if (args[3]) {
argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
- argbuf = kmalloc(argsize, GFP_KERNEL);
+ argbuf = kzalloc(argsize, GFP_KERNEL);
if (argbuf == NULL)
return -ENOMEM;
- memcpy(argbuf, args, 4);
}
if (set_transfer(drive, &tfargs)) {
xfer_rate = args[1];
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 73ca8f73917d..9fe19808d815 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -864,9 +864,8 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int r
down(&ide_setting_sem);
while ((*p) && strcmp((*p)->name, name) < 0)
p = &((*p)->next);
- if ((setting = kmalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
+ if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
goto abort;
- memset(setting, 0, sizeof(*setting));
if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
goto abort;
strcpy(setting->name, name);
@@ -889,8 +888,7 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int r
return 0;
abort:
up(&ide_setting_sem);
- if (setting)
- kfree(setting);
+ kfree(setting);
return -1;
}
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index a35a58bef1a4..1dafffa7e513 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -116,9 +116,8 @@ static dev_link_t *ide_attach(void)
DEBUG(0, "ide_attach()\n");
/* Create new ide device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) return NULL;
- memset(info, 0, sizeof(*info));
link = &info->link; link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
@@ -221,9 +220,8 @@ static void ide_config(dev_link_t *link)
DEBUG(0, "ide_config(0x%p)\n", link);
- stk = kmalloc(sizeof(*stk), GFP_KERNEL);
+ stk = kzalloc(sizeof(*stk), GFP_KERNEL);
if (!stk) goto err_mem;
- memset(stk, 0, sizeof(*stk));
cfg = &stk->parse.cftable_entry;
tuple.TupleData = (cisdata_t *)&stk->buf;
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 127619a109ed..7b589d948bf9 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1516,7 +1516,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
{
- struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL);
+ struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4);
u8 did, rid;
@@ -1524,7 +1524,6 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
printk(KERN_WARNING "hpt366: out of memory.\n");
return;
}
- memset(info, 0, sizeof(struct hpt_info));
ide_set_hwifdata(hwif, info);
if(dmabase) {
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index e440036e651f..108fda83fea4 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -642,14 +642,13 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
{
- struct it821x_dev *idev = kmalloc(sizeof(struct it821x_dev), GFP_KERNEL);
+ struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
u8 conf;
if(idev == NULL) {
printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
goto fallback;
}
- memset(idev, 0, sizeof(struct it821x_dev));
ide_set_hwifdata(hwif, idev);
pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
index e8e28569a668..75897509c401 100644
--- a/drivers/ieee1394/amdtp.c
+++ b/drivers/ieee1394/amdtp.c
@@ -320,8 +320,7 @@ static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous)
if ((control & OHCI1394_CONTEXT_ACTIVE) == 0)
break;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
}
}
}
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index 7545775d38ef..34b724afd28d 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -37,6 +37,9 @@
* $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
*/
+#include <linux/slab.h>
+#include <linux/string.h>
+
#include "agent.h"
#include "smi.h"
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 3d8175e5f054..41d6b4017acb 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -508,8 +508,7 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
wait_event(mad_agent_priv->wait,
!atomic_read(&mad_agent_priv->refcount));
- if (mad_agent_priv->reg_req)
- kfree(mad_agent_priv->reg_req);
+ kfree(mad_agent_priv->reg_req);
ib_dereg_mr(mad_agent_priv->agent.mr);
kfree(mad_agent_priv);
}
@@ -2500,8 +2499,7 @@ error:
static void destroy_mad_qp(struct ib_mad_qp_info *qp_info)
{
ib_destroy_qp(qp_info->qp);
- if (qp_info->snoop_table)
- kfree(qp_info->snoop_table);
+ kfree(qp_info->snoop_table);
}
/*
diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c
index 35df5010e723..c972d7235764 100644
--- a/drivers/infiniband/core/packer.c
+++ b/drivers/infiniband/core/packer.c
@@ -33,6 +33,8 @@
* $Id: packer.c 1349 2004-12-16 21:09:43Z roland $
*/
+#include <linux/string.h>
+
#include <rdma/ib_pack.h>
static u64 value_read(int offset, int size, void *structure)
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index b8120650e711..08648b1a387e 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -36,6 +36,9 @@
#include "core_priv.h"
+#include <linux/slab.h>
+#include <linux/string.h>
+
#include <rdma/ib_mad.h>
struct ib_port {
diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c
index 527b23450ab3..997c07db6d8f 100644
--- a/drivers/infiniband/core/ud_header.c
+++ b/drivers/infiniband/core/ud_header.c
@@ -34,6 +34,7 @@
*/
#include <linux/errno.h>
+#include <linux/string.h>
#include <rdma/ib_pack.h>
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 72d3ef786db5..4186cc888ea5 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -40,6 +40,7 @@
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/string.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_cache.h>
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c
index 7ac52af43b99..25ebab64bc42 100644
--- a/drivers/infiniband/hw/mthca/mthca_catas.c
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -32,6 +32,9 @@
* $Id$
*/
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+
#include "mthca_dev.h"
enum {
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 292f55be8cbd..26d5161fde07 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -32,6 +32,9 @@
* $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $
*/
+#include <linux/slab.h>
+#include <linux/string.h>
+
#include "mthca_dev.h"
#include "mthca_cmd.h"
#include "mthca_memfree.h"
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 4015a91f4b6e..948c1cc01bc9 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -271,8 +271,7 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz
goto exit;
}
- if (dev->name)
- kfree(dev->name);
+ kfree(dev->name);
size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
dev->name = name = kmalloc(size, GFP_KERNEL);
@@ -372,11 +371,8 @@ static int uinput_burn_device(struct uinput_device *udev)
if (test_bit(UIST_CREATED, &udev->state))
uinput_destroy_device(udev);
- if (udev->dev->name)
- kfree(udev->dev->name);
- if (udev->dev->phys)
- kfree(udev->dev->phys);
-
+ kfree(udev->dev->name);
+ kfree(udev->dev->phys);
kfree(udev->dev);
kfree(udev);
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index db9bad2b3d16..27391c32f3eb 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -212,11 +212,8 @@ static void avmcs_detach(dev_link_t *link)
/* Unlink device structure, free pieces */
*linkp = link->next;
- if (link->priv) {
- kfree(link->priv);
- }
+ kfree(link->priv);
kfree(link);
-
} /* avmcs_detach */
/*======================================================================
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 625799ab0d14..5d8ee7368f7b 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -552,14 +552,10 @@ close_hdlcstate(struct BCState *bcs)
{
modehdlc(bcs, 0, 0);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (bcs->hw.hdlc.rcvbuf) {
- kfree(bcs->hw.hdlc.rcvbuf);
- bcs->hw.hdlc.rcvbuf = NULL;
- }
- if (bcs->blog) {
- kfree(bcs->blog);
- bcs->blog = NULL;
- }
+ kfree(bcs->hw.hdlc.rcvbuf);
+ bcs->hw.hdlc.rcvbuf = NULL;
+ kfree(bcs->blog);
+ bcs->blog = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 0e22991635e7..5f5a5ae740d2 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -236,9 +236,7 @@ static void avma1cs_detach(dev_link_t *link)
/* Unlink device structure, free pieces */
*linkp = link->next;
- if (link->priv) {
- kfree(link->priv);
- }
+ kfree(link->priv);
kfree(link);
} /* avma1cs_detach */
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index fbaab4352902..8159bcecd0c2 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -787,8 +787,7 @@ static void ll_unload(struct IsdnCardState *cs)
ic.command = ISDN_STAT_UNLOAD;
ic.driver = cs->myid;
cs->iif.statcallb(&ic);
- if (cs->status_buf)
- kfree(cs->status_buf);
+ kfree(cs->status_buf);
cs->status_read = NULL;
cs->status_write = NULL;
cs->status_end = NULL;
@@ -807,10 +806,8 @@ static void closecard(int cardnr)
skb_queue_purge(&csta->rq);
skb_queue_purge(&csta->sq);
- if (csta->rcvbuf) {
- kfree(csta->rcvbuf);
- csta->rcvbuf = NULL;
- }
+ kfree(csta->rcvbuf);
+ csta->rcvbuf = NULL;
if (csta->tx_skb) {
dev_kfree_skb(csta->tx_skb);
csta->tx_skb = NULL;
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index 7cf87793e790..637a261c9312 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -1052,18 +1052,12 @@ init2bds0(struct IsdnCardState *cs)
void
release2bds0(struct IsdnCardState *cs)
{
- if (cs->bcs[0].hw.hfc.send) {
- kfree(cs->bcs[0].hw.hfc.send);
- cs->bcs[0].hw.hfc.send = NULL;
- }
- if (cs->bcs[1].hw.hfc.send) {
- kfree(cs->bcs[1].hw.hfc.send);
- cs->bcs[1].hw.hfc.send = NULL;
- }
- if (cs->hw.hfcD.send) {
- kfree(cs->hw.hfcD.send);
- cs->hw.hfcD.send = NULL;
- }
+ kfree(cs->bcs[0].hw.hfc.send);
+ cs->bcs[0].hw.hfc.send = NULL;
+ kfree(cs->bcs[1].hw.hfc.send);
+ cs->bcs[1].hw.hfc.send = NULL;
+ kfree(cs->hw.hfcD.send);
+ cs->hw.hfcD.send = NULL;
}
void
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index f978a5af8662..c964539cc43e 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -582,12 +582,8 @@ inithfc(struct IsdnCardState *cs)
void
releasehfc(struct IsdnCardState *cs)
{
- if (cs->bcs[0].hw.hfc.send) {
- kfree(cs->bcs[0].hw.hfc.send);
- cs->bcs[0].hw.hfc.send = NULL;
- }
- if (cs->bcs[1].hw.hfc.send) {
- kfree(cs->bcs[1].hw.hfc.send);
- cs->bcs[1].hw.hfc.send = NULL;
- }
+ kfree(cs->bcs[0].hw.hfc.send);
+ cs->bcs[0].hw.hfc.send = NULL;
+ kfree(cs->bcs[1].hw.hfc.send);
+ cs->bcs[1].hw.hfc.send = NULL;
}
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index e2c3af49d72b..32bf0d5d0f9a 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1,7 +1,7 @@
/*
* hfc_usb.c
*
- * $Id: hfc_usb.c,v 4.34 2005/01/26 17:25:53 martinb1 Exp $
+ * $Id: hfc_usb.c,v 4.36 2005/04/08 09:55:13 martinb1 Exp $
*
* modular HiSax ISDN driver for Colognechip HFC-S USB chip
*
@@ -44,12 +44,8 @@
#include "hisax_if.h"
#include "hfc_usb.h"
-/*
-* Version Information
-* (do not modify the CVS Makros $Revision: 4.34 $ and $Date: 2005/01/26 17:25:53 $ !)
-*/
static const char *hfcusb_revision =
- "Revision: 4.34 $ Date: 2005/01/26 17:25:53 $ ";
+ "$Revision: 4.36 $ $Date: 2005/04/08 09:55:13 $ ";
/* Hisax debug support
* use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG
@@ -63,81 +59,89 @@ module_param(debug, uint, 0);
static int hfc_debug;
#endif
+/* private vendor specific data */
+typedef struct {
+ __u8 led_scheme; // led display scheme
+ signed short led_bits[8]; // array of 8 possible LED bitmask settings
+ char *vend_name; // device name
+} hfcsusb_vdata;
/****************************************/
/* data defining the devices to be used */
/****************************************/
-static struct usb_device_id hfc_usb_idtab[] = {
- {USB_DEVICE(0x0959, 0x2bd0)}, /* Colognechip USB eval TA */
- {USB_DEVICE(0x0675, 0x1688)}, /* DrayTek miniVigor 128 USB ISDN TA */
- {USB_DEVICE(0x07b0, 0x0007)}, /* Billion USB TA 2 */
- {USB_DEVICE(0x0742, 0x2008)}, /* Stollmann USB TA */
- {USB_DEVICE(0x0742, 0x2009)}, /* Aceex USB ISDN TA */
- {USB_DEVICE(0x0742, 0x200A)}, /* OEM USB ISDN TA */
- {USB_DEVICE(0x08e3, 0x0301)}, /* OliTec ISDN USB */
- {USB_DEVICE(0x07fa, 0x0846)}, /* Bewan ISDN USB TA */
- {USB_DEVICE(0x07fa, 0x0847)}, /* Djinn Numeris USB */
- {USB_DEVICE(0x07b0, 0x0006)}, /* Twister ISDN USB TA */
- {} /* end with an all-zeroes entry */
+static struct usb_device_id hfcusb_idtab[] = {
+ {
+ .idVendor = 0x0959,
+ .idProduct = 0x2bd0,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_OFF, {4, 0, 2, 1},
+ "ISDN USB TA (Cologne Chip HFC-S USB based)"}),
+ },
+ {
+ .idVendor = 0x0675,
+ .idProduct = 0x1688,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {1, 2, 0, 0},
+ "DrayTek miniVigor 128 USB ISDN TA"}),
+ },
+ {
+ .idVendor = 0x07b0,
+ .idProduct = 0x0007,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Billion tiny USB ISDN TA 128"}),
+ },
+ {
+ .idVendor = 0x0742,
+ .idProduct = 0x2008,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {4, 0, 2, 1},
+ "Stollmann USB TA"}),
+ },
+ {
+ .idVendor = 0x0742,
+ .idProduct = 0x2009,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {4, 0, 2, 1},
+ "Aceex USB ISDN TA"}),
+ },
+ {
+ .idVendor = 0x0742,
+ .idProduct = 0x200A,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {4, 0, 2, 1},
+ "OEM USB ISDN TA"}),
+ },
+ {
+ .idVendor = 0x08e3,
+ .idProduct = 0x0301,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {2, 0, 1, 4},
+ "Olitec USB RNIS"}),
+ },
+ {
+ .idVendor = 0x07fa,
+ .idProduct = 0x0846,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Bewan Modem RNIS USB"}),
+ },
+ {
+ .idVendor = 0x07fa,
+ .idProduct = 0x0847,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Djinn Numeris USB"}),
+ },
+ {
+ .idVendor = 0x07b0,
+ .idProduct = 0x0006,
+ .driver_info = (unsigned long) &((hfcsusb_vdata)
+ {LED_SCHEME1, {0x80, -64, -32, -16},
+ "Twister ISDN TA"}),
+ },
};
-/* driver internal device specific data:
-* VendorID, ProductID, Devicename, LED_SCHEME,
-* LED's BitMask in HFCUSB_P_DATA Register : LED_USB, LED_S0, LED_B1, LED_B2
-*/
-static vendor_data vdata[] = {
- /* CologneChip Eval TA */
- {0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)",
- LED_OFF, {4, 0, 2, 1}
- }
- ,
- /* DrayTek miniVigor 128 USB ISDN TA */
- {0x0675, 0x1688, "DrayTek miniVigor 128 USB ISDN TA",
- LED_SCHEME1, {1, 2, 0, 0}
- }
- ,
- /* Billion TA */
- {0x07b0, 0x0007, "Billion tiny USB ISDN TA 128",
- LED_SCHEME1, {0x80, -64, -32, -16}
- }
- ,
- /* Stollmann TA */
- {0x0742, 0x2008, "Stollmann USB TA",
- LED_SCHEME1, {4, 0, 2, 1}
- }
- ,
- /* Aceex USB ISDN TA */
- {0x0742, 0x2009, "Aceex USB ISDN TA",
- LED_SCHEME1, {4, 0, 2, 1}
- }
- ,
- /* OEM USB ISDN TA */
- {0x0742, 0x200A, "OEM USB ISDN TA",
- LED_SCHEME1, {4, 0, 2, 1}
- }
- ,
- /* Olitec TA */
- {0x08e3, 0x0301, "Olitec USB RNIS",
- LED_SCHEME1, {2, 0, 1, 4}
- }
- ,
- /* Bewan TA */
- {0x07fa, 0x0846, "Bewan Modem RNIS USB",
- LED_SCHEME1, {0x80, -64, -32, -16}
- }
- ,
- /* Bewan TA */
- {0x07fa, 0x0847, "Djinn Numeris USB",
- LED_SCHEME1, {0x80, -64, -32, -16}
- }
- ,
- /* Twister ISDN TA */
- {0x07b0, 0x0006, "Twister ISDN TA",
- LED_SCHEME1, {0x80, -64, -32, -16}
- }
- ,
- {0, 0, 0} /* EOL element */
-};
/***************************************************************/
/* structure defining input+output fifos (interrupt/bulk mode) */
@@ -211,8 +215,6 @@ typedef struct hfcusb_data {
volatile __u8 l1_state; /* actual l1 state */
struct timer_list t3_timer; /* timer 3 for activation/deactivation */
struct timer_list t4_timer; /* timer 4 for activation/deactivation */
- struct timer_list led_timer; /* timer flashing leds */
-
} hfcusb_data;
@@ -227,7 +229,7 @@ symbolic(struct hfcusb_symbolic_list list[], const int num)
for (i = 0; list[i].name != NULL; i++)
if (list[i].num == num)
return (list[i].name);
- return "<unkown>";
+ return "<unkown ERROR>";
}
@@ -335,93 +337,57 @@ set_led_bit(hfcusb_data * hfc, signed short led_bits, int unset)
}
}
-/******************************************/
-/* invert B-channel LEDs if data is sent */
-/******************************************/
-static void
-led_timer(hfcusb_data * hfc)
-{
- static int cnt = 0;
-
- if (cnt) {
- if (hfc->led_b_active & 1)
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
- 0);
- if (hfc->led_b_active & 2)
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
- 0);
- } else {
- if (!(hfc->led_b_active & 1) || hfc->led_new_data & 1)
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
- 1);
- if (!(hfc->led_b_active & 2) || hfc->led_new_data & 2)
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
- 1);
- }
-
- write_led(hfc, hfc->led_state);
- hfc->led_new_data = 0;
-
- cnt = !cnt;
-
- /* restart 4 hz timer */
- if (!timer_pending(&hfc->led_timer)) {
- add_timer(&hfc->led_timer);
- hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
- }
-}
-
/**************************/
/* handle LED requests */
/**************************/
static void
handle_led(hfcusb_data * hfc, int event)
{
+ hfcsusb_vdata *driver_info =
+ (hfcsusb_vdata *) hfcusb_idtab[hfc->vend_idx].driver_info;
+
/* if no scheme -> no LED action */
- if (vdata[hfc->vend_idx].led_scheme == LED_OFF)
+ if (driver_info->led_scheme == LED_OFF)
return;
switch (event) {
case LED_POWER_ON:
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[0],
+ set_led_bit(hfc, driver_info->led_bits[0],
0);
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+ set_led_bit(hfc, driver_info->led_bits[1],
1);
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
+ set_led_bit(hfc, driver_info->led_bits[2],
1);
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
+ set_led_bit(hfc, driver_info->led_bits[3],
1);
break;
case LED_POWER_OFF: /* no Power off handling */
break;
case LED_S0_ON:
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+ set_led_bit(hfc, driver_info->led_bits[1],
0);
break;
case LED_S0_OFF:
- set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+ set_led_bit(hfc, driver_info->led_bits[1],
1);
break;
case LED_B1_ON:
- hfc->led_b_active |= 1;
+ set_led_bit(hfc, driver_info->led_bits[2],
+ 0);
break;
case LED_B1_OFF:
- hfc->led_b_active &= ~1;
- break;
- case LED_B1_DATA:
- hfc->led_new_data |= 1;
+ set_led_bit(hfc, driver_info->led_bits[2],
+ 1);
break;
case LED_B2_ON:
- hfc->led_b_active |= 2;
+ set_led_bit(hfc, driver_info->led_bits[3],
+ 0);
break;
case LED_B2_OFF:
- hfc->led_b_active &= ~2;
- break;
- case LED_B2_DATA:
- hfc->led_new_data |= 2;
+ set_led_bit(hfc, driver_info->led_bits[3],
+ 1);
break;
}
-
write_led(hfc, hfc->led_state);
}
@@ -725,14 +691,6 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
current_len + 1;
tx_offset += (current_len + 1);
- if (!transp_mode) {
- if (fifon == HFCUSB_B1_TX)
- handle_led(hfc,
- LED_B1_DATA);
- if (fifon == HFCUSB_B2_TX)
- handle_led(hfc,
- LED_B2_DATA);
- }
} else {
urb->iso_frame_desc[k].offset =
tx_offset++;
@@ -966,14 +924,6 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
skb_trim(fifo->skbuff, 0);
}
}
-
- /* LED flashing only in HDLC mode */
- if (!transp_mode) {
- if (fifon == HFCUSB_B1_RX)
- handle_led(hfc, LED_B1_DATA);
- if (fifon == HFCUSB_B2_RX)
- handle_led(hfc, LED_B2_DATA);
- }
}
/***********************************************/
@@ -1339,17 +1289,6 @@ usb_init(hfcusb_data * hfc)
hfc->t4_timer.data = (long) hfc;
hfc->t4_timer.function = (void *) l1_timer_expire_t4;
- /* init the led timer */
- init_timer(&hfc->led_timer);
- hfc->led_timer.data = (long) hfc;
- hfc->led_timer.function = (void *) led_timer;
-
- /* trigger 4 hz led timer */
- if (!timer_pending(&hfc->led_timer)) {
- hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
- add_timer(&hfc->led_timer);
- }
-
/* init the background machinery for control requests */
hfc->ctrl_read.bRequestType = 0xc0;
hfc->ctrl_read.bRequest = 1;
@@ -1440,13 +1379,18 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
attr, cfg_found, cidx, ep_addr;
int cmptbl[16], small_match, iso_packet_size, packet_size,
alt_used = 0;
+ hfcsusb_vdata *driver_info;
vend_idx = 0xffff;
- for (i = 0; vdata[i].vendor; i++) {
- if (dev->descriptor.idVendor == vdata[i].vendor
- && dev->descriptor.idProduct == vdata[i].prod_id)
+ for (i = 0; hfcusb_idtab[i].idVendor; i++) {
+ if (dev->descriptor.idVendor == hfcusb_idtab[i].idVendor
+ && dev->descriptor.idProduct ==
+ hfcusb_idtab[i].idProduct) {
vend_idx = i;
+ continue;
+ }
}
+
#ifdef CONFIG_HISAX_DEBUG
DBG(USB_DBG,
"HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum,
@@ -1457,10 +1401,6 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
ifnum, iface->desc.bAlternateSetting, intf->minor);
if (vend_idx != 0xffff) {
-#ifdef CONFIG_HISAX_DEBUG
- DBG(USB_DBG, "HFC-S USB: found vendor idx:%d name:%s",
- vend_idx, vdata[vend_idx].vend_name);
-#endif
/* if vendor and product ID is OK, start probing alternate settings */
alt_idx = 0;
small_match = 0xffff;
@@ -1687,9 +1627,11 @@ hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_sndctrlpipe(context->dev, 0);
context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
- printk(KERN_INFO
- "HFC-S USB: detected \"%s\"\n",
- vdata[vend_idx].vend_name);
+ driver_info =
+ (hfcsusb_vdata *) hfcusb_idtab[vend_idx].
+ driver_info;
+ printk(KERN_INFO "HFC-S USB: detected \"%s\"\n",
+ driver_info->vend_name);
#ifdef CONFIG_HISAX_DEBUG
DBG(USB_DBG,
"HFC-S USB: Endpoint-Config: %s (if=%d alt=%d)\n",
@@ -1740,8 +1682,6 @@ hfc_usb_disconnect(struct usb_interface
del_timer(&context->t3_timer);
if (timer_pending(&context->t4_timer))
del_timer(&context->t4_timer);
- if (timer_pending(&context->led_timer))
- del_timer(&context->led_timer);
/* tell all fifos to terminate */
for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
if (context->fifos[i].usb_transfer_mode == USB_ISOC) {
@@ -1785,9 +1725,11 @@ hfc_usb_disconnect(struct usb_interface
/* our driver information structure */
/************************************/
static struct usb_driver hfc_drv = {
- .owner = THIS_MODULE,.name =
- "hfc_usb",.id_table = hfc_usb_idtab,.probe =
- hfc_usb_probe,.disconnect = hfc_usb_disconnect,
+ .owner = THIS_MODULE,
+ .name = "hfc_usb",
+ .id_table = hfcusb_idtab,
+ .probe = hfc_usb_probe,
+ .disconnect = hfc_usb_disconnect,
};
static void __exit
hfc_usb_exit(void)
@@ -1825,4 +1767,4 @@ module_exit(hfc_usb_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
+MODULE_DEVICE_TABLE(usb, hfcusb_idtab);
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
index 280dd29b30d6..ec52c1a7c22a 100644
--- a/drivers/isdn/hisax/hfc_usb.h
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -1,7 +1,7 @@
/*
* hfc_usb.h
*
-* $Id: hfc_usb.h,v 4.1 2005/01/26 17:25:53 martinb1 Exp $
+* $Id: hfc_usb.h,v 4.2 2005/04/07 15:27:17 martinb1 Exp $
*/
#ifndef __HFC_USB_H__
@@ -91,7 +91,7 @@
/**********/
/* macros */
/**********/
-#define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
+#define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT)
#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
@@ -186,6 +186,7 @@ static int validconf[][19] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // EOL element
};
+#ifdef CONFIG_HISAX_DEBUG
// string description of chosen config
static char *conf_str[] = {
"4 Interrupt IN + 3 Isochron OUT",
@@ -193,6 +194,7 @@ static char *conf_str[] = {
"4 Isochron IN + 3 Isochron OUT",
"3 Isochron IN + 3 Isochron OUT"
};
+#endif
typedef struct {
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
index 66dbaee77bfb..c8f9951f7914 100644
--- a/drivers/isdn/hisax/hscx.c
+++ b/drivers/isdn/hisax/hscx.c
@@ -156,14 +156,10 @@ close_hscxstate(struct BCState *bcs)
{
modehscx(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (bcs->hw.hscx.rcvbuf) {
- kfree(bcs->hw.hscx.rcvbuf);
- bcs->hw.hscx.rcvbuf = NULL;
- }
- if (bcs->blog) {
- kfree(bcs->blog);
- bcs->blog = NULL;
- }
+ kfree(bcs->hw.hscx.rcvbuf);
+ bcs->hw.hscx.rcvbuf = NULL;
+ kfree(bcs->blog);
+ bcs->blog = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index b4ca5859b177..c615752b96aa 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -571,14 +571,10 @@ setstack_icc(struct PStack *st, struct IsdnCardState *cs)
static void
DC_Close_icc(struct IsdnCardState *cs) {
- if (cs->dc.icc.mon_rx) {
- kfree(cs->dc.icc.mon_rx);
- cs->dc.icc.mon_rx = NULL;
- }
- if (cs->dc.icc.mon_tx) {
- kfree(cs->dc.icc.mon_tx);
- cs->dc.icc.mon_tx = NULL;
- }
+ kfree(cs->dc.icc.mon_rx);
+ cs->dc.icc.mon_rx = NULL;
+ kfree(cs->dc.icc.mon_tx);
+ cs->dc.icc.mon_tx = NULL;
}
static void
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
index efba2f448017..2e9afae1254a 100644
--- a/drivers/isdn/hisax/ipacx.c
+++ b/drivers/isdn/hisax/ipacx.c
@@ -762,14 +762,10 @@ bch_close_state(struct BCState *bcs)
{
bch_mode(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (bcs->hw.hscx.rcvbuf) {
- kfree(bcs->hw.hscx.rcvbuf);
- bcs->hw.hscx.rcvbuf = NULL;
- }
- if (bcs->blog) {
- kfree(bcs->blog);
- bcs->blog = NULL;
- }
+ kfree(bcs->hw.hscx.rcvbuf);
+ bcs->hw.hscx.rcvbuf = NULL;
+ kfree(bcs->blog);
+ bcs->blog = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 85e063a08d23..565b7892c267 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -570,15 +570,12 @@ setstack_isac(struct PStack *st, struct IsdnCardState *cs)
}
static void
-DC_Close_isac(struct IsdnCardState *cs) {
- if (cs->dc.isac.mon_rx) {
- kfree(cs->dc.isac.mon_rx);
- cs->dc.isac.mon_rx = NULL;
- }
- if (cs->dc.isac.mon_tx) {
- kfree(cs->dc.isac.mon_tx);
- cs->dc.isac.mon_tx = NULL;
- }
+DC_Close_isac(struct IsdnCardState *cs)
+{
+ kfree(cs->dc.isac.mon_rx);
+ cs->dc.isac.mon_rx = NULL;
+ kfree(cs->dc.isac.mon_tx);
+ cs->dc.isac.mon_tx = NULL;
}
static void
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index 642a87c51295..674af673ff96 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -1688,10 +1688,8 @@ close_isarstate(struct BCState *bcs)
{
modeisar(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (bcs->hw.isar.rcvbuf) {
- kfree(bcs->hw.isar.rcvbuf);
- bcs->hw.isar.rcvbuf = NULL;
- }
+ kfree(bcs->hw.isar.rcvbuf);
+ bcs->hw.isar.rcvbuf = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index 363ae3179bbd..2659fecc2674 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -195,14 +195,10 @@ close_jadestate(struct BCState *bcs)
{
modejade(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (bcs->hw.hscx.rcvbuf) {
- kfree(bcs->hw.hscx.rcvbuf);
- bcs->hw.hscx.rcvbuf = NULL;
- }
- if (bcs->blog) {
- kfree(bcs->blog);
- bcs->blog = NULL;
- }
+ kfree(bcs->hw.hscx.rcvbuf);
+ bcs->hw.hscx.rcvbuf = NULL;
+ kfree(bcs->blog);
+ bcs->blog = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index 94da03c30c51..47a47ef0968b 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -855,14 +855,10 @@ close_tigerstate(struct BCState *bcs)
{
mode_tiger(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (bcs->hw.tiger.rcvbuf) {
- kfree(bcs->hw.tiger.rcvbuf);
- bcs->hw.tiger.rcvbuf = NULL;
- }
- if (bcs->hw.tiger.sendbuf) {
- kfree(bcs->hw.tiger.sendbuf);
- bcs->hw.tiger.sendbuf = NULL;
- }
+ kfree(bcs->hw.tiger.rcvbuf);
+ bcs->hw.tiger.rcvbuf = NULL;
+ kfree(bcs->hw.tiger.sendbuf);
+ bcs->hw.tiger.sendbuf = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
@@ -967,20 +963,12 @@ inittiger(struct IsdnCardState *cs)
static void
releasetiger(struct IsdnCardState *cs)
{
- if (cs->bcs[0].hw.tiger.send) {
- kfree(cs->bcs[0].hw.tiger.send);
- cs->bcs[0].hw.tiger.send = NULL;
- }
- if (cs->bcs[1].hw.tiger.send) {
- cs->bcs[1].hw.tiger.send = NULL;
- }
- if (cs->bcs[0].hw.tiger.rec) {
- kfree(cs->bcs[0].hw.tiger.rec);
- cs->bcs[0].hw.tiger.rec = NULL;
- }
- if (cs->bcs[1].hw.tiger.rec) {
- cs->bcs[1].hw.tiger.rec = NULL;
- }
+ kfree(cs->bcs[0].hw.tiger.send);
+ cs->bcs[0].hw.tiger.send = NULL;
+ cs->bcs[1].hw.tiger.send = NULL;
+ kfree(cs->bcs[0].hw.tiger.rec);
+ cs->bcs[0].hw.tiger.rec = NULL;
+ cs->bcs[1].hw.tiger.rec = NULL;
}
void
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 89fbeb58485d..b096b64b0253 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -335,14 +335,12 @@ void st5481_release_usb(struct st5481_adapter *adapter)
// Stop and free Control and Interrupt URBs
usb_kill_urb(ctrl->urb);
- if (ctrl->urb->transfer_buffer)
- kfree(ctrl->urb->transfer_buffer);
+ kfree(ctrl->urb->transfer_buffer);
usb_free_urb(ctrl->urb);
ctrl->urb = NULL;
usb_kill_urb(intr->urb);
- if (intr->urb->transfer_buffer)
- kfree(intr->urb->transfer_buffer);
+ kfree(intr->urb->transfer_buffer);
usb_free_urb(intr->urb);
ctrl->urb = NULL;
}
@@ -457,8 +455,7 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
err:
for (j = 0; j < 2; j++) {
if (urb[j]) {
- if (urb[j]->transfer_buffer)
- kfree(urb[j]->transfer_buffer);
+ kfree(urb[j]->transfer_buffer);
urb[j]->transfer_buffer = NULL;
usb_free_urb(urb[j]);
urb[j] = NULL;
@@ -473,8 +470,7 @@ void st5481_release_isocpipes(struct urb* urb[2])
for (j = 0; j < 2; j++) {
usb_kill_urb(urb[j]);
- if (urb[j]->transfer_buffer)
- kfree(urb[j]->transfer_buffer);
+ kfree(urb[j]->transfer_buffer);
usb_free_urb(urb[j]);
urb[j] = NULL;
}
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index 7baf8e488471..0352ee5f706c 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -819,14 +819,10 @@ close_w6692state(struct BCState *bcs)
{
W6692Bmode(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
- if (bcs->hw.w6692.rcvbuf) {
- kfree(bcs->hw.w6692.rcvbuf);
- bcs->hw.w6692.rcvbuf = NULL;
- }
- if (bcs->blog) {
- kfree(bcs->blog);
- bcs->blog = NULL;
- }
+ kfree(bcs->hw.w6692.rcvbuf);
+ bcs->hw.w6692.rcvbuf = NULL;
+ kfree(bcs->blog);
+ bcs->blog = NULL;
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
if (bcs->tx_skb) {
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
index 639582f61f41..87f59a0e2a95 100644
--- a/drivers/isdn/hysdn/hysdn_procconf.c
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -359,8 +359,7 @@ hysdn_conf_close(struct inode *ino, struct file *filep)
} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
/* read access -> output card info data */
- if (filep->private_data)
- kfree(filep->private_data); /* release memory */
+ kfree(filep->private_data); /* release memory */
}
unlock_kernel();
return (retval);
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index d97a9be5469c..1a19a0f89428 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -364,10 +364,8 @@ isdn_ppp_release(int min, struct file *file)
isdn_net_hangup(&p->dev);
}
for (i = 0; i < NUM_RCV_BUFFS; i++) {
- if (is->rq[i].buf) {
- kfree(is->rq[i].buf);
- is->rq[i].buf = NULL;
- }
+ kfree(is->rq[i].buf);
+ is->rq[i].buf = NULL;
}
is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
is->last = is->rq;
@@ -378,14 +376,10 @@ isdn_ppp_release(int min, struct file *file)
is->slcomp = NULL;
#endif
#ifdef CONFIG_IPPP_FILTER
- if (is->pass_filter) {
- kfree(is->pass_filter);
- is->pass_filter = NULL;
- }
- if (is->active_filter) {
- kfree(is->active_filter);
- is->active_filter = NULL;
- }
+ kfree(is->pass_filter);
+ is->pass_filter = NULL;
+ kfree(is->active_filter);
+ is->active_filter = NULL;
#endif
/* TODO: if this was the previous master: link the stuff to the new master */
@@ -914,8 +908,7 @@ isdn_ppp_cleanup(void)
kfree(ippp_table[i]);
#ifdef CONFIG_ISDN_MPP
- if (isdn_ppp_bundle_arr)
- kfree(isdn_ppp_bundle_arr);
+ kfree(isdn_ppp_bundle_arr);
#endif /* CONFIG_ISDN_MPP */
}
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index b37ef1f06b3d..8c404b4e2482 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -712,22 +712,14 @@ isdn_tty_modem_hup(modem_info * info, int local)
#endif
info->emu.vpar[4] = 0;
info->emu.vpar[5] = 8;
- if (info->dtmf_state) {
- kfree(info->dtmf_state);
- info->dtmf_state = NULL;
- }
- if (info->silence_state) {
- kfree(info->silence_state);
- info->silence_state = NULL;
- }
- if (info->adpcms) {
- kfree(info->adpcms);
- info->adpcms = NULL;
- }
- if (info->adpcmr) {
- kfree(info->adpcmr);
- info->adpcmr = NULL;
- }
+ kfree(info->dtmf_state);
+ info->dtmf_state = NULL;
+ kfree(info->silence_state);
+ info->silence_state = NULL;
+ kfree(info->adpcms);
+ info->adpcms = NULL;
+ kfree(info->adpcmr);
+ info->adpcmr = NULL;
#endif
if ((info->msr & UART_MSR_RI) &&
(info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
@@ -1721,8 +1713,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
*/
timeout = jiffies + HZ;
while (!(info->lsr & UART_LSR_TEMT)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(20);
+ schedule_timeout_interruptible(20);
if (time_after(jiffies,timeout))
break;
}
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 386df71eee74..6649f8bc9951 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -947,8 +947,7 @@ icn_loadproto(u_char __user * buffer, icn_card * card)
icn_maprelease_channel(card, 0);
return -EIO;
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(10);
+ schedule_timeout_interruptible(10);
}
}
writeb(0x20, &sbuf_n);
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index 14e1f8fbc61f..33d339700411 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -1161,12 +1161,9 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card)
if (a) {
if (!card->leased) {
card->leased = 1;
- while (card->ptype == ISDN_PTYPE_UNKNOWN) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(10);
- }
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(10);
+ while (card->ptype == ISDN_PTYPE_UNKNOWN)
+ schedule_timeout_interruptible(10);
+ schedule_timeout_interruptible(10);
sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n");
i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
printk(KERN_INFO
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index 5de861f40816..94f21486bb24 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -561,10 +561,8 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg,
else
pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL);
- if (cbdata.data.setup.CalledPN)
- kfree(cbdata.data.setup.CalledPN);
- if (cbdata.data.setup.CallingPN)
- kfree(cbdata.data.setup.CallingPN);
+ kfree(cbdata.data.setup.CalledPN);
+ kfree(cbdata.data.setup.CallingPN);
break;
case MSG_CONN_CONF:
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 1ebed041672d..62b7acfad8a4 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -529,8 +529,7 @@ static int identify_board(unsigned long rambase, unsigned int iobase)
*/
x = 0;
while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
x++;
}
if(x == 100) {
diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c
index ca204da3257d..0a0fe6b8039b 100644
--- a/drivers/isdn/sc/message.c
+++ b/drivers/isdn/sc/message.c
@@ -208,8 +208,7 @@ int send_and_receive(int card,
tries = 0;
/* wait for the response */
while (tries < timeout) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
pr_debug("SAR waiting..\n");
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 8f02c155fdc0..c0b46bceb5df 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -857,8 +857,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
static void adbhid_input_unregister(int id)
{
input_unregister_device(adbhid[id]->input);
- if (adbhid[id]->keycode)
- kfree(adbhid[id]->keycode);
+ kfree(adbhid[id]->keycode);
kfree(adbhid[id]);
adbhid[id] = NULL;
}
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index cc507ceef153..3fc8cdd94c3d 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -1678,10 +1678,9 @@ static int main_control_loop(void *x)
}
// FIXME: Deal with signals
- set_current_state(TASK_INTERRUPTIBLE);
elapsed = jiffies - start;
if (elapsed < HZ)
- schedule_timeout(HZ - elapsed);
+ schedule_timeout_interruptible(HZ - elapsed);
}
out:
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 6497295ebfb9..1223e98ecd70 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1587,8 +1587,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
/* make sure we don't swamp the stripe cache if someone else
* is trying to get access
*/
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 6437a95ffc1c..775786947701 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1746,8 +1746,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
/* make sure we don't swamp the stripe cache if someone else
* is trying to get access
*/
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 34a837a1abf4..b3c9d7327ac1 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1331,9 +1331,7 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
{
/* check if the ASIC is there */
if (dst_probe(state) < 0) {
- if (state)
- kfree(state);
-
+ kfree(state);
return NULL;
}
/* determine settings based on type */
@@ -1349,9 +1347,7 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad
break;
default:
dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
- if (state)
- kfree(state);
-
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index d4b97989e3ed..654d7dc879d9 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include "dvb_frontend.h"
#include "cx24110.h"
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index 794be520d590..645946a992d9 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -148,7 +148,7 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
@@ -171,7 +171,7 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach()
return &state->frontend;
error:
- if (state) kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index faaad1ae8559..19b4bf7c21a7 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -559,7 +559,8 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
return &state->frontend;
error:
- if (reg0x3e >= 0) l64781_writereg (state, 0x3e, reg0x3e); /* restore reg 0x3e */
+ if (reg0x3e >= 0)
+ l64781_writereg (state, 0x3e, reg0x3e); /* restore reg 0x3e */
kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 8dde72bd1046..7852b83b82d4 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -731,8 +731,7 @@ struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
dprintk("%s: ERROR\n",__FUNCTION__);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index e38454901dd1..9c67f406d581 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -677,8 +677,7 @@ struct dvb_frontend* mt312_attach(const struct mt312_config* config,
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 817b044c7fd1..fc74c40d6477 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -577,8 +577,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
return &state->frontend;
error:
- if (state)
- kfree(state);
+ kfree(state);
return NULL;
}
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index 87fd3a7bb392..0823ddaf7004 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -865,10 +865,8 @@ out_dev:
out_irq:
#endif
- for (i = 0; i < MAX_AR_HEIGHT; i++) {
- if (ar->frame[i])
- kfree(ar->frame[i]);
- }
+ for (i = 0; i < MAX_AR_HEIGHT; i++)
+ kfree(ar->frame[i]);
out_line_buff:
#if USE_INT
@@ -899,10 +897,8 @@ static void __exit ar_cleanup_module(void)
#if USE_INT
free_irq(M32R_IRQ_INT3, ar);
#endif
- for (i = 0; i < MAX_AR_HEIGHT; i++) {
- if (ar->frame[i])
- kfree(ar->frame[i]);
- }
+ for (i = 0; i < MAX_AR_HEIGHT; i++)
+ kfree(ar->frame[i]);
#if USE_INT
kfree(ar->line_buff);
#endif
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index c062a017491e..d538a994ff04 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1951,8 +1951,7 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
}
down(&fh->cap.lock);
- if (fh->ov.clips)
- kfree(fh->ov.clips);
+ kfree(fh->ov.clips);
fh->ov.clips = clips;
fh->ov.nclips = n;
@@ -2723,8 +2722,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file,
fh->ov.w.height = fb->fmt.height;
btv->init.ov.w.width = fb->fmt.width;
btv->init.ov.w.height = fb->fmt.height;
- if (fh->ov.clips)
- kfree(fh->ov.clips);
+ kfree(fh->ov.clips);
fh->ov.clips = NULL;
fh->ov.nclips = 0;
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 262890cb20a7..e75e7948fd9d 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -741,8 +741,8 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
set_current_state(TASK_INTERRUPTIBLE);
schedule();
} else {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(timeout));
+ schedule_timeout_interruptible
+ (msecs_to_jiffies(timeout));
}
}
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index badf2f9e3072..61a2d6b50eef 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -342,8 +342,8 @@ static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
set_current_state(TASK_INTERRUPTIBLE);
schedule();
} else {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(timeout));
+ schedule_timeout_interruptible
+ (msecs_to_jiffies(timeout));
}
}
remove_wait_queue(&dev->thread.wq, &wait);
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 59bb71381a1b..d679ca23ded7 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -1006,10 +1006,8 @@ v4l_compat_translate_ioctl(struct inode *inode,
break;
}
- if (cap2)
- kfree(cap2);
- if (fmt2)
- kfree(fmt2);
+ kfree(cap2);
+ kfree(fmt2);
return err;
}
diff --git a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c
index c9d5f1a873cc..839db622040d 100644
--- a/drivers/media/video/videocodec.c
+++ b/drivers/media/video/videocodec.c
@@ -353,8 +353,7 @@ videocodec_build_table (void)
dprintk(3, "videocodec_build table: %d entries, %d bytes\n", i,
size);
- if (videocodec_buf)
- kfree(videocodec_buf);
+ kfree(videocodec_buf);
videocodec_buf = (char *) kmalloc(size, GFP_KERNEL);
i = 0;
@@ -471,8 +470,7 @@ videocodec_exit (void)
{
#ifdef CONFIG_PROC_FS
remove_proc_entry("videocodecs", NULL);
- if (videocodec_buf)
- kfree(videocodec_buf);
+ kfree(videocodec_buf);
#endif
}
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 06df15f75de9..83c49f9610d0 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -215,8 +215,7 @@ video_usercopy(struct inode *inode, struct file *file,
}
out:
- if (mbuf)
- kfree(mbuf);
+ kfree(mbuf);
return err;
}
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index eed2acea1779..39a0d238900e 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -1057,10 +1057,8 @@ zr36057_init (struct zoran *zr)
KERN_ERR
"%s: zr36057_init() - kmalloc (STAT_COM) failed\n",
ZR_DEVNAME(zr));
- if (vdev)
- kfree(vdev);
- if (mem)
- kfree((void *)mem);
+ kfree(vdev);
+ kfree((void *)mem);
return -ENOMEM;
}
memset((void *) mem, 0, mem_needed);
@@ -1105,15 +1103,15 @@ zoran_release (struct zoran *zr)
/* unregister videocodec bus */
if (zr->codec) {
struct videocodec_master *master = zr->codec->master_data;
+
videocodec_detach(zr->codec);
- if (master)
- kfree(master);
+ kfree(master);
}
if (zr->vfe) {
struct videocodec_master *master = zr->vfe->master_data;
+
videocodec_detach(zr->vfe);
- if (master)
- kfree(master);
+ kfree(master);
}
/* unregister i2c bus */
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 53adeb70f2ca..07bde9acd672 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -996,8 +996,6 @@ zoran_jpg_queue_frame (struct file *file,
return -EINVAL;
}
- spin_lock_irqsave(&zr->spinlock, flags);
-
if (fh->jpg_buffers.active == ZORAN_FREE) {
if (zr->jpg_buffers.active == ZORAN_FREE) {
zr->jpg_buffers = fh->jpg_buffers;
@@ -1016,6 +1014,8 @@ zoran_jpg_queue_frame (struct file *file,
zr36057_enable_jpg(zr, mode);
}
+ spin_lock_irqsave(&zr->spinlock, flags);
+
if (!res) {
switch (zr->jpg_buffers.buffer[num].state) {
case BUZ_STATE_DONE:
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index ed3c891e388f..014085d8ec85 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -511,7 +511,7 @@ mpt_lan_close(struct net_device *dev)
{
struct mpt_lan_priv *priv = netdev_priv(dev);
MPT_ADAPTER *mpt_dev = priv->mpt_dev;
- unsigned int timeout;
+ unsigned long timeout;
int i;
dlprintk((KERN_INFO MYNAM ": mpt_lan_close called\n"));
@@ -526,11 +526,9 @@ mpt_lan_close(struct net_device *dev)
mpt_lan_reset(dev);
- timeout = 2 * HZ;
- while (atomic_read(&priv->buckets_out) && --timeout) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ timeout = jiffies + 2 * HZ;
+ while (atomic_read(&priv->buckets_out) && time_before(jiffies, timeout))
+ schedule_timeout_interruptible(1);
for (i = 0; i < priv->max_buckets_out; i++) {
if (priv->RcvCtl[i].skb != NULL) {
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 5cb07eb224d7..4330ed0cedaa 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1013,10 +1013,8 @@ mptscsih_remove(struct pci_dev *pdev)
spin_lock_irqsave(&dvtaskQ_lock, flags);
if (dvtaskQ_active) {
spin_unlock_irqrestore(&dvtaskQ_lock, flags);
- while(dvtaskQ_active && --count) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
+ while(dvtaskQ_active && --count)
+ schedule_timeout_interruptible(1);
} else {
spin_unlock_irqrestore(&dvtaskQ_lock, flags);
}
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index b675b4ebbebd..9c339a2505b0 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -33,6 +33,7 @@
#include <linux/workqueue.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */
#include <asm/param.h> /* HZ */
#include "core.h"
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 61b837de4b6a..4eb53258842e 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -93,8 +93,7 @@ u32 i2o_msg_get_wait(struct i2o_controller *c,
c->name);
return I2O_QUEUE_EMPTY;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
return m;
@@ -485,8 +484,7 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
osm_warn("%s: Timeout Initializing\n", c->name);
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
m = c->out_queue.phys;
@@ -548,8 +546,7 @@ static int i2o_iop_reset(struct i2o_controller *c)
if (time_after(jiffies, timeout))
break;
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
switch (*status) {
@@ -577,8 +574,7 @@ static int i2o_iop_reset(struct i2o_controller *c)
rc = -ETIMEDOUT;
goto exit;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
}
@@ -989,8 +985,7 @@ int i2o_status_get(struct i2o_controller *c)
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
#ifdef DEBUG
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index c75d713c01e4..55ba23075c90 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -15,6 +15,8 @@
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
#include <asm/dma.h>
#include <asm/system.h>
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 4ff67e7363d9..e954b8354fef 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -1602,8 +1602,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
if (host->dma_addr)
dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
DMA_BIDIRECTIONAL);
- if (host->dma_buffer)
- kfree(host->dma_buffer);
+ kfree(host->dma_buffer);
if (host->dma >= 0)
free_dma(host->dma);
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 0cfcd88468e0..c3fc9b2f21fb 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -455,8 +455,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
setup_err:
if(mtd) {
- if(mtd->eraseregions)
- kfree(mtd->eraseregions);
+ kfree(mtd->eraseregions);
kfree(mtd);
}
kfree(cfi->cmdset_priv);
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 8505f118f2db..0e6475050da9 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -378,8 +378,7 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
setup_err:
if(mtd) {
- if(mtd->eraseregions)
- kfree(mtd->eraseregions);
+ kfree(mtd->eraseregions);
kfree(mtd);
}
kfree(cfi->cmdset_priv);
@@ -1742,6 +1741,7 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
+
kfree(cfi->cmdset_priv);
kfree(cfi->cfiq);
kfree(cfi);
diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c
index 662e807801ed..59a29e616a22 100644
--- a/drivers/mtd/devices/blkmtd.c
+++ b/drivers/mtd/devices/blkmtd.c
@@ -539,11 +539,8 @@ static void free_device(struct blkmtd_dev *dev)
{
DEBUG(2, "blkmtd: free_device() dev = %p\n", dev);
if(dev) {
- if(dev->mtd_info.eraseregions)
- kfree(dev->mtd_info.eraseregions);
- if(dev->mtd_info.name)
- kfree(dev->mtd_info.name);
-
+ kfree(dev->mtd_info.eraseregions);
+ kfree(dev->mtd_info.name);
if(dev->blkdev) {
invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping);
close_bdev_excl(dev->blkdev);
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index 39eb53f6551f..8db65bf029ea 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -126,10 +126,8 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
}
if (add_mtd_blktrans_dev(&inftl->mbd)) {
- if (inftl->PUtable)
- kfree(inftl->PUtable);
- if (inftl->VUtable)
- kfree(inftl->VUtable);
+ kfree(inftl->PUtable);
+ kfree(inftl->VUtable);
kfree(inftl);
return;
}
@@ -147,10 +145,8 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
del_mtd_blktrans_dev(dev);
- if (inftl->PUtable)
- kfree(inftl->PUtable);
- if (inftl->VUtable)
- kfree(inftl->VUtable);
+ kfree(inftl->PUtable);
+ kfree(inftl->VUtable);
kfree(inftl);
}
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index b5dda47395a7..3dac53feeee2 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -574,6 +574,12 @@ int INFTL_mount(struct INFTLrecord *s)
/* Temporary buffer to store ANAC numbers. */
ANACtable = kmalloc(s->nb_blocks * sizeof(u8), GFP_KERNEL);
+ if (!ANACtable) {
+ printk(KERN_WARNING "INFTL: allocation of ANACtable "
+ "failed (%zd bytes)\n",
+ s->nb_blocks * sizeof(u8));
+ return -ENOMEM;
+ }
memset(ANACtable, 0, s->nb_blocks);
/*
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index e8a900a77685..9a64149f431d 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -259,9 +259,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
out:
/* Free any left over map structures */
- if (map) {
- kfree(map);
- }
+ kfree(map);
/* See if I have any map structures */
if (list_empty(&window->maps)) {
amd76xrom_cleanup(window);
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c
index bfe994e59265..8c19d722ac79 100644
--- a/drivers/mtd/maps/bast-flash.c
+++ b/drivers/mtd/maps/bast-flash.c
@@ -104,8 +104,7 @@ static int bast_flash_remove(struct device *dev)
map_destroy(info->mtd);
}
- if (info->partitions)
- kfree(info->partitions);
+ kfree(info->partitions);
if (info->area) {
release_resource(info->area);
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index c68b31dc7e6d..5a95ab370a97 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -313,8 +313,7 @@ static void __init clps_locate_partitions(struct mtd_info *mtd)
static void __exit clps_destroy_partitions(void)
{
- if (parsed_parts)
- kfree(parsed_parts);
+ kfree(parsed_parts);
}
static struct mtd_info *mymtd;
diff --git a/drivers/mtd/maps/ichxrom.c b/drivers/mtd/maps/ichxrom.c
index e505207cd489..c5e2111ba146 100644
--- a/drivers/mtd/maps/ichxrom.c
+++ b/drivers/mtd/maps/ichxrom.c
@@ -306,9 +306,8 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev,
out:
/* Free any left over map structures */
- if (map) {
- kfree(map);
- }
+ kfree(map);
+
/* See if I have any map structures */
if (list_empty(&window->maps)) {
ichxrom_cleanup(window);
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index d14a0185b8f4..93f50d6d5488 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -148,8 +148,7 @@ static int armflash_probe(struct device *_dev)
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
- if (info->parts)
- kfree(info->parts);
+ kfree(info->parts);
no_device:
iounmap(base);
@@ -176,8 +175,7 @@ static int armflash_remove(struct device *_dev)
del_mtd_partitions(info->mtd);
map_destroy(info->mtd);
}
- if (info->parts)
- kfree(info->parts);
+ kfree(info->parts);
iounmap(info->map.virt);
release_resource(info->res);
diff --git a/drivers/mtd/maps/ipaq-flash.c b/drivers/mtd/maps/ipaq-flash.c
index 712401810841..70b0e0b82c34 100644
--- a/drivers/mtd/maps/ipaq-flash.c
+++ b/drivers/mtd/maps/ipaq-flash.c
@@ -431,8 +431,7 @@ static void __exit ipaq_mtd_cleanup(void)
if (my_sub_mtd[i])
map_destroy(my_sub_mtd[i]);
}
- if (parsed_parts)
- kfree(parsed_parts);
+ kfree(parsed_parts);
}
}
diff --git a/drivers/mtd/maps/iq80310.c b/drivers/mtd/maps/iq80310.c
index 558d014e7acc..2e7577492a2c 100644
--- a/drivers/mtd/maps/iq80310.c
+++ b/drivers/mtd/maps/iq80310.c
@@ -103,8 +103,7 @@ static void __exit cleanup_iq80310(void)
if (mymtd) {
del_mtd_partitions(mymtd);
map_destroy(mymtd);
- if (parsed_parts)
- kfree(parsed_parts);
+ kfree(parsed_parts);
}
if (iq80310_map.virt)
iounmap((void *)iq80310_map.virt);
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index 00b9f67580f1..6f36497022d1 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -129,8 +129,7 @@ static int ixp2000_flash_remove(struct device *_dev)
if (info->map.map_priv_1)
iounmap((void *) info->map.map_priv_1);
- if (info->partitions) {
- kfree(info->partitions); }
+ kfree(info->partitions);
if (info->res) {
release_resource(info->res);
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 733a9297a562..0d87c02dee04 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -124,8 +124,7 @@ static int ixp4xx_flash_remove(struct device *_dev)
if (info->map.map_priv_1)
iounmap((void *) info->map.map_priv_1);
- if (info->partitions)
- kfree(info->partitions);
+ kfree(info->partitions);
if (info->res) {
release_resource(info->res);
diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
index 2337e0c46750..2b4c5058787d 100644
--- a/drivers/mtd/maps/lubbock-flash.c
+++ b/drivers/mtd/maps/lubbock-flash.c
@@ -158,8 +158,7 @@ static void __exit cleanup_lubbock(void)
if (lubbock_maps[i].cached)
iounmap(lubbock_maps[i].cached);
- if (parsed_parts[i])
- kfree(parsed_parts[i]);
+ kfree(parsed_parts[i]);
}
}
diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c
index da36e8dddd17..763304154a92 100644
--- a/drivers/mtd/maps/omap-toto-flash.c
+++ b/drivers/mtd/maps/omap-toto-flash.c
@@ -124,8 +124,7 @@ static void __exit omap_toto_mtd_cleanup(void)
if (flash_mtd) {
del_mtd_partitions(flash_mtd);
map_destroy(flash_mtd);
- if (parsed_parts)
- kfree(parsed_parts);
+ kfree(parsed_parts);
}
}
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index c8d0da19d897..a31f6ee8a4be 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -241,8 +241,7 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
#endif
}
- if (info->parts)
- kfree(info->parts);
+ kfree(info->parts);
for (i = info->num_subdev - 1; i >= 0; i--)
sa1100_destroy_subdev(&info->subdev[i]);
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 29091d10030a..1355c28f90a4 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -166,9 +166,7 @@ static void __exit uflash_cleanup(void)
iounmap(udev->map.virt);
udev->map.virt = NULL;
}
- if(0 != udev->name) {
- kfree(udev->name);
- }
+ kfree(udev->name);
kfree(udev);
}
}
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 4e28b977f224..0aca8179f27f 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -224,10 +224,8 @@ int __init init_tqm_mtd(void)
error_mem:
for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
if(map_banks[idx] != NULL) {
- if(map_banks[idx]->name != NULL) {
- kfree(map_banks[idx]->name);
- map_banks[idx]->name = NULL;
- }
+ kfree(map_banks[idx]->name);
+ map_banks[idx]->name = NULL;
kfree(map_banks[idx]);
map_banks[idx] = NULL;
}
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 04e54318bc6a..8e78d7b96a56 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2676,9 +2676,8 @@ void nand_release (struct mtd_info *mtd)
/* Deregister the device */
del_mtd_device (mtd);
- /* Free bad block table memory, if allocated */
- if (this->bbt)
- kfree (this->bbt);
+ /* Free bad block table memory */
+ kfree (this->bbt);
/* Buffer allocated by nand_scan ? */
if (this->options & NAND_OOBBUF_ALLOC)
kfree (this->oob_buf);
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index b2014043634f..062ff3877536 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -114,10 +114,8 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
}
if (add_mtd_blktrans_dev(&nftl->mbd)) {
- if (nftl->ReplUnitTable)
- kfree(nftl->ReplUnitTable);
- if (nftl->EUNtable)
- kfree(nftl->EUNtable);
+ kfree(nftl->ReplUnitTable);
+ kfree(nftl->EUNtable);
kfree(nftl);
return;
}
@@ -133,10 +131,8 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
DEBUG(MTD_DEBUG_LEVEL1, "NFTL: remove_dev (i=%d)\n", dev->devnum);
del_mtd_blktrans_dev(dev);
- if (nftl->ReplUnitTable)
- kfree(nftl->ReplUnitTable);
- if (nftl->EUNtable)
- kfree(nftl->EUNtable);
+ kfree(nftl->ReplUnitTable);
+ kfree(nftl->EUNtable);
kfree(nftl);
}
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 455ba915ede7..7488ee7f7caf 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -602,7 +602,7 @@ MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
First the windows. There are eight register windows, with the command
and status registers available in each.
*/
-#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
+#define EL3WINDOW(win_num) iowrite16(SelectWindow + (win_num), ioaddr + EL3_CMD)
#define EL3_CMD 0x0e
#define EL3_STATUS 0x0e
@@ -776,7 +776,8 @@ struct vortex_private {
/* PCI configuration space information. */
struct device *gendev;
- char __iomem *cb_fn_base; /* CardBus function status addr space. */
+ void __iomem *ioaddr; /* IO address space */
+ void __iomem *cb_fn_base; /* CardBus function status addr space. */
/* Some values here only for performance evaluation and path-coverage */
int rx_nocopy, rx_copy, queued_packet, rx_csumhits;
@@ -869,12 +870,12 @@ static struct {
/* number of ETHTOOL_GSTATS u64's */
#define VORTEX_NUM_STATS 3
-static int vortex_probe1(struct device *gendev, long ioaddr, int irq,
+static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
int chip_idx, int card_idx);
static void vortex_up(struct net_device *dev);
static void vortex_down(struct net_device *dev, int final);
static int vortex_open(struct net_device *dev);
-static void mdio_sync(long ioaddr, int bits);
+static void mdio_sync(void __iomem *ioaddr, int bits);
static int mdio_read(struct net_device *dev, int phy_id, int location);
static void mdio_write(struct net_device *vp, int phy_id, int location, int value);
static void vortex_timer(unsigned long arg);
@@ -887,7 +888,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static irqreturn_t boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int vortex_close(struct net_device *dev);
static void dump_tx_ring(struct net_device *dev);
-static void update_stats(long ioaddr, struct net_device *dev);
+static void update_stats(void __iomem *ioaddr, struct net_device *dev);
static struct net_device_stats *vortex_get_stats(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
#ifdef CONFIG_PCI
@@ -902,14 +903,16 @@ static void set_8021q_mode(struct net_device *dev, int enable);
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
/* Option count limit only -- unlimited interfaces are supported. */
#define MAX_UNITS 8
-static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int hw_checksums[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[MAX_UNITS] = { [0 ... MAX_UNITS-1] = -1 };
+static int full_duplex[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int hw_checksums[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int flow_ctrl[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int enable_wol[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
+static int use_mmio[MAX_UNITS] = {[0 ... MAX_UNITS-1] = -1 };
static int global_options = -1;
static int global_full_duplex = -1;
static int global_enable_wol = -1;
+static int global_use_mmio = -1;
/* #define dev_alloc_skb dev_alloc_skb_debug */
@@ -934,21 +937,25 @@ module_param(compaq_ioaddr, int, 0);
module_param(compaq_irq, int, 0);
module_param(compaq_device_id, int, 0);
module_param(watchdog, int, 0);
+module_param(global_use_mmio, int, 0);
+module_param_array(use_mmio, int, NULL, 0);
MODULE_PARM_DESC(debug, "3c59x debug level (0-6)");
MODULE_PARM_DESC(options, "3c59x: Bits 0-3: media type, bit 4: bus mastering, bit 9: full duplex");
MODULE_PARM_DESC(global_options, "3c59x: same as options, but applies to all NICs if options is unset");
MODULE_PARM_DESC(full_duplex, "3c59x full duplex setting(s) (1)");
-MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if full_duplex is unset");
MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)");
MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)");
MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)");
-MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if enable_wol is unset");
MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt");
MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(compaq_irq, "3c59x PCI IRQ number (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(compaq_device_id, "3c59x PCI device ID (Compaq BIOS problem workaround)");
MODULE_PARM_DESC(watchdog, "3c59x transmit timeout in milliseconds");
+MODULE_PARM_DESC(global_use_mmio, "3c59x: same as use_mmio, but applies to all NICs if options is unset");
+MODULE_PARM_DESC(use_mmio, "3c59x: use memory-mapped PCI I/O resource (0-1)");
#ifdef CONFIG_NET_POLL_CONTROLLER
static void poll_vortex(struct net_device *dev)
@@ -1029,18 +1036,19 @@ static struct eisa_driver vortex_eisa_driver = {
static int vortex_eisa_probe (struct device *device)
{
- long ioaddr;
+ void __iomem *ioaddr;
struct eisa_device *edev;
edev = to_eisa_device (device);
- ioaddr = edev->base_addr;
- if (!request_region(ioaddr, VORTEX_TOTAL_SIZE, DRV_NAME))
+ if (!request_region(edev->base_addr, VORTEX_TOTAL_SIZE, DRV_NAME))
return -EBUSY;
- if (vortex_probe1(device, ioaddr, inw(ioaddr + 0xC88) >> 12,
+ ioaddr = ioport_map(edev->base_addr, VORTEX_TOTAL_SIZE);
+
+ if (vortex_probe1(device, ioaddr, ioread16(ioaddr + 0xC88) >> 12,
edev->id.driver_data, vortex_cards_found)) {
- release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ release_region (edev->base_addr, VORTEX_TOTAL_SIZE);
return -ENODEV;
}
@@ -1054,7 +1062,7 @@ static int vortex_eisa_remove (struct device *device)
struct eisa_device *edev;
struct net_device *dev;
struct vortex_private *vp;
- long ioaddr;
+ void __iomem *ioaddr;
edev = to_eisa_device (device);
dev = eisa_get_drvdata (edev);
@@ -1065,11 +1073,11 @@ static int vortex_eisa_remove (struct device *device)
}
vp = netdev_priv(dev);
- ioaddr = dev->base_addr;
+ ioaddr = vp->ioaddr;
unregister_netdev (dev);
- outw (TotalReset|0x14, ioaddr + EL3_CMD);
- release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ iowrite16 (TotalReset|0x14, ioaddr + EL3_CMD);
+ release_region (dev->base_addr, VORTEX_TOTAL_SIZE);
free_netdev (dev);
return 0;
@@ -1096,8 +1104,8 @@ static int __init vortex_eisa_init (void)
/* Special code to work-around the Compaq PCI BIOS32 problem. */
if (compaq_ioaddr) {
- vortex_probe1(NULL, compaq_ioaddr, compaq_irq,
- compaq_device_id, vortex_cards_found++);
+ vortex_probe1(NULL, ioport_map(compaq_ioaddr, VORTEX_TOTAL_SIZE),
+ compaq_irq, compaq_device_id, vortex_cards_found++);
}
return vortex_cards_found - orig_cards_found + eisa_found;
@@ -1107,15 +1115,32 @@ static int __init vortex_eisa_init (void)
static int __devinit vortex_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- int rc;
+ int rc, unit, pci_bar;
+ struct vortex_chip_info *vci;
+ void __iomem *ioaddr;
/* wake up and enable device */
rc = pci_enable_device (pdev);
if (rc < 0)
goto out;
- rc = vortex_probe1 (&pdev->dev, pci_resource_start (pdev, 0),
- pdev->irq, ent->driver_data, vortex_cards_found);
+ unit = vortex_cards_found;
+
+ if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) {
+ /* Determine the default if the user didn't override us */
+ vci = &vortex_info_tbl[ent->driver_data];
+ pci_bar = vci->drv_flags & (IS_CYCLONE | IS_TORNADO) ? 1 : 0;
+ } else if (unit < MAX_UNITS && use_mmio[unit] >= 0)
+ pci_bar = use_mmio[unit] ? 1 : 0;
+ else
+ pci_bar = global_use_mmio ? 1 : 0;
+
+ ioaddr = pci_iomap(pdev, pci_bar, 0);
+ if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */
+ ioaddr = pci_iomap(pdev, 0, 0);
+
+ rc = vortex_probe1(&pdev->dev, ioaddr, pdev->irq,
+ ent->driver_data, unit);
if (rc < 0) {
pci_disable_device (pdev);
goto out;
@@ -1134,7 +1159,7 @@ out:
* NOTE: pdev can be NULL, for the case of a Compaq device
*/
static int __devinit vortex_probe1(struct device *gendev,
- long ioaddr, int irq,
+ void __iomem *ioaddr, int irq,
int chip_idx, int card_idx)
{
struct vortex_private *vp;
@@ -1202,15 +1227,16 @@ static int __devinit vortex_probe1(struct device *gendev,
if (print_info)
printk (KERN_INFO "See Documentation/networking/vortex.txt\n");
- printk(KERN_INFO "%s: 3Com %s %s at 0x%lx. Vers " DRV_VERSION "\n",
+ printk(KERN_INFO "%s: 3Com %s %s at %p. Vers " DRV_VERSION "\n",
print_name,
pdev ? "PCI" : "EISA",
vci->name,
ioaddr);
- dev->base_addr = ioaddr;
+ dev->base_addr = (unsigned long)ioaddr;
dev->irq = irq;
dev->mtu = mtu;
+ vp->ioaddr = ioaddr;
vp->large_frames = mtu > 1500;
vp->drv_flags = vci->drv_flags;
vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
@@ -1226,7 +1252,7 @@ static int __devinit vortex_probe1(struct device *gendev,
if (pdev) {
/* EISA resources already marked, so only PCI needs to do this here */
/* Ignore return value, because Cardbus drivers already allocate for us */
- if (request_region(ioaddr, vci->io_size, print_name) != NULL)
+ if (request_region(dev->base_addr, vci->io_size, print_name) != NULL)
vp->must_free_region = 1;
/* enable bus-mastering if necessary */
@@ -1316,14 +1342,14 @@ static int __devinit vortex_probe1(struct device *gendev,
for (i = 0; i < 0x40; i++) {
int timer;
- outw(base + i, ioaddr + Wn0EepromCmd);
+ iowrite16(base + i, ioaddr + Wn0EepromCmd);
/* Pause for at least 162 us. for the read to take place. */
for (timer = 10; timer >= 0; timer--) {
udelay(162);
- if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
+ if ((ioread16(ioaddr + Wn0EepromCmd) & 0x8000) == 0)
break;
}
- eeprom[i] = inw(ioaddr + Wn0EepromData);
+ eeprom[i] = ioread16(ioaddr + Wn0EepromData);
}
}
for (i = 0; i < 0x18; i++)
@@ -1338,6 +1364,7 @@ static int __devinit vortex_probe1(struct device *gendev,
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
if (print_info) {
for (i = 0; i < 6; i++)
printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
@@ -1351,7 +1378,7 @@ static int __devinit vortex_probe1(struct device *gendev,
}
EL3WINDOW(2);
for (i = 0; i < 6; i++)
- outb(dev->dev_addr[i], ioaddr + i);
+ iowrite8(dev->dev_addr[i], ioaddr + i);
#ifdef __sparc__
if (print_info)
@@ -1366,7 +1393,7 @@ static int __devinit vortex_probe1(struct device *gendev,
#endif
EL3WINDOW(4);
- step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
+ step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
if (print_info) {
printk(KERN_INFO " product code %02x%02x rev %02x.%d date %02d-"
"%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14],
@@ -1375,31 +1402,30 @@ static int __devinit vortex_probe1(struct device *gendev,
if (pdev && vci->drv_flags & HAS_CB_FNS) {
- unsigned long fn_st_addr; /* Cardbus function status space */
unsigned short n;
- fn_st_addr = pci_resource_start (pdev, 2);
- if (fn_st_addr) {
- vp->cb_fn_base = ioremap(fn_st_addr, 128);
+ vp->cb_fn_base = pci_iomap(pdev, 2, 0);
+ if (!vp->cb_fn_base) {
retval = -ENOMEM;
- if (!vp->cb_fn_base)
- goto free_ring;
+ goto free_ring;
}
+
if (print_info) {
printk(KERN_INFO "%s: CardBus functions mapped %8.8lx->%p\n",
- print_name, fn_st_addr, vp->cb_fn_base);
+ print_name, pci_resource_start(pdev, 2),
+ vp->cb_fn_base);
}
EL3WINDOW(2);
- n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
+ n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010;
if (vp->drv_flags & INVERT_LED_PWR)
n |= 0x10;
if (vp->drv_flags & INVERT_MII_PWR)
n |= 0x4000;
- outw(n, ioaddr + Wn2_ResetOptions);
+ iowrite16(n, ioaddr + Wn2_ResetOptions);
if (vp->drv_flags & WNO_XCVR_PWR) {
EL3WINDOW(0);
- outw(0x0800, ioaddr);
+ iowrite16(0x0800, ioaddr);
}
}
@@ -1418,13 +1444,13 @@ static int __devinit vortex_probe1(struct device *gendev,
static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
unsigned int config;
EL3WINDOW(3);
- vp->available_media = inw(ioaddr + Wn3_Options);
+ vp->available_media = ioread16(ioaddr + Wn3_Options);
if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */
vp->available_media = 0x40;
- config = inl(ioaddr + Wn3_Config);
+ config = ioread32(ioaddr + Wn3_Config);
if (print_info) {
printk(KERN_DEBUG " Internal config register is %4.4x, "
- "transceivers %#x.\n", config, inw(ioaddr + Wn3_Options));
+ "transceivers %#x.\n", config, ioread16(ioaddr + Wn3_Options));
printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
8 << RAM_SIZE(config),
RAM_WIDTH(config) ? "word" : "byte",
@@ -1455,7 +1481,7 @@ static int __devinit vortex_probe1(struct device *gendev,
if (vp->drv_flags & EXTRA_PREAMBLE)
mii_preamble_required++;
mdio_sync(ioaddr, 32);
- mdio_read(dev, 24, 1);
+ mdio_read(dev, 24, MII_BMSR);
for (phy = 0; phy < 32 && phy_idx < 1; phy++) {
int mii_status, phyx;
@@ -1469,7 +1495,7 @@ static int __devinit vortex_probe1(struct device *gendev,
phyx = phy - 1;
else
phyx = phy;
- mii_status = mdio_read(dev, phyx, 1);
+ mii_status = mdio_read(dev, phyx, MII_BMSR);
if (mii_status && mii_status != 0xffff) {
vp->phys[phy_idx++] = phyx;
if (print_info) {
@@ -1485,7 +1511,7 @@ static int __devinit vortex_probe1(struct device *gendev,
printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n");
vp->phys[0] = 24;
} else {
- vp->advertising = mdio_read(dev, vp->phys[0], 4);
+ vp->advertising = mdio_read(dev, vp->phys[0], MII_ADVERTISE);
if (vp->full_duplex) {
/* Only advertise the FD media types. */
vp->advertising &= ~0x02A0;
@@ -1510,10 +1536,10 @@ static int __devinit vortex_probe1(struct device *gendev,
if (vp->full_bus_master_tx) {
dev->hard_start_xmit = boomerang_start_xmit;
/* Actually, it still should work with iommu. */
- dev->features |= NETIF_F_SG;
- if (((hw_checksums[card_idx] == -1) && (vp->drv_flags & HAS_HWCKSM)) ||
- (hw_checksums[card_idx] == 1)) {
- dev->features |= NETIF_F_IP_CSUM;
+ if (card_idx < MAX_UNITS &&
+ ((hw_checksums[card_idx] == -1 && (vp->drv_flags & HAS_HWCKSM)) ||
+ hw_checksums[card_idx] == 1)) {
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
}
} else {
dev->hard_start_xmit = vortex_start_xmit;
@@ -1555,7 +1581,7 @@ free_ring:
vp->rx_ring_dma);
free_region:
if (vp->must_free_region)
- release_region(ioaddr, vci->io_size);
+ release_region(dev->base_addr, vci->io_size);
free_netdev(dev);
printk(KERN_ERR PFX "vortex_probe1 fails. Returns %d\n", retval);
out:
@@ -1565,17 +1591,19 @@ out:
static void
issue_and_wait(struct net_device *dev, int cmd)
{
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int i;
- outw(cmd, dev->base_addr + EL3_CMD);
+ iowrite16(cmd, ioaddr + EL3_CMD);
for (i = 0; i < 2000; i++) {
- if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress))
+ if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
return;
}
/* OK, that didn't work. Do it the slow way. One second */
for (i = 0; i < 100000; i++) {
- if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) {
+ if (!(ioread16(ioaddr + EL3_STATUS) & CmdInProgress)) {
if (vortex_debug > 1)
printk(KERN_INFO "%s: command 0x%04x took %d usecs\n",
dev->name, cmd, i * 10);
@@ -1584,14 +1612,14 @@ issue_and_wait(struct net_device *dev, int cmd)
udelay(10);
}
printk(KERN_ERR "%s: command 0x%04x did not complete! Status=0x%x\n",
- dev->name, cmd, inw(dev->base_addr + EL3_STATUS));
+ dev->name, cmd, ioread16(ioaddr + EL3_STATUS));
}
static void
vortex_up(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
unsigned int config;
int i;
@@ -1604,7 +1632,7 @@ vortex_up(struct net_device *dev)
/* Before initializing select the active media port. */
EL3WINDOW(3);
- config = inl(ioaddr + Wn3_Config);
+ config = ioread32(ioaddr + Wn3_Config);
if (vp->media_override != 7) {
printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n",
@@ -1651,14 +1679,14 @@ vortex_up(struct net_device *dev)
config = BFINS(config, dev->if_port, 20, 4);
if (vortex_debug > 6)
printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n", config);
- outl(config, ioaddr + Wn3_Config);
+ iowrite32(config, ioaddr + Wn3_Config);
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int mii_reg1, mii_reg5;
EL3WINDOW(4);
/* Read BMSR (reg1) only to clear old status. */
- mii_reg1 = mdio_read(dev, vp->phys[0], 1);
- mii_reg5 = mdio_read(dev, vp->phys[0], 5);
+ mii_reg1 = mdio_read(dev, vp->phys[0], MII_BMSR);
+ mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) {
netif_carrier_off(dev); /* No MII device or no link partner report */
} else {
@@ -1679,7 +1707,7 @@ vortex_up(struct net_device *dev)
}
/* Set the full-duplex bit. */
- outw( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
+ iowrite16( ((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
(vp->large_frames ? 0x40 : 0) |
((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
ioaddr + Wn3_MAC_Ctrl);
@@ -1695,51 +1723,51 @@ vortex_up(struct net_device *dev)
*/
issue_and_wait(dev, RxReset|0x04);
- outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
+ iowrite16(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
if (vortex_debug > 1) {
EL3WINDOW(4);
printk(KERN_DEBUG "%s: vortex_up() irq %d media status %4.4x.\n",
- dev->name, dev->irq, inw(ioaddr + Wn4_Media));
+ dev->name, dev->irq, ioread16(ioaddr + Wn4_Media));
}
/* Set the station address and mask in window 2 each time opened. */
EL3WINDOW(2);
for (i = 0; i < 6; i++)
- outb(dev->dev_addr[i], ioaddr + i);
+ iowrite8(dev->dev_addr[i], ioaddr + i);
for (; i < 12; i+=2)
- outw(0, ioaddr + i);
+ iowrite16(0, ioaddr + i);
if (vp->cb_fn_base) {
- unsigned short n = inw(ioaddr + Wn2_ResetOptions) & ~0x4010;
+ unsigned short n = ioread16(ioaddr + Wn2_ResetOptions) & ~0x4010;
if (vp->drv_flags & INVERT_LED_PWR)
n |= 0x10;
if (vp->drv_flags & INVERT_MII_PWR)
n |= 0x4000;
- outw(n, ioaddr + Wn2_ResetOptions);
+ iowrite16(n, ioaddr + Wn2_ResetOptions);
}
if (dev->if_port == XCVR_10base2)
/* Start the thinnet transceiver. We should really wait 50ms...*/
- outw(StartCoax, ioaddr + EL3_CMD);
+ iowrite16(StartCoax, ioaddr + EL3_CMD);
if (dev->if_port != XCVR_NWAY) {
EL3WINDOW(4);
- outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
+ iowrite16((ioread16(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
}
/* Switch to the stats window, and clear all stats by reading. */
- outw(StatsDisable, ioaddr + EL3_CMD);
+ iowrite16(StatsDisable, ioaddr + EL3_CMD);
EL3WINDOW(6);
for (i = 0; i < 10; i++)
- inb(ioaddr + i);
- inw(ioaddr + 10);
- inw(ioaddr + 12);
+ ioread8(ioaddr + i);
+ ioread16(ioaddr + 10);
+ ioread16(ioaddr + 12);
/* New: On the Vortex we must also clear the BadSSD counter. */
EL3WINDOW(4);
- inb(ioaddr + 12);
+ ioread8(ioaddr + 12);
/* ..and on the Boomerang we enable the extra statistics bits. */
- outw(0x0040, ioaddr + Wn4_NetDiag);
+ iowrite16(0x0040, ioaddr + Wn4_NetDiag);
/* Switch to register set 7 for normal use. */
EL3WINDOW(7);
@@ -1747,30 +1775,30 @@ vortex_up(struct net_device *dev)
if (vp->full_bus_master_rx) { /* Boomerang bus master. */
vp->cur_rx = vp->dirty_rx = 0;
/* Initialize the RxEarly register as recommended. */
- outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
- outl(0x0020, ioaddr + PktStatus);
- outl(vp->rx_ring_dma, ioaddr + UpListPtr);
+ iowrite16(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ iowrite32(0x0020, ioaddr + PktStatus);
+ iowrite32(vp->rx_ring_dma, ioaddr + UpListPtr);
}
if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
vp->cur_tx = vp->dirty_tx = 0;
if (vp->drv_flags & IS_BOOMERANG)
- outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
+ iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
/* Clear the Rx, Tx rings. */
for (i = 0; i < RX_RING_SIZE; i++) /* AKPM: this is done in vortex_open, too */
vp->rx_ring[i].status = 0;
for (i = 0; i < TX_RING_SIZE; i++)
vp->tx_skbuff[i] = NULL;
- outl(0, ioaddr + DownListPtr);
+ iowrite32(0, ioaddr + DownListPtr);
}
/* Set receiver mode: presumably accept b-case and phys addr only. */
set_rx_mode(dev);
/* enable 802.1q tagged frames */
set_8021q_mode(dev, 1);
- outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
+ iowrite16(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
// issue_and_wait(dev, SetTxStart|0x07ff);
- outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
- outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
+ iowrite16(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
+ iowrite16(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
/* Allow status bits to be seen. */
vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete|
(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
@@ -1780,13 +1808,13 @@ vortex_up(struct net_device *dev)
(vp->full_bus_master_rx ? 0 : RxComplete) |
StatsFull | HostError | TxComplete | IntReq
| (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
- outw(vp->status_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->status_enable, ioaddr + EL3_CMD);
/* Ack all pending events, and set active indicator mask. */
- outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
+ iowrite16(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
ioaddr + EL3_CMD);
- outw(vp->intr_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
- writel(0x8000, vp->cb_fn_base + 4);
+ iowrite32(0x8000, vp->cb_fn_base + 4);
netif_start_queue (dev);
}
@@ -1852,7 +1880,7 @@ vortex_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int next_tick = 60*HZ;
int ok = 0;
int media_status, mii_status, old_window;
@@ -1866,9 +1894,9 @@ vortex_timer(unsigned long data)
if (vp->medialock)
goto leave_media_alone;
disable_irq(dev->irq);
- old_window = inw(ioaddr + EL3_CMD) >> 13;
+ old_window = ioread16(ioaddr + EL3_CMD) >> 13;
EL3WINDOW(4);
- media_status = inw(ioaddr + Wn4_Media);
+ media_status = ioread16(ioaddr + Wn4_Media);
switch (dev->if_port) {
case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) {
@@ -1888,14 +1916,17 @@ vortex_timer(unsigned long data)
case XCVR_MII: case XCVR_NWAY:
{
spin_lock_bh(&vp->lock);
- mii_status = mdio_read(dev, vp->phys[0], 1);
- mii_status = mdio_read(dev, vp->phys[0], 1);
+ mii_status = mdio_read(dev, vp->phys[0], MII_BMSR);
+ if (!(mii_status & BMSR_LSTATUS)) {
+ /* Re-read to get actual link status */
+ mii_status = mdio_read(dev, vp->phys[0], MII_BMSR);
+ }
ok = 1;
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
dev->name, mii_status);
if (mii_status & BMSR_LSTATUS) {
- int mii_reg5 = mdio_read(dev, vp->phys[0], 5);
+ int mii_reg5 = mdio_read(dev, vp->phys[0], MII_LPA);
if (! vp->force_fd && mii_reg5 != 0xffff) {
int duplex;
@@ -1909,7 +1940,7 @@ vortex_timer(unsigned long data)
vp->phys[0], mii_reg5);
/* Set the full-duplex bit. */
EL3WINDOW(3);
- outw( (vp->full_duplex ? 0x20 : 0) |
+ iowrite16( (vp->full_duplex ? 0x20 : 0) |
(vp->large_frames ? 0x40 : 0) |
((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
ioaddr + Wn3_MAC_Ctrl);
@@ -1950,15 +1981,15 @@ vortex_timer(unsigned long data)
dev->name, media_tbl[dev->if_port].name);
next_tick = media_tbl[dev->if_port].wait;
}
- outw((media_status & ~(Media_10TP|Media_SQE)) |
+ iowrite16((media_status & ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
EL3WINDOW(3);
- config = inl(ioaddr + Wn3_Config);
+ config = ioread32(ioaddr + Wn3_Config);
config = BFINS(config, dev->if_port, 20, 4);
- outl(config, ioaddr + Wn3_Config);
+ iowrite32(config, ioaddr + Wn3_Config);
- outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
+ iowrite16(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
if (vortex_debug > 1)
printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config);
@@ -1974,29 +2005,29 @@ leave_media_alone:
mod_timer(&vp->timer, RUN_AT(next_tick));
if (vp->deferred)
- outw(FakeIntr, ioaddr + EL3_CMD);
+ iowrite16(FakeIntr, ioaddr + EL3_CMD);
return;
}
static void vortex_tx_timeout(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
- dev->name, inb(ioaddr + TxStatus),
- inw(ioaddr + EL3_STATUS));
+ dev->name, ioread8(ioaddr + TxStatus),
+ ioread16(ioaddr + EL3_STATUS));
EL3WINDOW(4);
printk(KERN_ERR " diagnostics: net %04x media %04x dma %08x fifo %04x\n",
- inw(ioaddr + Wn4_NetDiag),
- inw(ioaddr + Wn4_Media),
- inl(ioaddr + PktStatus),
- inw(ioaddr + Wn4_FIFODiag));
+ ioread16(ioaddr + Wn4_NetDiag),
+ ioread16(ioaddr + Wn4_Media),
+ ioread32(ioaddr + PktStatus),
+ ioread16(ioaddr + Wn4_FIFODiag));
/* Slight code bloat to be user friendly. */
- if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
+ if ((ioread8(ioaddr + TxStatus) & 0x88) == 0x88)
printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
" network cable problem?\n", dev->name);
- if (inw(ioaddr + EL3_STATUS) & IntLatch) {
+ if (ioread16(ioaddr + EL3_STATUS) & IntLatch) {
printk(KERN_ERR "%s: Interrupt posted but not delivered --"
" IRQ blocked by another device?\n", dev->name);
/* Bad idea here.. but we might as well handle a few events. */
@@ -2022,21 +2053,21 @@ static void vortex_tx_timeout(struct net_device *dev)
vp->stats.tx_errors++;
if (vp->full_bus_master_tx) {
printk(KERN_DEBUG "%s: Resetting the Tx ring pointer.\n", dev->name);
- if (vp->cur_tx - vp->dirty_tx > 0 && inl(ioaddr + DownListPtr) == 0)
- outl(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
+ if (vp->cur_tx - vp->dirty_tx > 0 && ioread32(ioaddr + DownListPtr) == 0)
+ iowrite32(vp->tx_ring_dma + (vp->dirty_tx % TX_RING_SIZE) * sizeof(struct boom_tx_desc),
ioaddr + DownListPtr);
if (vp->cur_tx - vp->dirty_tx < TX_RING_SIZE)
netif_wake_queue (dev);
if (vp->drv_flags & IS_BOOMERANG)
- outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
- outw(DownUnstall, ioaddr + EL3_CMD);
+ iowrite8(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
+ iowrite16(DownUnstall, ioaddr + EL3_CMD);
} else {
vp->stats.tx_dropped++;
netif_wake_queue(dev);
}
/* Issue Tx Enable */
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
dev->trans_start = jiffies;
/* Switch to register set 7 for normal use. */
@@ -2051,7 +2082,7 @@ static void
vortex_error(struct net_device *dev, int status)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int do_tx_reset = 0, reset_mask = 0;
unsigned char tx_status = 0;
@@ -2060,7 +2091,7 @@ vortex_error(struct net_device *dev, int status)
}
if (status & TxComplete) { /* Really "TxError" for us. */
- tx_status = inb(ioaddr + TxStatus);
+ tx_status = ioread8(ioaddr + TxStatus);
/* Presumably a tx-timeout. We must merely re-enable. */
if (vortex_debug > 2
|| (tx_status != 0x88 && vortex_debug > 0)) {
@@ -2074,20 +2105,20 @@ vortex_error(struct net_device *dev, int status)
}
if (tx_status & 0x14) vp->stats.tx_fifo_errors++;
if (tx_status & 0x38) vp->stats.tx_aborted_errors++;
- outb(0, ioaddr + TxStatus);
+ iowrite8(0, ioaddr + TxStatus);
if (tx_status & 0x30) { /* txJabber or txUnderrun */
do_tx_reset = 1;
} else if ((tx_status & 0x08) && (vp->drv_flags & MAX_COLLISION_RESET)) { /* maxCollisions */
do_tx_reset = 1;
reset_mask = 0x0108; /* Reset interface logic, but not download logic */
} else { /* Merely re-enable the transmitter. */
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
}
}
if (status & RxEarly) { /* Rx early is unused. */
vortex_rx(dev);
- outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
}
if (status & StatsFull) { /* Empty statistics. */
static int DoneDidThat;
@@ -2097,29 +2128,29 @@ vortex_error(struct net_device *dev, int status)
/* HACK: Disable statistics as an interrupt source. */
/* This occurs when we have the wrong media type! */
if (DoneDidThat == 0 &&
- inw(ioaddr + EL3_STATUS) & StatsFull) {
+ ioread16(ioaddr + EL3_STATUS) & StatsFull) {
printk(KERN_WARNING "%s: Updating statistics failed, disabling "
"stats as an interrupt source.\n", dev->name);
EL3WINDOW(5);
- outw(SetIntrEnb | (inw(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
+ iowrite16(SetIntrEnb | (ioread16(ioaddr + 10) & ~StatsFull), ioaddr + EL3_CMD);
vp->intr_enable &= ~StatsFull;
EL3WINDOW(7);
DoneDidThat++;
}
}
if (status & IntReq) { /* Restore all interrupt sources. */
- outw(vp->status_enable, ioaddr + EL3_CMD);
- outw(vp->intr_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->status_enable, ioaddr + EL3_CMD);
+ iowrite16(vp->intr_enable, ioaddr + EL3_CMD);
}
if (status & HostError) {
u16 fifo_diag;
EL3WINDOW(4);
- fifo_diag = inw(ioaddr + Wn4_FIFODiag);
+ fifo_diag = ioread16(ioaddr + Wn4_FIFODiag);
printk(KERN_ERR "%s: Host error, FIFO diagnostic register %4.4x.\n",
dev->name, fifo_diag);
/* Adapter failure requires Tx/Rx reset and reinit. */
if (vp->full_bus_master_tx) {
- int bus_status = inl(ioaddr + PktStatus);
+ int bus_status = ioread32(ioaddr + PktStatus);
/* 0x80000000 PCI master abort. */
/* 0x40000000 PCI target abort. */
if (vortex_debug)
@@ -2139,14 +2170,14 @@ vortex_error(struct net_device *dev, int status)
set_rx_mode(dev);
/* enable 802.1q VLAN tagged frames */
set_8021q_mode(dev, 1);
- outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
- outw(AckIntr | HostError, ioaddr + EL3_CMD);
+ iowrite16(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
+ iowrite16(AckIntr | HostError, ioaddr + EL3_CMD);
}
}
if (do_tx_reset) {
issue_and_wait(dev, TxReset|reset_mask);
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
if (!vp->full_bus_master_tx)
netif_wake_queue(dev);
}
@@ -2156,29 +2187,29 @@ static int
vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
/* Put out the doubleword header... */
- outl(skb->len, ioaddr + TX_FIFO);
+ iowrite32(skb->len, ioaddr + TX_FIFO);
if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */
int len = (skb->len + 3) & ~3;
- outl( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE),
+ iowrite32( vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len, PCI_DMA_TODEVICE),
ioaddr + Wn7_MasterAddr);
- outw(len, ioaddr + Wn7_MasterLen);
+ iowrite16(len, ioaddr + Wn7_MasterLen);
vp->tx_skb = skb;
- outw(StartDMADown, ioaddr + EL3_CMD);
+ iowrite16(StartDMADown, ioaddr + EL3_CMD);
/* netif_wake_queue() will be called at the DMADone interrupt. */
} else {
/* ... and the packet rounded to a doubleword. */
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+ iowrite32_rep(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
dev_kfree_skb (skb);
- if (inw(ioaddr + TxFree) > 1536) {
+ if (ioread16(ioaddr + TxFree) > 1536) {
netif_start_queue (dev); /* AKPM: redundant? */
} else {
/* Interrupt us when the FIFO has room for max-sized packet. */
netif_stop_queue(dev);
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
}
}
@@ -2189,7 +2220,7 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
int tx_status;
int i = 32;
- while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
+ while (--i > 0 && (tx_status = ioread8(ioaddr + TxStatus)) > 0) {
if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */
if (vortex_debug > 2)
printk(KERN_DEBUG "%s: Tx error, status %2.2x.\n",
@@ -2199,9 +2230,9 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (tx_status & 0x30) {
issue_and_wait(dev, TxReset);
}
- outw(TxEnable, ioaddr + EL3_CMD);
+ iowrite16(TxEnable, ioaddr + EL3_CMD);
}
- outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
+ iowrite8(0x00, ioaddr + TxStatus); /* Pop the status stack. */
}
}
return 0;
@@ -2211,7 +2242,7 @@ static int
boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
/* Calculate the next Tx descriptor entry. */
int entry = vp->cur_tx % TX_RING_SIZE;
struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE];
@@ -2275,8 +2306,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Wait for the stall to complete. */
issue_and_wait(dev, DownStall);
prev_entry->next = cpu_to_le32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc));
- if (inl(ioaddr + DownListPtr) == 0) {
- outl(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
+ if (ioread32(ioaddr + DownListPtr) == 0) {
+ iowrite32(vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc), ioaddr + DownListPtr);
vp->queued_packet++;
}
@@ -2291,7 +2322,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
#endif
}
- outw(DownUnstall, ioaddr + EL3_CMD);
+ iowrite16(DownUnstall, ioaddr + EL3_CMD);
spin_unlock_irqrestore(&vp->lock, flags);
dev->trans_start = jiffies;
return 0;
@@ -2310,15 +2341,15 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr;
+ void __iomem *ioaddr;
int status;
int work_done = max_interrupt_work;
int handled = 0;
- ioaddr = dev->base_addr;
+ ioaddr = vp->ioaddr;
spin_lock(&vp->lock);
- status = inw(ioaddr + EL3_STATUS);
+ status = ioread16(ioaddr + EL3_STATUS);
if (vortex_debug > 6)
printk("vortex_interrupt(). status=0x%4x\n", status);
@@ -2337,7 +2368,7 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
- dev->name, status, inb(ioaddr + Timer));
+ dev->name, status, ioread8(ioaddr + Timer));
do {
if (vortex_debug > 5)
@@ -2350,16 +2381,16 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (vortex_debug > 5)
printk(KERN_DEBUG " TX room bit was handled.\n");
/* There's room in the FIFO for a full-sized packet. */
- outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | TxAvailable, ioaddr + EL3_CMD);
netif_wake_queue (dev);
}
if (status & DMADone) {
- if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
- outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+ if (ioread16(ioaddr + Wn7_MasterStatus) & 0x1000) {
+ iowrite16(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
pci_unmap_single(VORTEX_PCI(vp), vp->tx_skb_dma, (vp->tx_skb->len + 3) & ~3, PCI_DMA_TODEVICE);
dev_kfree_skb_irq(vp->tx_skb); /* Release the transferred buffer */
- if (inw(ioaddr + TxFree) > 1536) {
+ if (ioread16(ioaddr + TxFree) > 1536) {
/*
* AKPM: FIXME: I don't think we need this. If the queue was stopped due to
* insufficient FIFO room, the TxAvailable test will succeed and call
@@ -2367,7 +2398,7 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
netif_wake_queue(dev);
} else { /* Interrupt when FIFO has room for max-sized packet. */
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ iowrite16(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
netif_stop_queue(dev);
}
}
@@ -2385,17 +2416,17 @@ vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Disable all pending interrupts. */
do {
vp->deferred |= status;
- outw(SetStatusEnb | (~vp->deferred & vp->status_enable),
+ iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
ioaddr + EL3_CMD);
- outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
- } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
+ iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
+ } while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
mod_timer(&vp->timer, jiffies + 1*HZ);
break;
}
/* Acknowledge the IRQ. */
- outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
- } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+ iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+ } while ((status = ioread16(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
@@ -2415,11 +2446,11 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr;
+ void __iomem *ioaddr;
int status;
int work_done = max_interrupt_work;
- ioaddr = dev->base_addr;
+ ioaddr = vp->ioaddr;
/*
* It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout
@@ -2427,7 +2458,7 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
spin_lock(&vp->lock);
- status = inw(ioaddr + EL3_STATUS);
+ status = ioread16(ioaddr + EL3_STATUS);
if (vortex_debug > 6)
printk(KERN_DEBUG "boomerang_interrupt. status=0x%4x\n", status);
@@ -2448,13 +2479,13 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: interrupt, status %4.4x, latency %d ticks.\n",
- dev->name, status, inb(ioaddr + Timer));
+ dev->name, status, ioread8(ioaddr + Timer));
do {
if (vortex_debug > 5)
printk(KERN_DEBUG "%s: In interrupt loop, status %4.4x.\n",
dev->name, status);
if (status & UpComplete) {
- outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | UpComplete, ioaddr + EL3_CMD);
if (vortex_debug > 5)
printk(KERN_DEBUG "boomerang_interrupt->boomerang_rx\n");
boomerang_rx(dev);
@@ -2463,11 +2494,11 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status & DownComplete) {
unsigned int dirty_tx = vp->dirty_tx;
- outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | DownComplete, ioaddr + EL3_CMD);
while (vp->cur_tx - dirty_tx > 0) {
int entry = dirty_tx % TX_RING_SIZE;
#if 1 /* AKPM: the latter is faster, but cyclone-only */
- if (inl(ioaddr + DownListPtr) ==
+ if (ioread32(ioaddr + DownListPtr) ==
vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc))
break; /* It still hasn't been processed. */
#else
@@ -2514,20 +2545,20 @@ boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Disable all pending interrupts. */
do {
vp->deferred |= status;
- outw(SetStatusEnb | (~vp->deferred & vp->status_enable),
+ iowrite16(SetStatusEnb | (~vp->deferred & vp->status_enable),
ioaddr + EL3_CMD);
- outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
- } while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
+ iowrite16(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
+ } while ((status = ioread16(ioaddr + EL3_CMD)) & IntLatch);
/* The timer will reenable interrupts. */
mod_timer(&vp->timer, jiffies + 1*HZ);
break;
}
/* Acknowledge the IRQ. */
- outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+ iowrite16(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
- writel(0x8000, vp->cb_fn_base + 4);
+ iowrite32(0x8000, vp->cb_fn_base + 4);
- } while ((status = inw(ioaddr + EL3_STATUS)) & IntLatch);
+ } while ((status = ioread16(ioaddr + EL3_STATUS)) & IntLatch);
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
@@ -2540,16 +2571,16 @@ handler_exit:
static int vortex_rx(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int i;
short rx_status;
if (vortex_debug > 5)
printk(KERN_DEBUG "vortex_rx(): status %4.4x, rx_status %4.4x.\n",
- inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
- while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
+ ioread16(ioaddr+EL3_STATUS), ioread16(ioaddr+RxStatus));
+ while ((rx_status = ioread16(ioaddr + RxStatus)) > 0) {
if (rx_status & 0x4000) { /* Error, update stats. */
- unsigned char rx_error = inb(ioaddr + RxErrors);
+ unsigned char rx_error = ioread8(ioaddr + RxErrors);
if (vortex_debug > 2)
printk(KERN_DEBUG " Rx error: status %2.2x.\n", rx_error);
vp->stats.rx_errors++;
@@ -2572,34 +2603,35 @@ static int vortex_rx(struct net_device *dev)
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
if (vp->bus_master &&
- ! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
+ ! (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)) {
dma_addr_t dma = pci_map_single(VORTEX_PCI(vp), skb_put(skb, pkt_len),
pkt_len, PCI_DMA_FROMDEVICE);
- outl(dma, ioaddr + Wn7_MasterAddr);
- outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
- outw(StartDMAUp, ioaddr + EL3_CMD);
- while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
+ iowrite32(dma, ioaddr + Wn7_MasterAddr);
+ iowrite16((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+ iowrite16(StartDMAUp, ioaddr + EL3_CMD);
+ while (ioread16(ioaddr + Wn7_MasterStatus) & 0x8000)
;
pci_unmap_single(VORTEX_PCI(vp), dma, pkt_len, PCI_DMA_FROMDEVICE);
} else {
- insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
- (pkt_len + 3) >> 2);
+ ioread32_rep(ioaddr + RX_FIFO,
+ skb_put(skb, pkt_len),
+ (pkt_len + 3) >> 2);
}
- outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
+ iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
vp->stats.rx_packets++;
/* Wait a limited time to go to next packet. */
for (i = 200; i >= 0; i--)
- if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
+ if ( ! (ioread16(ioaddr + EL3_STATUS) & CmdInProgress))
break;
continue;
} else if (vortex_debug > 0)
printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of "
"size %d.\n", dev->name, pkt_len);
+ vp->stats.rx_dropped++;
}
- vp->stats.rx_dropped++;
issue_and_wait(dev, RxDiscard);
}
@@ -2611,12 +2643,12 @@ boomerang_rx(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
int entry = vp->cur_rx % RX_RING_SIZE;
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int rx_status;
int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
if (vortex_debug > 5)
- printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", inw(ioaddr+EL3_STATUS));
+ printk(KERN_DEBUG "boomerang_rx(): status %4.4x\n", ioread16(ioaddr+EL3_STATUS));
while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
if (--rx_work_limit < 0)
@@ -2699,7 +2731,7 @@ boomerang_rx(struct net_device *dev)
vp->rx_skbuff[entry] = skb;
}
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
- outw(UpUnstall, ioaddr + EL3_CMD);
+ iowrite16(UpUnstall, ioaddr + EL3_CMD);
}
return 0;
}
@@ -2728,7 +2760,7 @@ static void
vortex_down(struct net_device *dev, int final_down)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
netif_stop_queue (dev);
@@ -2736,26 +2768,26 @@ vortex_down(struct net_device *dev, int final_down)
del_timer_sync(&vp->timer);
/* Turn off statistics ASAP. We update vp->stats below. */
- outw(StatsDisable, ioaddr + EL3_CMD);
+ iowrite16(StatsDisable, ioaddr + EL3_CMD);
/* Disable the receiver and transmitter. */
- outw(RxDisable, ioaddr + EL3_CMD);
- outw(TxDisable, ioaddr + EL3_CMD);
+ iowrite16(RxDisable, ioaddr + EL3_CMD);
+ iowrite16(TxDisable, ioaddr + EL3_CMD);
/* Disable receiving 802.1q tagged frames */
set_8021q_mode(dev, 0);
if (dev->if_port == XCVR_10base2)
/* Turn off thinnet power. Green! */
- outw(StopCoax, ioaddr + EL3_CMD);
+ iowrite16(StopCoax, ioaddr + EL3_CMD);
- outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
+ iowrite16(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
update_stats(ioaddr, dev);
if (vp->full_bus_master_rx)
- outl(0, ioaddr + UpListPtr);
+ iowrite32(0, ioaddr + UpListPtr);
if (vp->full_bus_master_tx)
- outl(0, ioaddr + DownListPtr);
+ iowrite32(0, ioaddr + DownListPtr);
if (final_down && VORTEX_PCI(vp)) {
vp->pm_state_valid = 1;
@@ -2768,7 +2800,7 @@ static int
vortex_close(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
int i;
if (netif_device_present(dev))
@@ -2776,17 +2808,18 @@ vortex_close(struct net_device *dev)
if (vortex_debug > 1) {
printk(KERN_DEBUG"%s: vortex_close() status %4.4x, Tx status %2.2x.\n",
- dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus));
+ dev->name, ioread16(ioaddr + EL3_STATUS), ioread8(ioaddr + TxStatus));
printk(KERN_DEBUG "%s: vortex close stats: rx_nocopy %d rx_copy %d"
" tx_queued %d Rx pre-checksummed %d.\n",
dev->name, vp->rx_nocopy, vp->rx_copy, vp->queued_packet, vp->rx_csumhits);
}
#if DO_ZEROCOPY
- if ( vp->rx_csumhits &&
- ((vp->drv_flags & HAS_HWCKSM) == 0) &&
- (hw_checksums[vp->card_idx] == -1)) {
- printk(KERN_WARNING "%s supports hardware checksums, and we're not using them!\n", dev->name);
+ if (vp->rx_csumhits &&
+ (vp->drv_flags & HAS_HWCKSM) == 0 &&
+ (vp->card_idx >= MAX_UNITS || hw_checksums[vp->card_idx] == -1)) {
+ printk(KERN_WARNING "%s supports hardware checksums, and we're "
+ "not using them!\n", dev->name);
}
#endif
@@ -2830,18 +2863,18 @@ dump_tx_ring(struct net_device *dev)
{
if (vortex_debug > 0) {
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
if (vp->full_bus_master_tx) {
int i;
- int stalled = inl(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */
+ int stalled = ioread32(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */
printk(KERN_ERR " Flags; bus-master %d, dirty %d(%d) current %d(%d)\n",
vp->full_bus_master_tx,
vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
printk(KERN_ERR " Transmit list %8.8x vs. %p.\n",
- inl(ioaddr + DownListPtr),
+ ioread32(ioaddr + DownListPtr),
&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
issue_and_wait(dev, DownStall);
for (i = 0; i < TX_RING_SIZE; i++) {
@@ -2855,7 +2888,7 @@ dump_tx_ring(struct net_device *dev)
le32_to_cpu(vp->tx_ring[i].status));
}
if (!stalled)
- outw(DownUnstall, ioaddr + EL3_CMD);
+ iowrite16(DownUnstall, ioaddr + EL3_CMD);
}
}
}
@@ -2863,11 +2896,12 @@ dump_tx_ring(struct net_device *dev)
static struct net_device_stats *vortex_get_stats(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
if (netif_device_present(dev)) { /* AKPM: Used to be netif_running */
spin_lock_irqsave (&vp->lock, flags);
- update_stats(dev->base_addr, dev);
+ update_stats(ioaddr, dev);
spin_unlock_irqrestore (&vp->lock, flags);
}
return &vp->stats;
@@ -2880,37 +2914,37 @@ static struct net_device_stats *vortex_get_stats(struct net_device *dev)
table. This is done by checking that the ASM (!) code generated uses
atomic updates with '+='.
*/
-static void update_stats(long ioaddr, struct net_device *dev)
+static void update_stats(void __iomem *ioaddr, struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- int old_window = inw(ioaddr + EL3_CMD);
+ int old_window = ioread16(ioaddr + EL3_CMD);
if (old_window == 0xffff) /* Chip suspended or ejected. */
return;
/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
/* Switch to the stats window, and read everything. */
EL3WINDOW(6);
- vp->stats.tx_carrier_errors += inb(ioaddr + 0);
- vp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
- vp->stats.collisions += inb(ioaddr + 3);
- vp->stats.tx_window_errors += inb(ioaddr + 4);
- vp->stats.rx_fifo_errors += inb(ioaddr + 5);
- vp->stats.tx_packets += inb(ioaddr + 6);
- vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4;
- /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */
+ vp->stats.tx_carrier_errors += ioread8(ioaddr + 0);
+ vp->stats.tx_heartbeat_errors += ioread8(ioaddr + 1);
+ vp->stats.collisions += ioread8(ioaddr + 3);
+ vp->stats.tx_window_errors += ioread8(ioaddr + 4);
+ vp->stats.rx_fifo_errors += ioread8(ioaddr + 5);
+ vp->stats.tx_packets += ioread8(ioaddr + 6);
+ vp->stats.tx_packets += (ioread8(ioaddr + 9)&0x30) << 4;
+ /* Rx packets */ ioread8(ioaddr + 7); /* Must read to clear */
/* Don't bother with register 9, an extension of registers 6&7.
If we do use the 6&7 values the atomic update assumption above
is invalid. */
- vp->stats.rx_bytes += inw(ioaddr + 10);
- vp->stats.tx_bytes += inw(ioaddr + 12);
+ vp->stats.rx_bytes += ioread16(ioaddr + 10);
+ vp->stats.tx_bytes += ioread16(ioaddr + 12);
/* Extra stats for get_ethtool_stats() */
- vp->xstats.tx_multiple_collisions += inb(ioaddr + 2);
- vp->xstats.tx_deferred += inb(ioaddr + 8);
+ vp->xstats.tx_multiple_collisions += ioread8(ioaddr + 2);
+ vp->xstats.tx_deferred += ioread8(ioaddr + 8);
EL3WINDOW(4);
- vp->xstats.rx_bad_ssd += inb(ioaddr + 12);
+ vp->xstats.rx_bad_ssd += ioread8(ioaddr + 12);
{
- u8 up = inb(ioaddr + 13);
+ u8 up = ioread8(ioaddr + 13);
vp->stats.rx_bytes += (up & 0x0f) << 16;
vp->stats.tx_bytes += (up & 0xf0) << 12;
}
@@ -2922,7 +2956,7 @@ static void update_stats(long ioaddr, struct net_device *dev)
static int vortex_nway_reset(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2936,7 +2970,7 @@ static int vortex_nway_reset(struct net_device *dev)
static u32 vortex_get_link(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2950,7 +2984,7 @@ static u32 vortex_get_link(struct net_device *dev)
static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2964,7 +2998,7 @@ static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int rc;
@@ -2994,10 +3028,11 @@ static void vortex_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
spin_lock_irqsave(&vp->lock, flags);
- update_stats(dev->base_addr, dev);
+ update_stats(ioaddr, dev);
spin_unlock_irqrestore(&vp->lock, flags);
data[0] = vp->xstats.tx_deferred;
@@ -3047,6 +3082,7 @@ static struct ethtool_ops vortex_ethtool_ops = {
.set_settings = vortex_set_settings,
.get_link = vortex_get_link,
.nway_reset = vortex_nway_reset,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
#ifdef CONFIG_PCI
@@ -3057,7 +3093,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
int err;
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
unsigned long flags;
int state = 0;
@@ -3085,7 +3121,8 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
the chip has a very clean way to set the mode, unlike many others. */
static void set_rx_mode(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int new_mode;
if (dev->flags & IFF_PROMISC) {
@@ -3097,7 +3134,7 @@ static void set_rx_mode(struct net_device *dev)
} else
new_mode = SetRxFilter | RxStation | RxBroadcast;
- outw(new_mode, ioaddr + EL3_CMD);
+ iowrite16(new_mode, ioaddr + EL3_CMD);
}
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
@@ -3111,8 +3148,8 @@ static void set_rx_mode(struct net_device *dev)
static void set_8021q_mode(struct net_device *dev, int enable)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
- int old_window = inw(ioaddr + EL3_CMD);
+ void __iomem *ioaddr = vp->ioaddr;
+ int old_window = ioread16(ioaddr + EL3_CMD);
int mac_ctrl;
if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
@@ -3124,24 +3161,24 @@ static void set_8021q_mode(struct net_device *dev, int enable)
max_pkt_size += 4; /* 802.1Q VLAN tag */
EL3WINDOW(3);
- outw(max_pkt_size, ioaddr+Wn3_MaxPktSize);
+ iowrite16(max_pkt_size, ioaddr+Wn3_MaxPktSize);
/* set VlanEtherType to let the hardware checksumming
treat tagged frames correctly */
EL3WINDOW(7);
- outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
+ iowrite16(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
} else {
/* on older cards we have to enable large frames */
vp->large_frames = dev->mtu > 1500 || enable;
EL3WINDOW(3);
- mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl);
+ mac_ctrl = ioread16(ioaddr+Wn3_MAC_Ctrl);
if (vp->large_frames)
mac_ctrl |= 0x40;
else
mac_ctrl &= ~0x40;
- outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
+ iowrite16(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
}
EL3WINDOW(old_window);
@@ -3163,7 +3200,7 @@ static void set_8021q_mode(struct net_device *dev, int enable)
/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
met by back-to-back PCI I/O cycles, but we insert a delay to avoid
"overclocking" issues. */
-#define mdio_delay() inl(mdio_addr)
+#define mdio_delay() ioread32(mdio_addr)
#define MDIO_SHIFT_CLK 0x01
#define MDIO_DIR_WRITE 0x04
@@ -3174,15 +3211,15 @@ static void set_8021q_mode(struct net_device *dev, int enable)
/* Generate the preamble required for initial synchronization and
a few older transceivers. */
-static void mdio_sync(long ioaddr, int bits)
+static void mdio_sync(void __iomem *ioaddr, int bits)
{
- long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
/* Establish sync by sending at least 32 logic ones. */
while (-- bits >= 0) {
- outw(MDIO_DATA_WRITE1, mdio_addr);
+ iowrite16(MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
- outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
}
@@ -3190,10 +3227,11 @@ static void mdio_sync(long ioaddr, int bits)
static int mdio_read(struct net_device *dev, int phy_id, int location)
{
int i;
- long ioaddr = dev->base_addr;
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
unsigned int retval = 0;
- long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
if (mii_preamble_required)
mdio_sync(ioaddr, 32);
@@ -3201,17 +3239,17 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
/* Shift the read command bits out. */
for (i = 14; i >= 0; i--) {
int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outw(dataval, mdio_addr);
+ iowrite16(dataval, mdio_addr);
mdio_delay();
- outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
/* Read the two transition, 16 data, and wire-idle bits. */
for (i = 19; i > 0; i--) {
- outw(MDIO_ENB_IN, mdio_addr);
+ iowrite16(MDIO_ENB_IN, mdio_addr);
mdio_delay();
- retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
- outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ retval = (retval << 1) | ((ioread16(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+ iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
@@ -3219,9 +3257,10 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
{
- long ioaddr = dev->base_addr;
+ struct vortex_private *vp = netdev_priv(dev);
+ void __iomem *ioaddr = vp->ioaddr;
int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
- long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ void __iomem *mdio_addr = ioaddr + Wn4_PhysicalMgmt;
int i;
if (mii_preamble_required)
@@ -3230,16 +3269,16 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
/* Shift the command bits out. */
for (i = 31; i >= 0; i--) {
int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
- outw(dataval, mdio_addr);
+ iowrite16(dataval, mdio_addr);
mdio_delay();
- outw(dataval | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(dataval | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
/* Leave the interface idle. */
for (i = 1; i >= 0; i--) {
- outw(MDIO_ENB_IN, mdio_addr);
+ iowrite16(MDIO_ENB_IN, mdio_addr);
mdio_delay();
- outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ iowrite16(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
return;
@@ -3250,15 +3289,15 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
static void acpi_set_WOL(struct net_device *dev)
{
struct vortex_private *vp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = vp->ioaddr;
if (vp->enable_wol) {
/* Power up on: 1==Downloaded Filter, 2==Magic Packets, 4==Link Status. */
EL3WINDOW(7);
- outw(2, ioaddr + 0x0c);
+ iowrite16(2, ioaddr + 0x0c);
/* The RxFilter must accept the WOL frames. */
- outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
- outw(RxEnable, ioaddr + EL3_CMD);
+ iowrite16(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
+ iowrite16(RxEnable, ioaddr + EL3_CMD);
pci_enable_wake(VORTEX_PCI(vp), 0, 1);
@@ -3280,10 +3319,9 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev)
vp = netdev_priv(dev);
- /* AKPM: FIXME: we should have
- * if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
- * here
- */
+ if (vp->cb_fn_base)
+ pci_iounmap(VORTEX_PCI(vp), vp->cb_fn_base);
+
unregister_netdev(dev);
if (VORTEX_PCI(vp)) {
@@ -3293,8 +3331,10 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev)
pci_disable_device(VORTEX_PCI(vp));
}
/* Should really use issue_and_wait() here */
- outw(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
- dev->base_addr + EL3_CMD);
+ iowrite16(TotalReset | ((vp->drv_flags & EEPROM_RESET) ? 0x04 : 0x14),
+ vp->ioaddr + EL3_CMD);
+
+ pci_iounmap(VORTEX_PCI(vp), vp->ioaddr);
pci_free_consistent(pdev,
sizeof(struct boom_rx_desc) * RX_RING_SIZE
@@ -3342,7 +3382,7 @@ static int __init vortex_init (void)
static void __exit vortex_eisa_cleanup (void)
{
struct vortex_private *vp;
- long ioaddr;
+ void __iomem *ioaddr;
#ifdef CONFIG_EISA
/* Take care of the EISA devices */
@@ -3351,11 +3391,13 @@ static void __exit vortex_eisa_cleanup (void)
if (compaq_net_device) {
vp = compaq_net_device->priv;
- ioaddr = compaq_net_device->base_addr;
+ ioaddr = ioport_map(compaq_net_device->base_addr,
+ VORTEX_TOTAL_SIZE);
unregister_netdev (compaq_net_device);
- outw (TotalReset, ioaddr + EL3_CMD);
- release_region (ioaddr, VORTEX_TOTAL_SIZE);
+ iowrite16 (TotalReset, ioaddr + EL3_CMD);
+ release_region(compaq_net_device->base_addr,
+ VORTEX_TOTAL_SIZE);
free_netdev (compaq_net_device);
}
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 85504fb900da..bd6983d1afba 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -18,8 +18,8 @@
* Much better multiple PHY support by Magnus Damm.
* Copyright (c) 2000 Ericsson Radio Systems AB.
*
- * Support for FEC controller of ColdFire/5270/5271/5272/5274/5275/5280/5282.
- * Copyright (c) 2001-2004 Greg Ungerer (gerg@snapgear.com)
+ * Support for FEC controller of ColdFire processors.
+ * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com)
*
* Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
* Copyright (c) 2004-2005 Macq Electronique SA.
@@ -50,7 +50,8 @@
#include <asm/pgtable.h>
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
- defined(CONFIG_M5272) || defined(CONFIG_M528x)
+ defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
+ defined(CONFIG_M520x)
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include "fec.h"
@@ -77,6 +78,8 @@ static unsigned int fec_hw[] = {
(MCF_MBAR + 0x1800),
#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
(MCF_MBAR + 0x1000),
+#elif defined(CONFIG_M520x)
+ (MCF_MBAR+0x30000),
#else
&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
#endif
@@ -139,6 +142,10 @@ typedef struct {
#define TX_RING_SIZE 16 /* Must be power of two */
#define TX_RING_MOD_MASK 15 /* for this to work */
+#if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)
+#error "FEC: descriptor ring size contants too large"
+#endif
+
/* Interrupt events/masks.
*/
#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
@@ -164,7 +171,8 @@ typedef struct {
* size bits. Other FEC hardware does not, so we need to take that into
* account when setting it.
*/
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+ defined(CONFIG_M520x)
#define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16)
#else
#define OPT_FRAME_SIZE 0
@@ -1137,6 +1145,65 @@ static phy_info_t const phy_info_ks8721bl = {
};
/* ------------------------------------------------------------------------- */
+/* register definitions for the DP83848 */
+
+#define MII_DP8384X_PHYSTST 16 /* PHY Status Register */
+
+static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev)
+{
+ struct fec_enet_private *fep = dev->priv;
+ volatile uint *s = &(fep->phy_status);
+
+ *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+
+ /* Link up */
+ if (mii_reg & 0x0001) {
+ fep->link = 1;
+ *s |= PHY_STAT_LINK;
+ } else
+ fep->link = 0;
+ /* Status of link */
+ if (mii_reg & 0x0010) /* Autonegotioation complete */
+ *s |= PHY_STAT_ANC;
+ if (mii_reg & 0x0002) { /* 10MBps? */
+ if (mii_reg & 0x0004) /* Full Duplex? */
+ *s |= PHY_STAT_10FDX;
+ else
+ *s |= PHY_STAT_10HDX;
+ } else { /* 100 Mbps? */
+ if (mii_reg & 0x0004) /* Full Duplex? */
+ *s |= PHY_STAT_100FDX;
+ else
+ *s |= PHY_STAT_100HDX;
+ }
+ if (mii_reg & 0x0008)
+ *s |= PHY_STAT_FAULT;
+}
+
+static phy_info_t phy_info_dp83848= {
+ 0x020005c9,
+ "DP83848",
+
+ (const phy_cmd_t []) { /* config */
+ { mk_mii_read(MII_REG_CR), mii_parse_cr },
+ { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
+ { mk_mii_read(MII_DP8384X_PHYSTST), mii_parse_dp8384x_sr2 },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* startup - enable interrupts */
+ { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
+ { mk_mii_read(MII_REG_SR), mii_parse_sr },
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* ack_int - never happens, no interrupt */
+ { mk_mii_end, }
+ },
+ (const phy_cmd_t []) { /* shutdown */
+ { mk_mii_end, }
+ },
+};
+
+/* ------------------------------------------------------------------------- */
static phy_info_t const * const phy_info[] = {
&phy_info_lxt970,
@@ -1144,6 +1211,7 @@ static phy_info_t const * const phy_info[] = {
&phy_info_qs6612,
&phy_info_am79c874,
&phy_info_ks8721bl,
+ &phy_info_dp83848,
NULL
};
@@ -1422,6 +1490,134 @@ static void __inline__ fec_uncache(unsigned long addr)
/* ------------------------------------------------------------------------- */
+#elif defined(CONFIG_M520x)
+
+/*
+ * Code specific to Coldfire 520x
+ */
+static void __inline__ fec_request_intrs(struct net_device *dev)
+{
+ struct fec_enet_private *fep;
+ int b;
+ static const struct idesc {
+ char *name;
+ unsigned short irq;
+ } *idp, id[] = {
+ { "fec(TXF)", 23 },
+ { "fec(TXB)", 24 },
+ { "fec(TXFIFO)", 25 },
+ { "fec(TXCR)", 26 },
+ { "fec(RXF)", 27 },
+ { "fec(RXB)", 28 },
+ { "fec(MII)", 29 },
+ { "fec(LC)", 30 },
+ { "fec(HBERR)", 31 },
+ { "fec(GRA)", 32 },
+ { "fec(EBERR)", 33 },
+ { "fec(BABT)", 34 },
+ { "fec(BABR)", 35 },
+ { NULL },
+ };
+
+ fep = netdev_priv(dev);
+ b = 64 + 13;
+
+ /* Setup interrupt handlers. */
+ for (idp = id; idp->name; idp++) {
+ if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0)
+ printk("FEC: Could not allocate %s IRQ(%d)!\n", idp->name, b+idp->irq);
+ }
+
+ /* Unmask interrupts at ColdFire interrupt controller */
+ {
+ volatile unsigned char *icrp;
+ volatile unsigned long *imrp;
+
+ icrp = (volatile unsigned char *) (MCF_IPSBAR + MCFICM_INTC0 +
+ MCFINTC_ICR0);
+ for (b = 36; (b < 49); b++)
+ icrp[b] = 0x04;
+ imrp = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 +
+ MCFINTC_IMRH);
+ *imrp &= ~0x0001FFF0;
+ }
+ *(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FEC) |= 0xf0;
+ *(volatile unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C) |= 0x0f;
+}
+
+static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
+{
+ volatile fec_t *fecp;
+
+ fecp = fep->hwp;
+ fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
+ fecp->fec_x_cntrl = 0x00;
+
+ /*
+ * Set MII speed to 2.5 MHz
+ * See 5282 manual section 17.5.4.7: MSCR
+ */
+ fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
+ fecp->fec_mii_speed = fep->phy_speed;
+
+ fec_restart(dev, 0);
+}
+
+static void __inline__ fec_get_mac(struct net_device *dev)
+{
+ struct fec_enet_private *fep = netdev_priv(dev);
+ volatile fec_t *fecp;
+ unsigned char *iap, tmpaddr[ETH_ALEN];
+
+ fecp = fep->hwp;
+
+ if (FEC_FLASHMAC) {
+ /*
+ * Get MAC address from FLASH.
+ * If it is all 1's or 0's, use the default.
+ */
+ iap = FEC_FLASHMAC;
+ if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
+ (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
+ iap = fec_mac_default;
+ if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&
+ (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
+ iap = fec_mac_default;
+ } else {
+ *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;
+ *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);
+ iap = &tmpaddr[0];
+ }
+
+ memcpy(dev->dev_addr, iap, ETH_ALEN);
+
+ /* Adjust MAC if using default MAC address */
+ if (iap == fec_mac_default)
+ dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
+}
+
+static void __inline__ fec_enable_phy_intr(void)
+{
+}
+
+static void __inline__ fec_disable_phy_intr(void)
+{
+}
+
+static void __inline__ fec_phy_ack_intr(void)
+{
+}
+
+static void __inline__ fec_localhw_setup(void)
+{
+}
+
+static void __inline__ fec_uncache(unsigned long addr)
+{
+}
+
+/* ------------------------------------------------------------------------- */
+
#else
/*
@@ -1952,6 +2148,14 @@ int __init fec_enet_init(struct net_device *dev)
if (index >= FEC_MAX_PORTS)
return -ENXIO;
+ /* Allocate memory for buffer descriptors.
+ */
+ mem_addr = __get_free_page(GFP_KERNEL);
+ if (mem_addr == 0) {
+ printk("FEC: allocate descriptor memory failed?\n");
+ return -ENOMEM;
+ }
+
/* Create an Ethernet device instance.
*/
fecp = (volatile fec_t *) fec_hw[index];
@@ -1964,16 +2168,6 @@ int __init fec_enet_init(struct net_device *dev)
fecp->fec_ecntrl = 1;
udelay(10);
- /* Clear and enable interrupts */
- fecp->fec_ievent = 0xffc00000;
- fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
- FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
- fecp->fec_hash_table_high = 0;
- fecp->fec_hash_table_low = 0;
- fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
- fecp->fec_ecntrl = 2;
- fecp->fec_r_des_active = 0x01000000;
-
/* Set the Ethernet address. If using multiple Enets on the 8xx,
* this needs some work to get unique addresses.
*
@@ -1982,14 +2176,6 @@ int __init fec_enet_init(struct net_device *dev)
*/
fec_get_mac(dev);
- /* Allocate memory for buffer descriptors.
- */
- if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) {
- printk("FEC init error. Need more space.\n");
- printk("FEC initialization failed.\n");
- return 1;
- }
- mem_addr = __get_free_page(GFP_KERNEL);
cbd_base = (cbd_t *)mem_addr;
/* XXX: missing check for allocation failure */
@@ -2067,6 +2253,16 @@ int __init fec_enet_init(struct net_device *dev)
*/
fec_request_intrs(dev);
+ /* Clear and enable interrupts */
+ fecp->fec_ievent = 0xffc00000;
+ fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
+ FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+ fecp->fec_hash_table_high = 0;
+ fecp->fec_hash_table_low = 0;
+ fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+ fecp->fec_ecntrl = 2;
+ fecp->fec_r_des_active = 0x01000000;
+
dev->base_addr = (unsigned long)fecp;
/* The FEC Ethernet specific entries in the device structure. */
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index 045761b8a600..965c5c49fcdc 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -1,11 +1,10 @@
/****************************************************************************/
/*
- * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5230,
- * 5231, 5232, 5234, 5235, 5270, 5271, 5272, 5274, 5275,
- * 5280 and 5282.
+ * fec.h -- Fast Ethernet Controller for Motorola ColdFire SoC
+ * processors.
*
- * (C) Copyright 2000-2003, Greg Ungerer (gerg@snapgear.com)
+ * (C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com)
* (C) Copyright 2000-2001, Lineo (www.lineo.com)
*/
@@ -14,7 +13,8 @@
#define FEC_H
/****************************************************************************/
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+ defined(CONFIG_M520x)
/*
* Just figures, Motorola would have to change the offsets for
* registers in the same peripheral device on different models
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index 6e6f42d01e64..4b48b31ec235 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -78,17 +78,15 @@ static void parse_data(struct parport *port, int device, char *str)
u++;
}
if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
- if (info->mfr)
- kfree (info->mfr);
+ kfree(info->mfr);
info->mfr = kstrdup(sep, GFP_KERNEL);
} else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
- if (info->model)
- kfree (info->model);
+ kfree(info->model);
info->model = kstrdup(sep, GFP_KERNEL);
} else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
int i;
- if (info->class_name)
- kfree (info->class_name);
+
+ kfree(info->class_name);
info->class_name = kstrdup(sep, GFP_KERNEL);
for (u = sep; *u; u++)
*u = toupper(*u);
@@ -102,21 +100,22 @@ static void parse_data(struct parport *port, int device, char *str)
info->class = PARPORT_CLASS_OTHER;
} else if (!strcmp(p, "CMD") ||
!strcmp(p, "COMMAND SET")) {
- if (info->cmdset)
- kfree (info->cmdset);
+ kfree(info->cmdset);
info->cmdset = kstrdup(sep, GFP_KERNEL);
/* if it speaks printer language, it's
probably a printer */
if (strstr(sep, "PJL") || strstr(sep, "PCL"))
guessed_class = PARPORT_CLASS_PRINTER;
} else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
- if (info->description)
- kfree (info->description);
+ kfree(info->description);
info->description = kstrdup(sep, GFP_KERNEL);
}
}
rock_on:
- if (q) p = q+1; else p=NULL;
+ if (q)
+ p = q + 1;
+ else
+ p = NULL;
}
/* If the device didn't tell us its class, maybe we have managed to
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index ae7becf7efa5..9cb3ab156b09 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -202,16 +202,11 @@ static void free_port (struct parport *port)
list_del(&port->full_list);
spin_unlock(&full_list_lock);
for (d = 0; d < 5; d++) {
- if (port->probe_info[d].class_name)
- kfree (port->probe_info[d].class_name);
- if (port->probe_info[d].mfr)
- kfree (port->probe_info[d].mfr);
- if (port->probe_info[d].model)
- kfree (port->probe_info[d].model);
- if (port->probe_info[d].cmdset)
- kfree (port->probe_info[d].cmdset);
- if (port->probe_info[d].description)
- kfree (port->probe_info[d].description);
+ kfree(port->probe_info[d].class_name);
+ kfree(port->probe_info[d].mfr);
+ kfree(port->probe_info[d].model);
+ kfree(port->probe_info[d].cmdset);
+ kfree(port->probe_info[d].description);
}
kfree(port->name);
@@ -618,9 +613,9 @@ parport_register_device(struct parport *port, const char *name,
return tmp;
out_free_all:
- kfree (tmp->state);
+ kfree(tmp->state);
out_free_pardevice:
- kfree (tmp);
+ kfree(tmp);
out:
parport_put_port (port);
module_put(port->ops->owner);
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
index 93e39c4096a9..00b81a7bdd26 100644
--- a/drivers/pci/hotplug/cpqphp_pci.c
+++ b/drivers/pci/hotplug/cpqphp_pci.c
@@ -259,8 +259,7 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
sizeof(struct irq_routing_table)) / sizeof(struct irq_info);
// Make sure I got at least one entry
if (len == 0) {
- if (PCIIRQRoutingInfoLength != NULL)
- kfree(PCIIRQRoutingInfoLength );
+ kfree(PCIIRQRoutingInfoLength );
return -1;
}
@@ -275,8 +274,7 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
ctrl->pci_bus->number = tbus;
pci_bus_read_config_dword (ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
if (!nobridge || (work == 0xffffffff)) {
- if (PCIIRQRoutingInfoLength != NULL)
- kfree(PCIIRQRoutingInfoLength );
+ kfree(PCIIRQRoutingInfoLength );
return 0;
}
@@ -289,20 +287,17 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num
dbg("Scan bus for Non Bridge: bus %d\n", tbus);
if (PCI_ScanBusForNonBridge(ctrl, tbus, dev_num) == 0) {
*bus_num = tbus;
- if (PCIIRQRoutingInfoLength != NULL)
- kfree(PCIIRQRoutingInfoLength );
+ kfree(PCIIRQRoutingInfoLength );
return 0;
}
} else {
- if (PCIIRQRoutingInfoLength != NULL)
- kfree(PCIIRQRoutingInfoLength );
+ kfree(PCIIRQRoutingInfoLength );
return 0;
}
}
}
- if (PCIIRQRoutingInfoLength != NULL)
- kfree(PCIIRQRoutingInfoLength );
+ kfree(PCIIRQRoutingInfoLength );
return -1;
}
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c
index 33b2c69a0829..76c727c74cc0 100644
--- a/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ b/drivers/pci/hotplug/pciehprm_nonacpi.c
@@ -31,6 +31,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/slab.h>
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index ae986e590b48..94e68c54d273 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -10,6 +10,7 @@
#include <linux/mempolicy.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#include "pci.h"
/*
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 3afb682255a0..2dc3e611a9a3 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -334,10 +334,8 @@ void destroy_cis_cache(struct pcmcia_socket *s)
/*
* If there was a fake CIS, destroy that as well.
*/
- if (s->fake_cis) {
- kfree(s->fake_cis);
- s->fake_cis = NULL;
- }
+ kfree(s->fake_cis);
+ s->fake_cis = NULL;
}
EXPORT_SYMBOL(destroy_cis_cache);
@@ -386,10 +384,8 @@ int verify_cis_cache(struct pcmcia_socket *s)
int pcmcia_replace_cis(struct pcmcia_socket *s, cisdump_t *cis)
{
- if (s->fake_cis != NULL) {
- kfree(s->fake_cis);
- s->fake_cis = NULL;
- }
+ kfree(s->fake_cis);
+ s->fake_cis = NULL;
if (cis->Length > CISTPL_MAX_CIS_SIZE)
return CS_BAD_SIZE;
s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index d5e76423a0ee..234cdca6fe13 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -331,10 +331,8 @@ static void shutdown_socket(struct pcmcia_socket *s)
cb_free(s);
#endif
s->functions = 0;
- if (s->config) {
- kfree(s->config);
- s->config = NULL;
- }
+ kfree(s->config);
+ s->config = NULL;
{
int status;
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index e95ed67d4f05..bd7c966ea2d7 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -12,7 +12,7 @@
#include "base.h"
LIST_HEAD(pnp_cards);
-LIST_HEAD(pnp_card_drivers);
+static LIST_HEAD(pnp_card_drivers);
static const struct pnp_card_device_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card)
@@ -374,11 +374,13 @@ void pnp_unregister_card_driver(struct pnp_card_driver * drv)
pnp_unregister_driver(&drv->link);
}
+#if 0
EXPORT_SYMBOL(pnp_add_card);
EXPORT_SYMBOL(pnp_remove_card);
EXPORT_SYMBOL(pnp_add_card_device);
EXPORT_SYMBOL(pnp_remove_card_device);
EXPORT_SYMBOL(pnp_add_card_id);
+#endif /* 0 */
EXPORT_SYMBOL(pnp_request_card_device);
EXPORT_SYMBOL(pnp_release_card_device);
EXPORT_SYMBOL(pnp_register_card_driver);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index deed92459bc5..aec83ec5ea23 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -158,13 +158,14 @@ void __pnp_remove_device(struct pnp_dev *dev)
*
* this function will free all mem used by dev
*/
-
+#if 0
void pnp_remove_device(struct pnp_dev *dev)
{
if (!dev || dev->card)
return;
__pnp_remove_device(dev);
}
+#endif /* 0 */
static int __init pnp_init(void)
{
@@ -174,7 +175,9 @@ static int __init pnp_init(void)
subsys_initcall(pnp_init);
+#if 0
EXPORT_SYMBOL(pnp_register_protocol);
EXPORT_SYMBOL(pnp_unregister_protocol);
EXPORT_SYMBOL(pnp_add_device);
EXPORT_SYMBOL(pnp_remove_device);
+#endif /* 0 */
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index 33da25f3213f..d3ccce706ab4 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -214,6 +214,8 @@ int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev)
EXPORT_SYMBOL(pnp_register_driver);
EXPORT_SYMBOL(pnp_unregister_driver);
+#if 0
EXPORT_SYMBOL(pnp_add_id);
+#endif
EXPORT_SYMBOL(pnp_device_attach);
EXPORT_SYMBOL(pnp_device_detach);
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index beedd86800f4..57fd60314d59 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -941,7 +941,9 @@ EXPORT_SYMBOL(isapnp_protocol);
EXPORT_SYMBOL(isapnp_present);
EXPORT_SYMBOL(isapnp_cfg_begin);
EXPORT_SYMBOL(isapnp_cfg_end);
+#if 0
EXPORT_SYMBOL(isapnp_read_byte);
+#endif
EXPORT_SYMBOL(isapnp_write_byte);
static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res)
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index cbb2749db178..261668618b2d 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -555,7 +555,9 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne
EXPORT_SYMBOL(pnp_manual_config_dev);
+#if 0
EXPORT_SYMBOL(pnp_auto_config_dev);
+#endif
EXPORT_SYMBOL(pnp_activate_dev);
EXPORT_SYMBOL(pnp_disable_dev);
EXPORT_SYMBOL(pnp_resource_change);
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 1a8915e74160..816479ad217b 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -117,7 +117,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
return ACPI_FAILURE(status) ? -ENODEV : 0;
}
-struct pnp_protocol pnpacpi_protocol = {
+static struct pnp_protocol pnpacpi_protocol = {
.name = "Plug and Play ACPI",
.get = pnpacpi_get_resources,
.set = pnpacpi_set_resources,
@@ -234,7 +234,7 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle,
}
int pnpacpi_disabled __initdata;
-int __init pnpacpi_init(void)
+static int __init pnpacpi_init(void)
{
if (acpi_disabled || pnpacpi_disabled) {
pnp_info("PnP ACPI: disabled");
@@ -258,4 +258,6 @@ static int __init pnpacpi_setup(char *str)
}
__setup("pnpacpi=", pnpacpi_setup);
+#if 0
EXPORT_SYMBOL(pnpacpi_protocol);
+#endif
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 887ad8939349..6ded527169f4 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -477,12 +477,14 @@ int pnp_check_dma(struct pnp_dev * dev, int idx)
}
+#if 0
EXPORT_SYMBOL(pnp_register_dependent_option);
EXPORT_SYMBOL(pnp_register_independent_option);
EXPORT_SYMBOL(pnp_register_irq_resource);
EXPORT_SYMBOL(pnp_register_dma_resource);
EXPORT_SYMBOL(pnp_register_port_resource);
EXPORT_SYMBOL(pnp_register_mem_resource);
+#endif /* 0 */
/* format is: pnp_reserve_irq=irq1[,irq2] .... */
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
new file mode 100644
index 000000000000..0b2d2c3579a7
--- /dev/null
+++ b/drivers/rapidio/Kconfig
@@ -0,0 +1,18 @@
+#
+# RapidIO configuration
+#
+config RAPIDIO_8_BIT_TRANSPORT
+ bool "8-bit transport addressing"
+ depends on RAPIDIO
+ ---help---
+ By default, the kernel assumes a 16-bit addressed RapidIO
+ network. By selecting this option, the kernel will support
+ an 8-bit addressed network.
+
+config RAPIDIO_DISC_TIMEOUT
+ int "Discovery timeout duration (seconds)"
+ depends on RAPIDIO
+ default "30"
+ ---help---
+ Amount of time a discovery node waits for a host to complete
+ enumeration beforing giving up.
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile
new file mode 100644
index 000000000000..7c0e1818de51
--- /dev/null
+++ b/drivers/rapidio/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for RapidIO interconnect services
+#
+obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
+
+obj-$(CONFIG_RAPIDIO) += switches/
diff --git a/drivers/rapidio/rio-access.c b/drivers/rapidio/rio-access.c
new file mode 100644
index 000000000000..b9fab2ae3a36
--- /dev/null
+++ b/drivers/rapidio/rio-access.c
@@ -0,0 +1,175 @@
+/*
+ * RapidIO configuration space access support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/rio.h>
+#include <linux/module.h>
+
+/*
+ * These interrupt-safe spinlocks protect all accesses to RIO
+ * configuration space and doorbell access.
+ */
+static spinlock_t rio_config_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t rio_doorbell_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Wrappers for all RIO configuration access functions. They just check
+ * alignment, do locking and call the low-level functions pointed to
+ * by rio_mport->ops.
+ */
+
+#define RIO_8_BAD 0
+#define RIO_16_BAD (offset & 1)
+#define RIO_32_BAD (offset & 3)
+
+/**
+ * RIO_LOP_READ - Generate rio_local_read_config_* functions
+ * @size: Size of configuration space read (8, 16, 32 bits)
+ * @type: C type of value argument
+ * @len: Length of configuration space read (1, 2, 4 bytes)
+ *
+ * Generates rio_local_read_config_* functions used to access
+ * configuration space registers on the local device.
+ */
+#define RIO_LOP_READ(size,type,len) \
+int __rio_local_read_config_##size \
+ (struct rio_mport *mport, u32 offset, type *value) \
+{ \
+ int res; \
+ unsigned long flags; \
+ u32 data = 0; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+ res = mport->ops->lcread(mport->id, offset, len, &data); \
+ *value = (type)data; \
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+}
+
+/**
+ * RIO_LOP_WRITE - Generate rio_local_write_config_* functions
+ * @size: Size of configuration space write (8, 16, 32 bits)
+ * @type: C type of value argument
+ * @len: Length of configuration space write (1, 2, 4 bytes)
+ *
+ * Generates rio_local_write_config_* functions used to access
+ * configuration space registers on the local device.
+ */
+#define RIO_LOP_WRITE(size,type,len) \
+int __rio_local_write_config_##size \
+ (struct rio_mport *mport, u32 offset, type value) \
+{ \
+ int res; \
+ unsigned long flags; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+ res = mport->ops->lcwrite(mport->id, offset, len, value); \
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+}
+
+RIO_LOP_READ(8, u8, 1)
+RIO_LOP_READ(16, u16, 2)
+RIO_LOP_READ(32, u32, 4)
+RIO_LOP_WRITE(8, u8, 1)
+RIO_LOP_WRITE(16, u16, 2)
+RIO_LOP_WRITE(32, u32, 4)
+
+EXPORT_SYMBOL_GPL(__rio_local_read_config_8);
+EXPORT_SYMBOL_GPL(__rio_local_read_config_16);
+EXPORT_SYMBOL_GPL(__rio_local_read_config_32);
+EXPORT_SYMBOL_GPL(__rio_local_write_config_8);
+EXPORT_SYMBOL_GPL(__rio_local_write_config_16);
+EXPORT_SYMBOL_GPL(__rio_local_write_config_32);
+
+/**
+ * RIO_OP_READ - Generate rio_mport_read_config_* functions
+ * @size: Size of configuration space read (8, 16, 32 bits)
+ * @type: C type of value argument
+ * @len: Length of configuration space read (1, 2, 4 bytes)
+ *
+ * Generates rio_mport_read_config_* functions used to access
+ * configuration space registers on the local device.
+ */
+#define RIO_OP_READ(size,type,len) \
+int rio_mport_read_config_##size \
+ (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \
+{ \
+ int res; \
+ unsigned long flags; \
+ u32 data = 0; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+ res = mport->ops->cread(mport->id, destid, hopcount, offset, len, &data); \
+ *value = (type)data; \
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+}
+
+/**
+ * RIO_OP_WRITE - Generate rio_mport_write_config_* functions
+ * @size: Size of configuration space write (8, 16, 32 bits)
+ * @type: C type of value argument
+ * @len: Length of configuration space write (1, 2, 4 bytes)
+ *
+ * Generates rio_mport_write_config_* functions used to access
+ * configuration space registers on the local device.
+ */
+#define RIO_OP_WRITE(size,type,len) \
+int rio_mport_write_config_##size \
+ (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \
+{ \
+ int res; \
+ unsigned long flags; \
+ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \
+ spin_lock_irqsave(&rio_config_lock, flags); \
+ res = mport->ops->cwrite(mport->id, destid, hopcount, offset, len, value); \
+ spin_unlock_irqrestore(&rio_config_lock, flags); \
+ return res; \
+}
+
+RIO_OP_READ(8, u8, 1)
+RIO_OP_READ(16, u16, 2)
+RIO_OP_READ(32, u32, 4)
+RIO_OP_WRITE(8, u8, 1)
+RIO_OP_WRITE(16, u16, 2)
+RIO_OP_WRITE(32, u32, 4)
+
+EXPORT_SYMBOL_GPL(rio_mport_read_config_8);
+EXPORT_SYMBOL_GPL(rio_mport_read_config_16);
+EXPORT_SYMBOL_GPL(rio_mport_read_config_32);
+EXPORT_SYMBOL_GPL(rio_mport_write_config_8);
+EXPORT_SYMBOL_GPL(rio_mport_write_config_16);
+EXPORT_SYMBOL_GPL(rio_mport_write_config_32);
+
+/**
+ * rio_mport_send_doorbell - Send a doorbell message
+ *
+ * @mport: RIO master port
+ * @destid: RIO device destination ID
+ * @data: Doorbell message data
+ *
+ * Send a doorbell message to a RIO device. The doorbell message
+ * has a 16-bit info field provided by the data argument.
+ */
+int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
+{
+ int res;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rio_doorbell_lock, flags);
+ res = mport->ops->dsend(mport->id, destid, data);
+ spin_unlock_irqrestore(&rio_doorbell_lock, flags);
+
+ return res;
+}
+
+EXPORT_SYMBOL_GPL(rio_mport_send_doorbell);
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
new file mode 100644
index 000000000000..dc749609699a
--- /dev/null
+++ b/drivers/rapidio/rio-driver.c
@@ -0,0 +1,229 @@
+/*
+ * RapidIO driver support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/rio.h>
+#include <linux/rio_ids.h>
+
+#include "rio.h"
+
+/**
+ * rio_match_device - Tell if a RIO device has a matching RIO device id structure
+ * @id: the RIO device id structure to match against
+ * @rdev: the RIO device structure to match against
+ *
+ * Used from driver probe and bus matching to check whether a RIO device
+ * matches a device id structure provided by a RIO driver. Returns the
+ * matching &struct rio_device_id or %NULL if there is no match.
+ */
+static const struct rio_device_id *rio_match_device(const struct rio_device_id
+ *id,
+ const struct rio_dev *rdev)
+{
+ while (id->vid || id->asm_vid) {
+ if (((id->vid == RIO_ANY_ID) || (id->vid == rdev->vid)) &&
+ ((id->did == RIO_ANY_ID) || (id->did == rdev->did)) &&
+ ((id->asm_vid == RIO_ANY_ID)
+ || (id->asm_vid == rdev->asm_vid))
+ && ((id->asm_did == RIO_ANY_ID)
+ || (id->asm_did == rdev->asm_did)))
+ return id;
+ id++;
+ }
+ return NULL;
+}
+
+/**
+ * rio_dev_get - Increments the reference count of the RIO device structure
+ *
+ * @rdev: RIO device being referenced
+ *
+ * Each live reference to a device should be refcounted.
+ *
+ * Drivers for RIO devices should normally record such references in
+ * their probe() methods, when they bind to a device, and release
+ * them by calling rio_dev_put(), in their disconnect() methods.
+ */
+struct rio_dev *rio_dev_get(struct rio_dev *rdev)
+{
+ if (rdev)
+ get_device(&rdev->dev);
+
+ return rdev;
+}
+
+/**
+ * rio_dev_put - Release a use of the RIO device structure
+ *
+ * @rdev: RIO device being disconnected
+ *
+ * Must be called when a user of a device is finished with it.
+ * When the last user of the device calls this function, the
+ * memory of the device is freed.
+ */
+void rio_dev_put(struct rio_dev *rdev)
+{
+ if (rdev)
+ put_device(&rdev->dev);
+}
+
+/**
+ * rio_device_probe - Tell if a RIO device structure has a matching RIO
+ * device id structure
+ * @id: the RIO device id structure to match against
+ * @dev: the RIO device structure to match against
+ *
+ * return 0 and set rio_dev->driver when drv claims rio_dev, else error
+ */
+static int rio_device_probe(struct device *dev)
+{
+ struct rio_driver *rdrv = to_rio_driver(dev->driver);
+ struct rio_dev *rdev = to_rio_dev(dev);
+ int error = -ENODEV;
+ const struct rio_device_id *id;
+
+ if (!rdev->driver && rdrv->probe) {
+ if (!rdrv->id_table)
+ return error;
+ id = rio_match_device(rdrv->id_table, rdev);
+ rio_dev_get(rdev);
+ if (id)
+ error = rdrv->probe(rdev, id);
+ if (error >= 0) {
+ rdev->driver = rdrv;
+ error = 0;
+ rio_dev_put(rdev);
+ }
+ }
+ return error;
+}
+
+/**
+ * rio_device_remove - Remove a RIO device from the system
+ *
+ * @dev: the RIO device structure to match against
+ *
+ * Remove a RIO device from the system. If it has an associated
+ * driver, then run the driver remove() method. Then update
+ * the reference count.
+ */
+static int rio_device_remove(struct device *dev)
+{
+ struct rio_dev *rdev = to_rio_dev(dev);
+ struct rio_driver *rdrv = rdev->driver;
+
+ if (rdrv) {
+ if (rdrv->remove)
+ rdrv->remove(rdev);
+ rdev->driver = NULL;
+ }
+
+ rio_dev_put(rdev);
+
+ return 0;
+}
+
+/**
+ * rio_register_driver - register a new RIO driver
+ * @rdrv: the RIO driver structure to register
+ *
+ * Adds a &struct rio_driver to the list of registered drivers
+ * Returns a negative value on error, otherwise 0. If no error
+ * occurred, the driver remains registered even if no device
+ * was claimed during registration.
+ */
+int rio_register_driver(struct rio_driver *rdrv)
+{
+ /* initialize common driver fields */
+ rdrv->driver.name = rdrv->name;
+ rdrv->driver.bus = &rio_bus_type;
+ rdrv->driver.probe = rio_device_probe;
+ rdrv->driver.remove = rio_device_remove;
+
+ /* register with core */
+ return driver_register(&rdrv->driver);
+}
+
+/**
+ * rio_unregister_driver - unregister a RIO driver
+ * @rdrv: the RIO driver structure to unregister
+ *
+ * Deletes the &struct rio_driver from the list of registered RIO
+ * drivers, gives it a chance to clean up by calling its remove()
+ * function for each device it was responsible for, and marks those
+ * devices as driverless.
+ */
+void rio_unregister_driver(struct rio_driver *rdrv)
+{
+ driver_unregister(&rdrv->driver);
+}
+
+/**
+ * rio_match_bus - Tell if a RIO device structure has a matching RIO
+ * driver device id structure
+ * @dev: the standard device structure to match against
+ * @drv: the standard driver structure containing the ids to match against
+ *
+ * Used by a driver to check whether a RIO device present in the
+ * system is in its list of supported devices. Returns 1 if
+ * there is a matching &struct rio_device_id or 0 if there is
+ * no match.
+ */
+static int rio_match_bus(struct device *dev, struct device_driver *drv)
+{
+ struct rio_dev *rdev = to_rio_dev(dev);
+ struct rio_driver *rdrv = to_rio_driver(drv);
+ const struct rio_device_id *id = rdrv->id_table;
+ const struct rio_device_id *found_id;
+
+ if (!id)
+ goto out;
+
+ found_id = rio_match_device(id, rdev);
+
+ if (found_id)
+ return 1;
+
+ out:return 0;
+}
+
+static struct device rio_bus = {
+ .bus_id = "rapidio",
+};
+
+struct bus_type rio_bus_type = {
+ .name = "rapidio",
+ .match = rio_match_bus,
+ .dev_attrs = rio_dev_attrs
+};
+
+/**
+ * rio_bus_init - Register the RapidIO bus with the device model
+ *
+ * Registers the RIO bus device and RIO bus type with the Linux
+ * device model.
+ */
+static int __init rio_bus_init(void)
+{
+ if (device_register(&rio_bus) < 0)
+ printk("RIO: failed to register RIO bus device\n");
+ return bus_register(&rio_bus_type);
+}
+
+postcore_initcall(rio_bus_init);
+
+EXPORT_SYMBOL_GPL(rio_register_driver);
+EXPORT_SYMBOL_GPL(rio_unregister_driver);
+EXPORT_SYMBOL_GPL(rio_bus_type);
+EXPORT_SYMBOL_GPL(rio_dev_get);
+EXPORT_SYMBOL_GPL(rio_dev_put);
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
new file mode 100644
index 000000000000..4f7ed4bd3be9
--- /dev/null
+++ b/drivers/rapidio/rio-scan.c
@@ -0,0 +1,945 @@
+/*
+ * RapidIO enumeration and discovery support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+#include <linux/rio_regs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+
+#include "rio.h"
+
+LIST_HEAD(rio_devices);
+static LIST_HEAD(rio_switches);
+
+#define RIO_ENUM_CMPL_MAGIC 0xdeadbeef
+
+static void rio_enum_timeout(unsigned long);
+
+DEFINE_SPINLOCK(rio_global_list_lock);
+
+static int next_destid = 0;
+static int next_switchid = 0;
+static int next_net = 0;
+
+static struct timer_list rio_enum_timer =
+TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
+
+static int rio_mport_phys_table[] = {
+ RIO_EFB_PAR_EP_ID,
+ RIO_EFB_PAR_EP_REC_ID,
+ RIO_EFB_SER_EP_ID,
+ RIO_EFB_SER_EP_REC_ID,
+ -1,
+};
+
+static int rio_sport_phys_table[] = {
+ RIO_EFB_PAR_EP_FREE_ID,
+ RIO_EFB_SER_EP_FREE_ID,
+ -1,
+};
+
+/**
+ * rio_get_device_id - Get the base/extended device id for a device
+ * @port: RIO master port
+ * @destid: Destination ID of device
+ * @hopcount: Hopcount to device
+ *
+ * Reads the base/extended device id from a device. Returns the
+ * 8/16-bit device ID.
+ */
+static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
+{
+ u32 result;
+
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result);
+
+ return RIO_GET_DID(result);
+}
+
+/**
+ * rio_set_device_id - Set the base/extended device id for a device
+ * @port: RIO master port
+ * @destid: Destination ID of device
+ * @hopcount: Hopcount to device
+ * @did: Device ID value to be written
+ *
+ * Writes the base/extended device id from a device.
+ */
+static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did)
+{
+ rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR,
+ RIO_SET_DID(did));
+}
+
+/**
+ * rio_local_set_device_id - Set the base/extended device id for a port
+ * @port: RIO master port
+ * @did: Device ID value to be written
+ *
+ * Writes the base/extended device id from a device.
+ */
+static void rio_local_set_device_id(struct rio_mport *port, u16 did)
+{
+ rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(did));
+}
+
+/**
+ * rio_clear_locks- Release all host locks and signal enumeration complete
+ * @port: Master port to issue transaction
+ *
+ * Marks the component tag CSR on each device with the enumeration
+ * complete flag. When complete, it then release the host locks on
+ * each device. Returns 0 on success or %-EINVAL on failure.
+ */
+static int rio_clear_locks(struct rio_mport *port)
+{
+ struct rio_dev *rdev;
+ u32 result;
+ int ret = 0;
+
+ /* Write component tag CSR magic complete value */
+ rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR,
+ RIO_ENUM_CMPL_MAGIC);
+ list_for_each_entry(rdev, &rio_devices, global_list)
+ rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR,
+ RIO_ENUM_CMPL_MAGIC);
+
+ /* Release host device id locks */
+ rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) != 0xffff) {
+ printk(KERN_INFO
+ "RIO: badness when releasing host lock on master port, result %8.8x\n",
+ result);
+ ret = -EINVAL;
+ }
+ list_for_each_entry(rdev, &rio_devices, global_list) {
+ rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) != 0xffff) {
+ printk(KERN_INFO
+ "RIO: badness when releasing host lock on vid %4.4x did %4.4x\n",
+ rdev->vid, rdev->did);
+ ret = -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * rio_enum_host- Set host lock and initialize host destination ID
+ * @port: Master port to issue transaction
+ *
+ * Sets the local host master port lock and destination ID register
+ * with the host device ID value. The host device ID value is provided
+ * by the platform. Returns %0 on success or %-1 on failure.
+ */
+static int rio_enum_host(struct rio_mport *port)
+{
+ u32 result;
+
+ /* Set master port host device id lock */
+ rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+
+ rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) != port->host_deviceid)
+ return -1;
+
+ /* Set master port destid and init destid ctr */
+ rio_local_set_device_id(port, port->host_deviceid);
+
+ if (next_destid == port->host_deviceid)
+ next_destid++;
+
+ return 0;
+}
+
+/**
+ * rio_device_has_destid- Test if a device contains a destination ID register
+ * @port: Master port to issue transaction
+ * @src_ops: RIO device source operations
+ * @dst_ops: RIO device destination operations
+ *
+ * Checks the provided @src_ops and @dst_ops for the necessary transaction
+ * capabilities that indicate whether or not a device will implement a
+ * destination ID register. Returns 1 if true or 0 if false.
+ */
+static int rio_device_has_destid(struct rio_mport *port, int src_ops,
+ int dst_ops)
+{
+ u32 mask = RIO_OPS_READ | RIO_OPS_WRITE | RIO_OPS_ATOMIC_TST_SWP | RIO_OPS_ATOMIC_INC | RIO_OPS_ATOMIC_DEC | RIO_OPS_ATOMIC_SET | RIO_OPS_ATOMIC_CLR;
+
+ return !!((src_ops | dst_ops) & mask);
+}
+
+/**
+ * rio_release_dev- Frees a RIO device struct
+ * @dev: LDM device associated with a RIO device struct
+ *
+ * Gets the RIO device struct associated a RIO device struct.
+ * The RIO device struct is freed.
+ */
+static void rio_release_dev(struct device *dev)
+{
+ struct rio_dev *rdev;
+
+ rdev = to_rio_dev(dev);
+ kfree(rdev);
+}
+
+/**
+ * rio_is_switch- Tests if a RIO device has switch capabilities
+ * @rdev: RIO device
+ *
+ * Gets the RIO device Processing Element Features register
+ * contents and tests for switch capabilities. Returns 1 if
+ * the device is a switch or 0 if it is not a switch.
+ * The RIO device struct is freed.
+ */
+static int rio_is_switch(struct rio_dev *rdev)
+{
+ if (rdev->pef & RIO_PEF_SWITCH)
+ return 1;
+ return 0;
+}
+
+/**
+ * rio_route_set_ops- Sets routing operations for a particular vendor switch
+ * @rdev: RIO device
+ *
+ * Searches the RIO route ops table for known switch types. If the vid
+ * and did match a switch table entry, then set the add_entry() and
+ * get_entry() ops to the table entry values.
+ */
+static void rio_route_set_ops(struct rio_dev *rdev)
+{
+ struct rio_route_ops *cur = __start_rio_route_ops;
+ struct rio_route_ops *end = __end_rio_route_ops;
+
+ while (cur < end) {
+ if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
+ pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev));
+ rdev->rswitch->add_entry = cur->add_hook;
+ rdev->rswitch->get_entry = cur->get_hook;
+ }
+ cur++;
+ }
+
+ if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
+ printk(KERN_ERR "RIO: missing routing ops for %s\n",
+ rio_name(rdev));
+}
+
+/**
+ * rio_add_device- Adds a RIO device to the device model
+ * @rdev: RIO device
+ *
+ * Adds the RIO device to the global device list and adds the RIO
+ * device to the RIO device list. Creates the generic sysfs nodes
+ * for an RIO device.
+ */
+static void __devinit rio_add_device(struct rio_dev *rdev)
+{
+ device_add(&rdev->dev);
+
+ spin_lock(&rio_global_list_lock);
+ list_add_tail(&rdev->global_list, &rio_devices);
+ spin_unlock(&rio_global_list_lock);
+
+ rio_create_sysfs_dev_files(rdev);
+}
+
+/**
+ * rio_setup_device- Allocates and sets up a RIO device
+ * @net: RIO network
+ * @port: Master port to send transactions
+ * @destid: Current destination ID
+ * @hopcount: Current hopcount
+ * @do_enum: Enumeration/Discovery mode flag
+ *
+ * Allocates a RIO device and configures fields based on configuration
+ * space contents. If device has a destination ID register, a destination
+ * ID is either assigned in enumeration mode or read from configuration
+ * space in discovery mode. If the device has switch capabilities, then
+ * a switch is allocated and configured appropriately. Returns a pointer
+ * to a RIO device on success or NULL on failure.
+ *
+ */
+static struct rio_dev *rio_setup_device(struct rio_net *net,
+ struct rio_mport *port, u16 destid,
+ u8 hopcount, int do_enum)
+{
+ struct rio_dev *rdev;
+ struct rio_switch *rswitch;
+ int result, rdid;
+
+ rdev = kmalloc(sizeof(struct rio_dev), GFP_KERNEL);
+ if (!rdev)
+ goto out;
+
+ memset(rdev, 0, sizeof(struct rio_dev));
+ rdev->net = net;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR,
+ &result);
+ rdev->did = result >> 16;
+ rdev->vid = result & 0xffff;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_INFO_CAR,
+ &rdev->device_rev);
+ rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_ID_CAR,
+ &result);
+ rdev->asm_did = result >> 16;
+ rdev->asm_vid = result & 0xffff;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR,
+ &result);
+ rdev->asm_rev = result >> 16;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR,
+ &rdev->pef);
+ if (rdev->pef & RIO_PEF_EXT_FEATURES)
+ rdev->efptr = result & 0xffff;
+
+ rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
+ &rdev->src_ops);
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
+ &rdev->dst_ops);
+
+ if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)
+ && do_enum) {
+ rio_set_device_id(port, destid, hopcount, next_destid);
+ rdev->destid = next_destid++;
+ if (next_destid == port->host_deviceid)
+ next_destid++;
+ } else
+ rdev->destid = rio_get_device_id(port, destid, hopcount);
+
+ /* If a PE has both switch and other functions, show it as a switch */
+ if (rio_is_switch(rdev)) {
+ rio_mport_read_config_32(port, destid, hopcount,
+ RIO_SWP_INFO_CAR, &rdev->swpinfo);
+ rswitch = kmalloc(sizeof(struct rio_switch), GFP_KERNEL);
+ if (!rswitch) {
+ kfree(rdev);
+ rdev = NULL;
+ goto out;
+ }
+ rswitch->switchid = next_switchid;
+ rswitch->hopcount = hopcount;
+ rswitch->destid = 0xffff;
+ /* Initialize switch route table */
+ for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++)
+ rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
+ rdev->rswitch = rswitch;
+ sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id,
+ rdev->rswitch->switchid);
+ rio_route_set_ops(rdev);
+
+ list_add_tail(&rswitch->node, &rio_switches);
+
+ } else
+ sprintf(rio_name(rdev), "%02x:e:%04x", rdev->net->id,
+ rdev->destid);
+
+ rdev->dev.bus = &rio_bus_type;
+
+ device_initialize(&rdev->dev);
+ rdev->dev.release = rio_release_dev;
+ rio_dev_get(rdev);
+
+ rdev->dma_mask = DMA_32BIT_MASK;
+ rdev->dev.dma_mask = &rdev->dma_mask;
+ rdev->dev.coherent_dma_mask = DMA_32BIT_MASK;
+
+ if ((rdev->pef & RIO_PEF_INB_DOORBELL) &&
+ (rdev->dst_ops & RIO_DST_OPS_DOORBELL))
+ rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE],
+ 0, 0xffff);
+
+ rio_add_device(rdev);
+
+ out:
+ return rdev;
+}
+
+/**
+ * rio_sport_is_active- Tests if a switch port has an active connection.
+ * @port: Master port to send transaction
+ * @destid: Associated destination ID for switch
+ * @hopcount: Hopcount to reach switch
+ * @sport: Switch port number
+ *
+ * Reads the port error status CSR for a particular switch port to
+ * determine if the port has an active link. Returns
+ * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is
+ * inactive.
+ */
+static int
+rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
+{
+ u32 result;
+ u32 ext_ftr_ptr;
+
+ int *entry = rio_sport_phys_table;
+
+ do {
+ if ((ext_ftr_ptr =
+ rio_mport_get_feature(port, 0, destid, hopcount, *entry)))
+
+ break;
+ } while (*++entry >= 0);
+
+ if (ext_ftr_ptr)
+ rio_mport_read_config_32(port, destid, hopcount,
+ ext_ftr_ptr +
+ RIO_PORT_N_ERR_STS_CSR(sport),
+ &result);
+
+ return (result & PORT_N_ERR_STS_PORT_OK);
+}
+
+/**
+ * rio_route_add_entry- Add a route entry to a switch routing table
+ * @mport: Master port to send transaction
+ * @rdev: Switch device
+ * @table: Routing table ID
+ * @route_destid: Destination ID to be routed
+ * @route_port: Port number to be routed
+ *
+ * Calls the switch specific add_entry() method to add a route entry
+ * on a switch. The route table can be specified using the @table
+ * argument if a switch has per port routing tables or the normal
+ * use is to specific all tables (or the global table) by passing
+ * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
+ * on failure.
+ */
+static int rio_route_add_entry(struct rio_mport *mport, struct rio_dev *rdev,
+ u16 table, u16 route_destid, u8 route_port)
+{
+ return rdev->rswitch->add_entry(mport, rdev->rswitch->destid,
+ rdev->rswitch->hopcount, table,
+ route_destid, route_port);
+}
+
+/**
+ * rio_route_get_entry- Read a route entry in a switch routing table
+ * @mport: Master port to send transaction
+ * @rdev: Switch device
+ * @table: Routing table ID
+ * @route_destid: Destination ID to be routed
+ * @route_port: Pointer to read port number into
+ *
+ * Calls the switch specific get_entry() method to read a route entry
+ * in a switch. The route table can be specified using the @table
+ * argument if a switch has per port routing tables or the normal
+ * use is to specific all tables (or the global table) by passing
+ * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
+ * on failure.
+ */
+static int
+rio_route_get_entry(struct rio_mport *mport, struct rio_dev *rdev, u16 table,
+ u16 route_destid, u8 * route_port)
+{
+ return rdev->rswitch->get_entry(mport, rdev->rswitch->destid,
+ rdev->rswitch->hopcount, table,
+ route_destid, route_port);
+}
+
+/**
+ * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a device
+ * @port: Master port to send transaction
+ * @hopcount: Number of hops to the device
+ *
+ * Used during enumeration to read the Host Device ID Lock CSR on a
+ * RIO device. Returns the value of the lock register.
+ */
+static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
+{
+ u32 result;
+
+ rio_mport_read_config_32(port, RIO_ANY_DESTID, hopcount,
+ RIO_HOST_DID_LOCK_CSR, &result);
+
+ return (u16) (result & 0xffff);
+}
+
+/**
+ * rio_get_swpinfo_inport- Gets the ingress port number
+ * @mport: Master port to send transaction
+ * @destid: Destination ID associated with the switch
+ * @hopcount: Number of hops to the device
+ *
+ * Returns port number being used to access the switch device.
+ */
+static u8
+rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount)
+{
+ u32 result;
+
+ rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR,
+ &result);
+
+ return (u8) (result & 0xff);
+}
+
+/**
+ * rio_get_swpinfo_tports- Gets total number of ports on the switch
+ * @mport: Master port to send transaction
+ * @destid: Destination ID associated with the switch
+ * @hopcount: Number of hops to the device
+ *
+ * Returns total numbers of ports implemented by the switch device.
+ */
+static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid,
+ u8 hopcount)
+{
+ u32 result;
+
+ rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR,
+ &result);
+
+ return RIO_GET_TOTAL_PORTS(result);
+}
+
+/**
+ * rio_net_add_mport- Add a master port to a RIO network
+ * @net: RIO network
+ * @port: Master port to add
+ *
+ * Adds a master port to the network list of associated master
+ * ports..
+ */
+static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port)
+{
+ spin_lock(&rio_global_list_lock);
+ list_add_tail(&port->nnode, &net->mports);
+ spin_unlock(&rio_global_list_lock);
+}
+
+/**
+ * rio_enum_peer- Recursively enumerate a RIO network through a master port
+ * @net: RIO network being enumerated
+ * @port: Master port to send transactions
+ * @hopcount: Number of hops into the network
+ *
+ * Recursively enumerates a RIO network. Transactions are sent via the
+ * master port passed in @port.
+ */
+static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+ u8 hopcount)
+{
+ int port_num;
+ int num_ports;
+ int cur_destid;
+ struct rio_dev *rdev;
+ u16 destid;
+ int tmp;
+
+ if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) {
+ pr_debug("RIO: PE already discovered by this host\n");
+ /*
+ * Already discovered by this host. Add it as another
+ * master port for the current network.
+ */
+ rio_net_add_mport(net, port);
+ return 0;
+ }
+
+ /* Attempt to acquire device lock */
+ rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
+ RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
+ while ((tmp = rio_get_host_deviceid_lock(port, hopcount))
+ < port->host_deviceid) {
+ /* Delay a bit */
+ mdelay(1);
+ /* Attempt to acquire device lock again */
+ rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
+ RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ }
+
+ if (rio_get_host_deviceid_lock(port, hopcount) > port->host_deviceid) {
+ pr_debug(
+ "RIO: PE locked by a higher priority host...retreating\n");
+ return -1;
+ }
+
+ /* Setup new RIO device */
+ if ((rdev = rio_setup_device(net, port, RIO_ANY_DESTID, hopcount, 1))) {
+ /* Add device to the global and bus/net specific list. */
+ list_add_tail(&rdev->net_list, &net->devices);
+ } else
+ return -1;
+
+ if (rio_is_switch(rdev)) {
+ next_switchid++;
+
+ for (destid = 0; destid < next_destid; destid++) {
+ rio_route_add_entry(port, rdev, RIO_GLOBAL_TABLE,
+ destid, rio_get_swpinfo_inport(port,
+ RIO_ANY_DESTID,
+ hopcount));
+ rdev->rswitch->route_table[destid] =
+ rio_get_swpinfo_inport(port, RIO_ANY_DESTID,
+ hopcount);
+ }
+
+ num_ports =
+ rio_get_swpinfo_tports(port, RIO_ANY_DESTID, hopcount);
+ pr_debug(
+ "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
+ rio_name(rdev), rdev->vid, rdev->did, num_ports);
+ for (port_num = 0; port_num < num_ports; port_num++) {
+ if (rio_get_swpinfo_inport
+ (port, RIO_ANY_DESTID, hopcount) == port_num)
+ continue;
+
+ cur_destid = next_destid;
+
+ if (rio_sport_is_active
+ (port, RIO_ANY_DESTID, hopcount, port_num)) {
+ pr_debug(
+ "RIO: scanning device on port %d\n",
+ port_num);
+ rio_route_add_entry(port, rdev,
+ RIO_GLOBAL_TABLE,
+ RIO_ANY_DESTID, port_num);
+
+ if (rio_enum_peer(net, port, hopcount + 1) < 0)
+ return -1;
+
+ /* Update routing tables */
+ if (next_destid > cur_destid) {
+ for (destid = cur_destid;
+ destid < next_destid; destid++) {
+ rio_route_add_entry(port, rdev,
+ RIO_GLOBAL_TABLE,
+ destid,
+ port_num);
+ rdev->rswitch->
+ route_table[destid] =
+ port_num;
+ }
+ rdev->rswitch->destid = cur_destid;
+ }
+ }
+ }
+ } else
+ pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n",
+ rio_name(rdev), rdev->vid, rdev->did);
+
+ return 0;
+}
+
+/**
+ * rio_enum_complete- Tests if enumeration of a network is complete
+ * @port: Master port to send transaction
+ *
+ * Tests the Component Tag CSR for presence of the magic enumeration
+ * complete flag. Return %1 if enumeration is complete or %0 if
+ * enumeration is incomplete.
+ */
+static int rio_enum_complete(struct rio_mport *port)
+{
+ u32 tag_csr;
+ int ret = 0;
+
+ rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
+
+ if (tag_csr == RIO_ENUM_CMPL_MAGIC)
+ ret = 1;
+
+ return ret;
+}
+
+/**
+ * rio_disc_peer- Recursively discovers a RIO network through a master port
+ * @net: RIO network being discovered
+ * @port: Master port to send transactions
+ * @destid: Current destination ID in network
+ * @hopcount: Number of hops into the network
+ *
+ * Recursively discovers a RIO network. Transactions are sent via the
+ * master port passed in @port.
+ */
+static int
+rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
+ u8 hopcount)
+{
+ u8 port_num, route_port;
+ int num_ports;
+ struct rio_dev *rdev;
+ u16 ndestid;
+
+ /* Setup new RIO device */
+ if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) {
+ /* Add device to the global and bus/net specific list. */
+ list_add_tail(&rdev->net_list, &net->devices);
+ } else
+ return -1;
+
+ if (rio_is_switch(rdev)) {
+ next_switchid++;
+
+ /* Associated destid is how we accessed this switch */
+ rdev->rswitch->destid = destid;
+
+ num_ports = rio_get_swpinfo_tports(port, destid, hopcount);
+ pr_debug(
+ "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
+ rio_name(rdev), rdev->vid, rdev->did, num_ports);
+ for (port_num = 0; port_num < num_ports; port_num++) {
+ if (rio_get_swpinfo_inport(port, destid, hopcount) ==
+ port_num)
+ continue;
+
+ if (rio_sport_is_active
+ (port, destid, hopcount, port_num)) {
+ pr_debug(
+ "RIO: scanning device on port %d\n",
+ port_num);
+ for (ndestid = 0; ndestid < RIO_ANY_DESTID;
+ ndestid++) {
+ rio_route_get_entry(port, rdev,
+ RIO_GLOBAL_TABLE,
+ ndestid,
+ &route_port);
+ if (route_port == port_num)
+ break;
+ }
+
+ if (rio_disc_peer
+ (net, port, ndestid, hopcount + 1) < 0)
+ return -1;
+ }
+ }
+ } else
+ pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n",
+ rio_name(rdev), rdev->vid, rdev->did);
+
+ return 0;
+}
+
+/**
+ * rio_mport_is_active- Tests if master port link is active
+ * @port: Master port to test
+ *
+ * Reads the port error status CSR for the master port to
+ * determine if the port has an active link. Returns
+ * %PORT_N_ERR_STS_PORT_OK if the master port is active
+ * or %0 if it is inactive.
+ */
+static int rio_mport_is_active(struct rio_mport *port)
+{
+ u32 result = 0;
+ u32 ext_ftr_ptr;
+ int *entry = rio_mport_phys_table;
+
+ do {
+ if ((ext_ftr_ptr =
+ rio_mport_get_feature(port, 1, 0, 0, *entry)))
+ break;
+ } while (*++entry >= 0);
+
+ if (ext_ftr_ptr)
+ rio_local_read_config_32(port,
+ ext_ftr_ptr +
+ RIO_PORT_N_ERR_STS_CSR(port->index),
+ &result);
+
+ return (result & PORT_N_ERR_STS_PORT_OK);
+}
+
+/**
+ * rio_alloc_net- Allocate and configure a new RIO network
+ * @port: Master port associated with the RIO network
+ *
+ * Allocates a RIO network structure, initializes per-network
+ * list heads, and adds the associated master port to the
+ * network list of associated master ports. Returns a
+ * RIO network pointer on success or %NULL on failure.
+ */
+static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
+{
+ struct rio_net *net;
+
+ net = kmalloc(sizeof(struct rio_net), GFP_KERNEL);
+ if (net) {
+ memset(net, 0, sizeof(struct rio_net));
+ INIT_LIST_HEAD(&net->node);
+ INIT_LIST_HEAD(&net->devices);
+ INIT_LIST_HEAD(&net->mports);
+ list_add_tail(&port->nnode, &net->mports);
+ net->hport = port;
+ net->id = next_net++;
+ }
+ return net;
+}
+
+/**
+ * rio_enum_mport- Start enumeration through a master port
+ * @mport: Master port to send transactions
+ *
+ * Starts the enumeration process. If somebody has enumerated our
+ * master port device, then give up. If not and we have an active
+ * link, then start recursive peer enumeration. Returns %0 if
+ * enumeration succeeds or %-EBUSY if enumeration fails.
+ */
+int rio_enum_mport(struct rio_mport *mport)
+{
+ struct rio_net *net = NULL;
+ int rc = 0;
+
+ printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id,
+ mport->name);
+ /* If somebody else enumerated our master port device, bail. */
+ if (rio_enum_host(mport) < 0) {
+ printk(KERN_INFO
+ "RIO: master port %d device has been enumerated by a remote host\n",
+ mport->id);
+ rc = -EBUSY;
+ goto out;
+ }
+
+ /* If master port has an active link, allocate net and enum peers */
+ if (rio_mport_is_active(mport)) {
+ if (!(net = rio_alloc_net(mport))) {
+ printk(KERN_ERR "RIO: failed to allocate new net\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+ if (rio_enum_peer(net, mport, 0) < 0) {
+ /* A higher priority host won enumeration, bail. */
+ printk(KERN_INFO
+ "RIO: master port %d device has lost enumeration to a remote host\n",
+ mport->id);
+ rio_clear_locks(mport);
+ rc = -EBUSY;
+ goto out;
+ }
+ rio_clear_locks(mport);
+ } else {
+ printk(KERN_INFO "RIO: master port %d link inactive\n",
+ mport->id);
+ rc = -EINVAL;
+ }
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_build_route_tables- Generate route tables from switch route entries
+ *
+ * For each switch device, generate a route table by copying existing
+ * route entries from the switch.
+ */
+static void rio_build_route_tables(void)
+{
+ struct rio_dev *rdev;
+ int i;
+ u8 sport;
+
+ list_for_each_entry(rdev, &rio_devices, global_list)
+ if (rio_is_switch(rdev))
+ for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
+ if (rio_route_get_entry
+ (rdev->net->hport, rdev, RIO_GLOBAL_TABLE, i,
+ &sport) < 0)
+ continue;
+ rdev->rswitch->route_table[i] = sport;
+ }
+}
+
+/**
+ * rio_enum_timeout- Signal that enumeration timed out
+ * @data: Address of timeout flag.
+ *
+ * When the enumeration complete timer expires, set a flag that
+ * signals to the discovery process that enumeration did not
+ * complete in a sane amount of time.
+ */
+static void rio_enum_timeout(unsigned long data)
+{
+ /* Enumeration timed out, set flag */
+ *(int *)data = 1;
+}
+
+/**
+ * rio_disc_mport- Start discovery through a master port
+ * @mport: Master port to send transactions
+ *
+ * Starts the discovery process. If we have an active link,
+ * then wait for the signal that enumeration is complete.
+ * When enumeration completion is signaled, start recursive
+ * peer discovery. Returns %0 if discovery succeeds or %-EBUSY
+ * on failure.
+ */
+int rio_disc_mport(struct rio_mport *mport)
+{
+ struct rio_net *net = NULL;
+ int enum_timeout_flag = 0;
+
+ printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id,
+ mport->name);
+
+ /* If master port has an active link, allocate net and discover peers */
+ if (rio_mport_is_active(mport)) {
+ if (!(net = rio_alloc_net(mport))) {
+ printk(KERN_ERR "RIO: Failed to allocate new net\n");
+ goto bail;
+ }
+
+ pr_debug("RIO: wait for enumeration complete...");
+
+ rio_enum_timer.expires =
+ jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
+ rio_enum_timer.data = (unsigned long)&enum_timeout_flag;
+ add_timer(&rio_enum_timer);
+ while (!rio_enum_complete(mport)) {
+ mdelay(1);
+ if (enum_timeout_flag) {
+ del_timer_sync(&rio_enum_timer);
+ goto timeout;
+ }
+ }
+ del_timer_sync(&rio_enum_timer);
+
+ pr_debug("done\n");
+ if (rio_disc_peer(net, mport, RIO_ANY_DESTID, 0) < 0) {
+ printk(KERN_INFO
+ "RIO: master port %d device has failed discovery\n",
+ mport->id);
+ goto bail;
+ }
+
+ rio_build_route_tables();
+ }
+
+ return 0;
+
+ timeout:
+ pr_debug("timeout\n");
+ bail:
+ return -EBUSY;
+}
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
new file mode 100644
index 000000000000..30a11436e241
--- /dev/null
+++ b/drivers/rapidio/rio-sysfs.c
@@ -0,0 +1,230 @@
+/*
+ * RapidIO sysfs attributes and support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/stat.h>
+
+#include "rio.h"
+
+/* Sysfs support */
+#define rio_config_attr(field, format_string) \
+static ssize_t \
+field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct rio_dev *rdev = to_rio_dev(dev); \
+ \
+ return sprintf(buf, format_string, rdev->field); \
+} \
+
+rio_config_attr(did, "0x%04x\n");
+rio_config_attr(vid, "0x%04x\n");
+rio_config_attr(device_rev, "0x%08x\n");
+rio_config_attr(asm_did, "0x%04x\n");
+rio_config_attr(asm_vid, "0x%04x\n");
+rio_config_attr(asm_rev, "0x%04x\n");
+
+static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct rio_dev *rdev = to_rio_dev(dev);
+ char *str = buf;
+ int i;
+
+ if (!rdev->rswitch)
+ goto out;
+
+ for (i = 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
+ if (rdev->rswitch->route_table[i] == RIO_INVALID_ROUTE)
+ continue;
+ str +=
+ sprintf(str, "%04x %02x\n", i,
+ rdev->rswitch->route_table[i]);
+ }
+
+ out:
+ return (str - buf);
+}
+
+struct device_attribute rio_dev_attrs[] = {
+ __ATTR_RO(did),
+ __ATTR_RO(vid),
+ __ATTR_RO(device_rev),
+ __ATTR_RO(asm_did),
+ __ATTR_RO(asm_vid),
+ __ATTR_RO(asm_rev),
+ __ATTR_RO(routes),
+ __ATTR_NULL,
+};
+
+static ssize_t
+rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct rio_dev *dev =
+ to_rio_dev(container_of(kobj, struct device, kobj));
+ unsigned int size = 0x100;
+ loff_t init_off = off;
+ u8 *data = (u8 *) buf;
+
+ /* Several chips lock up trying to read undefined config space */
+ if (capable(CAP_SYS_ADMIN))
+ size = 0x200000;
+
+ if (off > size)
+ return 0;
+ if (off + count > size) {
+ size -= off;
+ count = size;
+ } else {
+ size = count;
+ }
+
+ if ((off & 1) && size) {
+ u8 val;
+ rio_read_config_8(dev, off, &val);
+ data[off - init_off] = val;
+ off++;
+ size--;
+ }
+
+ if ((off & 3) && size > 2) {
+ u16 val;
+ rio_read_config_16(dev, off, &val);
+ data[off - init_off] = (val >> 8) & 0xff;
+ data[off - init_off + 1] = val & 0xff;
+ off += 2;
+ size -= 2;
+ }
+
+ while (size > 3) {
+ u32 val;
+ rio_read_config_32(dev, off, &val);
+ data[off - init_off] = (val >> 24) & 0xff;
+ data[off - init_off + 1] = (val >> 16) & 0xff;
+ data[off - init_off + 2] = (val >> 8) & 0xff;
+ data[off - init_off + 3] = val & 0xff;
+ off += 4;
+ size -= 4;
+ }
+
+ if (size >= 2) {
+ u16 val;
+ rio_read_config_16(dev, off, &val);
+ data[off - init_off] = (val >> 8) & 0xff;
+ data[off - init_off + 1] = val & 0xff;
+ off += 2;
+ size -= 2;
+ }
+
+ if (size > 0) {
+ u8 val;
+ rio_read_config_8(dev, off, &val);
+ data[off - init_off] = val;
+ off++;
+ --size;
+ }
+
+ return count;
+}
+
+static ssize_t
+rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct rio_dev *dev =
+ to_rio_dev(container_of(kobj, struct device, kobj));
+ unsigned int size = count;
+ loff_t init_off = off;
+ u8 *data = (u8 *) buf;
+
+ if (off > 0x200000)
+ return 0;
+ if (off + count > 0x200000) {
+ size = 0x200000 - off;
+ count = size;
+ }
+
+ if ((off & 1) && size) {
+ rio_write_config_8(dev, off, data[off - init_off]);
+ off++;
+ size--;
+ }
+
+ if ((off & 3) && (size > 2)) {
+ u16 val = data[off - init_off + 1];
+ val |= (u16) data[off - init_off] << 8;
+ rio_write_config_16(dev, off, val);
+ off += 2;
+ size -= 2;
+ }
+
+ while (size > 3) {
+ u32 val = data[off - init_off + 3];
+ val |= (u32) data[off - init_off + 2] << 8;
+ val |= (u32) data[off - init_off + 1] << 16;
+ val |= (u32) data[off - init_off] << 24;
+ rio_write_config_32(dev, off, val);
+ off += 4;
+ size -= 4;
+ }
+
+ if (size >= 2) {
+ u16 val = data[off - init_off + 1];
+ val |= (u16) data[off - init_off] << 8;
+ rio_write_config_16(dev, off, val);
+ off += 2;
+ size -= 2;
+ }
+
+ if (size) {
+ rio_write_config_8(dev, off, data[off - init_off]);
+ off++;
+ --size;
+ }
+
+ return count;
+}
+
+static struct bin_attribute rio_config_attr = {
+ .attr = {
+ .name = "config",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = 0x200000,
+ .read = rio_read_config,
+ .write = rio_write_config,
+};
+
+/**
+ * rio_create_sysfs_dev_files - create RIO specific sysfs files
+ * @rdev: device whose entries should be created
+ *
+ * Create files when @rdev is added to sysfs.
+ */
+int rio_create_sysfs_dev_files(struct rio_dev *rdev)
+{
+ sysfs_create_bin_file(&rdev->dev.kobj, &rio_config_attr);
+
+ return 0;
+}
+
+/**
+ * rio_remove_sysfs_dev_files - cleanup RIO specific sysfs files
+ * @rdev: device whose entries we should free
+ *
+ * Cleanup when @rdev is removed from sysfs.
+ */
+void rio_remove_sysfs_dev_files(struct rio_dev *rdev)
+{
+ sysfs_remove_bin_file(&rdev->dev.kobj, &rio_config_attr);
+}
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
new file mode 100644
index 000000000000..3ca1011ceaac
--- /dev/null
+++ b/drivers/rapidio/rio.c
@@ -0,0 +1,510 @@
+/*
+ * RapidIO interconnect services
+ * (RapidIO Interconnect Specification, http://www.rapidio.org)
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+#include <linux/rio_regs.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#include "rio.h"
+
+static LIST_HEAD(rio_mports);
+
+/**
+ * rio_local_get_device_id - Get the base/extended device id for a port
+ * @port: RIO master port from which to get the deviceid
+ *
+ * Reads the base/extended device id from the local device
+ * implementing the master port. Returns the 8/16-bit device
+ * id.
+ */
+u16 rio_local_get_device_id(struct rio_mport *port)
+{
+ u32 result;
+
+ rio_local_read_config_32(port, RIO_DID_CSR, &result);
+
+ return (RIO_GET_DID(result));
+}
+
+/**
+ * rio_request_inb_mbox - request inbound mailbox service
+ * @mport: RIO master port from which to allocate the mailbox resource
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox number to claim
+ * @entries: Number of entries in inbound mailbox queue
+ * @minb: Callback to execute when inbound message is received
+ *
+ * Requests ownership of an inbound mailbox resource and binds
+ * a callback function to the resource. Returns %0 on success.
+ */
+int rio_request_inb_mbox(struct rio_mport *mport,
+ void *dev_id,
+ int mbox,
+ int entries,
+ void (*minb) (struct rio_mport * mport, void *dev_id, int mbox,
+ int slot))
+{
+ int rc = 0;
+
+ struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+
+ if (res) {
+ rio_init_mbox_res(res, mbox, mbox);
+
+ /* Make sure this mailbox isn't in use */
+ if ((rc =
+ request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE],
+ res)) < 0) {
+ kfree(res);
+ goto out;
+ }
+
+ mport->inb_msg[mbox].res = res;
+
+ /* Hook the inbound message callback */
+ mport->inb_msg[mbox].mcback = minb;
+
+ rc = rio_open_inb_mbox(mport, dev_id, mbox, entries);
+ } else
+ rc = -ENOMEM;
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_release_inb_mbox - release inbound mailbox message service
+ * @mport: RIO master port from which to release the mailbox resource
+ * @mbox: Mailbox number to release
+ *
+ * Releases ownership of an inbound mailbox resource. Returns 0
+ * if the request has been satisfied.
+ */
+int rio_release_inb_mbox(struct rio_mport *mport, int mbox)
+{
+ rio_close_inb_mbox(mport, mbox);
+
+ /* Release the mailbox resource */
+ return release_resource(mport->inb_msg[mbox].res);
+}
+
+/**
+ * rio_request_outb_mbox - request outbound mailbox service
+ * @mport: RIO master port from which to allocate the mailbox resource
+ * @dev_id: Device specific pointer to pass on event
+ * @mbox: Mailbox number to claim
+ * @entries: Number of entries in outbound mailbox queue
+ * @moutb: Callback to execute when outbound message is sent
+ *
+ * Requests ownership of an outbound mailbox resource and binds
+ * a callback function to the resource. Returns 0 on success.
+ */
+int rio_request_outb_mbox(struct rio_mport *mport,
+ void *dev_id,
+ int mbox,
+ int entries,
+ void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot))
+{
+ int rc = 0;
+
+ struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+
+ if (res) {
+ rio_init_mbox_res(res, mbox, mbox);
+
+ /* Make sure this outbound mailbox isn't in use */
+ if ((rc =
+ request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE],
+ res)) < 0) {
+ kfree(res);
+ goto out;
+ }
+
+ mport->outb_msg[mbox].res = res;
+
+ /* Hook the inbound message callback */
+ mport->outb_msg[mbox].mcback = moutb;
+
+ rc = rio_open_outb_mbox(mport, dev_id, mbox, entries);
+ } else
+ rc = -ENOMEM;
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_release_outb_mbox - release outbound mailbox message service
+ * @mport: RIO master port from which to release the mailbox resource
+ * @mbox: Mailbox number to release
+ *
+ * Releases ownership of an inbound mailbox resource. Returns 0
+ * if the request has been satisfied.
+ */
+int rio_release_outb_mbox(struct rio_mport *mport, int mbox)
+{
+ rio_close_outb_mbox(mport, mbox);
+
+ /* Release the mailbox resource */
+ return release_resource(mport->outb_msg[mbox].res);
+}
+
+/**
+ * rio_setup_inb_dbell - bind inbound doorbell callback
+ * @mport: RIO master port to bind the doorbell callback
+ * @dev_id: Device specific pointer to pass on event
+ * @res: Doorbell message resource
+ * @dinb: Callback to execute when doorbell is received
+ *
+ * Adds a doorbell resource/callback pair into a port's
+ * doorbell event list. Returns 0 if the request has been
+ * satisfied.
+ */
+static int
+rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res,
+ void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst,
+ u16 info))
+{
+ int rc = 0;
+ struct rio_dbell *dbell;
+
+ if (!(dbell = kmalloc(sizeof(struct rio_dbell), GFP_KERNEL))) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ dbell->res = res;
+ dbell->dinb = dinb;
+ dbell->dev_id = dev_id;
+
+ list_add_tail(&dbell->node, &mport->dbells);
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_request_inb_dbell - request inbound doorbell message service
+ * @mport: RIO master port from which to allocate the doorbell resource
+ * @dev_id: Device specific pointer to pass on event
+ * @start: Doorbell info range start
+ * @end: Doorbell info range end
+ * @dinb: Callback to execute when doorbell is received
+ *
+ * Requests ownership of an inbound doorbell resource and binds
+ * a callback function to the resource. Returns 0 if the request
+ * has been satisfied.
+ */
+int rio_request_inb_dbell(struct rio_mport *mport,
+ void *dev_id,
+ u16 start,
+ u16 end,
+ void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src,
+ u16 dst, u16 info))
+{
+ int rc = 0;
+
+ struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+
+ if (res) {
+ rio_init_dbell_res(res, start, end);
+
+ /* Make sure these doorbells aren't in use */
+ if ((rc =
+ request_resource(&mport->riores[RIO_DOORBELL_RESOURCE],
+ res)) < 0) {
+ kfree(res);
+ goto out;
+ }
+
+ /* Hook the doorbell callback */
+ rc = rio_setup_inb_dbell(mport, dev_id, res, dinb);
+ } else
+ rc = -ENOMEM;
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_release_inb_dbell - release inbound doorbell message service
+ * @mport: RIO master port from which to release the doorbell resource
+ * @start: Doorbell info range start
+ * @end: Doorbell info range end
+ *
+ * Releases ownership of an inbound doorbell resource and removes
+ * callback from the doorbell event list. Returns 0 if the request
+ * has been satisfied.
+ */
+int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end)
+{
+ int rc = 0, found = 0;
+ struct rio_dbell *dbell;
+
+ list_for_each_entry(dbell, &mport->dbells, node) {
+ if ((dbell->res->start == start) && (dbell->res->end == end)) {
+ found = 1;
+ break;
+ }
+ }
+
+ /* If we can't find an exact match, fail */
+ if (!found) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Delete from list */
+ list_del(&dbell->node);
+
+ /* Release the doorbell resource */
+ rc = release_resource(dbell->res);
+
+ /* Free the doorbell event */
+ kfree(dbell);
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_request_outb_dbell - request outbound doorbell message range
+ * @rdev: RIO device from which to allocate the doorbell resource
+ * @start: Doorbell message range start
+ * @end: Doorbell message range end
+ *
+ * Requests ownership of a doorbell message range. Returns a resource
+ * if the request has been satisfied or %NULL on failure.
+ */
+struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start,
+ u16 end)
+{
+ struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+
+ if (res) {
+ rio_init_dbell_res(res, start, end);
+
+ /* Make sure these doorbells aren't in use */
+ if (request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE], res)
+ < 0) {
+ kfree(res);
+ res = NULL;
+ }
+ }
+
+ return res;
+}
+
+/**
+ * rio_release_outb_dbell - release outbound doorbell message range
+ * @rdev: RIO device from which to release the doorbell resource
+ * @res: Doorbell resource to be freed
+ *
+ * Releases ownership of a doorbell message range. Returns 0 if the
+ * request has been satisfied.
+ */
+int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res)
+{
+ int rc = release_resource(res);
+
+ kfree(res);
+
+ return rc;
+}
+
+/**
+ * rio_mport_get_feature - query for devices' extended features
+ * @port: Master port to issue transaction
+ * @local: Indicate a local master port or remote device access
+ * @destid: Destination ID of the device
+ * @hopcount: Number of switch hops to the device
+ * @ftr: Extended feature code
+ *
+ * Tell if a device supports a given RapidIO capability.
+ * Returns the offset of the requested extended feature
+ * block within the device's RIO configuration space or
+ * 0 in case the device does not support it. Possible
+ * values for @ftr:
+ *
+ * %RIO_EFB_PAR_EP_ID LP/LVDS EP Devices
+ *
+ * %RIO_EFB_PAR_EP_REC_ID LP/LVDS EP Recovery Devices
+ *
+ * %RIO_EFB_PAR_EP_FREE_ID LP/LVDS EP Free Devices
+ *
+ * %RIO_EFB_SER_EP_ID LP/Serial EP Devices
+ *
+ * %RIO_EFB_SER_EP_REC_ID LP/Serial EP Recovery Devices
+ *
+ * %RIO_EFB_SER_EP_FREE_ID LP/Serial EP Free Devices
+ */
+u32
+rio_mport_get_feature(struct rio_mport * port, int local, u16 destid,
+ u8 hopcount, int ftr)
+{
+ u32 asm_info, ext_ftr_ptr, ftr_header;
+
+ if (local)
+ rio_local_read_config_32(port, RIO_ASM_INFO_CAR, &asm_info);
+ else
+ rio_mport_read_config_32(port, destid, hopcount,
+ RIO_ASM_INFO_CAR, &asm_info);
+
+ ext_ftr_ptr = asm_info & RIO_EXT_FTR_PTR_MASK;
+
+ while (ext_ftr_ptr) {
+ if (local)
+ rio_local_read_config_32(port, ext_ftr_ptr,
+ &ftr_header);
+ else
+ rio_mport_read_config_32(port, destid, hopcount,
+ ext_ftr_ptr, &ftr_header);
+ if (RIO_GET_BLOCK_ID(ftr_header) == ftr)
+ return ext_ftr_ptr;
+ if (!(ext_ftr_ptr = RIO_GET_BLOCK_PTR(ftr_header)))
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did
+ * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
+ * @did: RIO did to match or %RIO_ANY_ID to match all dids
+ * @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids
+ * @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids
+ * @from: Previous RIO device found in search, or %NULL for new search
+ *
+ * Iterates through the list of known RIO devices. If a RIO device is
+ * found with a matching @vid, @did, @asm_vid, @asm_did, the reference
+ * count to the device is incrememted and a pointer to its device
+ * structure is returned. Otherwise, %NULL is returned. A new search
+ * is initiated by passing %NULL to the @from argument. Otherwise, if
+ * @from is not %NULL, searches continue from next device on the global
+ * list. The reference count for @from is always decremented if it is
+ * not %NULL.
+ */
+struct rio_dev *rio_get_asm(u16 vid, u16 did,
+ u16 asm_vid, u16 asm_did, struct rio_dev *from)
+{
+ struct list_head *n;
+ struct rio_dev *rdev;
+
+ WARN_ON(in_interrupt());
+ spin_lock(&rio_global_list_lock);
+ n = from ? from->global_list.next : rio_devices.next;
+
+ while (n && (n != &rio_devices)) {
+ rdev = rio_dev_g(n);
+ if ((vid == RIO_ANY_ID || rdev->vid == vid) &&
+ (did == RIO_ANY_ID || rdev->did == did) &&
+ (asm_vid == RIO_ANY_ID || rdev->asm_vid == asm_vid) &&
+ (asm_did == RIO_ANY_ID || rdev->asm_did == asm_did))
+ goto exit;
+ n = n->next;
+ }
+ rdev = NULL;
+ exit:
+ rio_dev_put(from);
+ rdev = rio_dev_get(rdev);
+ spin_unlock(&rio_global_list_lock);
+ return rdev;
+}
+
+/**
+ * rio_get_device - Begin or continue searching for a RIO device by vid/did
+ * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
+ * @did: RIO did to match or %RIO_ANY_ID to match all dids
+ * @from: Previous RIO device found in search, or %NULL for new search
+ *
+ * Iterates through the list of known RIO devices. If a RIO device is
+ * found with a matching @vid and @did, the reference count to the
+ * device is incrememted and a pointer to its device structure is returned.
+ * Otherwise, %NULL is returned. A new search is initiated by passing %NULL
+ * to the @from argument. Otherwise, if @from is not %NULL, searches
+ * continue from next device on the global list. The reference count for
+ * @from is always decremented if it is not %NULL.
+ */
+struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
+{
+ return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
+}
+
+static void rio_fixup_device(struct rio_dev *dev)
+{
+}
+
+static int __devinit rio_init(void)
+{
+ struct rio_dev *dev = NULL;
+
+ while ((dev = rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) != NULL) {
+ rio_fixup_device(dev);
+ }
+ return 0;
+}
+
+device_initcall(rio_init);
+
+int rio_init_mports(void)
+{
+ int rc = 0;
+ struct rio_mport *port;
+
+ list_for_each_entry(port, &rio_mports, node) {
+ if (!request_mem_region(port->iores.start,
+ port->iores.end - port->iores.start,
+ port->name)) {
+ printk(KERN_ERR
+ "RIO: Error requesting master port region %8.8lx-%8.8lx\n",
+ port->iores.start, port->iores.end - 1);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ if (port->host_deviceid >= 0)
+ rio_enum_mport(port);
+ else
+ rio_disc_mport(port);
+ }
+
+ out:
+ return rc;
+}
+
+void rio_register_mport(struct rio_mport *port)
+{
+ list_add_tail(&port->node, &rio_mports);
+}
+
+EXPORT_SYMBOL_GPL(rio_local_get_device_id);
+EXPORT_SYMBOL_GPL(rio_get_device);
+EXPORT_SYMBOL_GPL(rio_get_asm);
+EXPORT_SYMBOL_GPL(rio_request_inb_dbell);
+EXPORT_SYMBOL_GPL(rio_release_inb_dbell);
+EXPORT_SYMBOL_GPL(rio_request_outb_dbell);
+EXPORT_SYMBOL_GPL(rio_release_outb_dbell);
+EXPORT_SYMBOL_GPL(rio_request_inb_mbox);
+EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
+EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
+EXPORT_SYMBOL_GPL(rio_release_outb_mbox);
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
new file mode 100644
index 000000000000..b242cee656e7
--- /dev/null
+++ b/drivers/rapidio/rio.h
@@ -0,0 +1,60 @@
+/*
+ * RapidIO interconnect services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/rio.h>
+
+/* Functions internal to the RIO core code */
+
+extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid,
+ u8 hopcount, int ftr);
+extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
+extern int rio_enum_mport(struct rio_mport *mport);
+extern int rio_disc_mport(struct rio_mport *mport);
+
+/* Structures internal to the RIO core code */
+extern struct device_attribute rio_dev_attrs[];
+extern spinlock_t rio_global_list_lock;
+
+extern struct rio_route_ops __start_rio_route_ops[];
+extern struct rio_route_ops __end_rio_route_ops[];
+
+/* Helpers internal to the RIO core code */
+#define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \
+ static struct rio_route_ops __rio_route_ops __attribute_used__ \
+ __attribute__((__section__(#section))) = { vid, did, add_hook, get_hook };
+
+/**
+ * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations
+ * @vid: RIO vendor ID
+ * @did: RIO device ID
+ * @add_hook: Callback that adds a route entry
+ * @get_hook: Callback that gets a route entry
+ *
+ * Manipulating switch route tables in RIO is switch specific. This
+ * registers a switch by vendor and device ID with two callbacks for
+ * modifying and retrieving route entries in a switch. A &struct
+ * rio_route_ops is initialized with the ops and placed into a
+ * RIO-specific kernel section.
+ */
+#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \
+ DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
+ vid, did, add_hook, get_hook)
+
+#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
+#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16)
+#define RIO_SET_DID(x) ((x & 0x000000ff) << 16)
+#else
+#define RIO_GET_DID(x) (x & 0xffff)
+#define RIO_SET_DID(x) (x & 0xffff)
+#endif
diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile
new file mode 100644
index 000000000000..b924f8301761
--- /dev/null
+++ b/drivers/rapidio/switches/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for RIO switches
+#
+
+obj-$(CONFIG_RAPIDIO) += tsi500.o
diff --git a/drivers/rapidio/switches/tsi500.c b/drivers/rapidio/switches/tsi500.c
new file mode 100644
index 000000000000..c77c23bd9840
--- /dev/null
+++ b/drivers/rapidio/switches/tsi500.c
@@ -0,0 +1,60 @@
+/*
+ * RapidIO Tsi500 switch support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/rio.h>
+#include <linux/rio_drv.h>
+#include <linux/rio_ids.h>
+#include "../rio.h"
+
+static int
+tsi500_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 route_port)
+{
+ int i;
+ u32 offset = 0x10000 + 0xa00 + ((route_destid / 2)&~0x3);
+ u32 result;
+
+ if (table == 0xff) {
+ rio_mport_read_config_32(mport, destid, hopcount, offset, &result);
+ result &= ~(0xf << (4*(route_destid & 0x7)));
+ for (i=0;i<4;i++)
+ rio_mport_write_config_32(mport, destid, hopcount, offset + (0x20000*i), result | (route_port << (4*(route_destid & 0x7))));
+ }
+ else {
+ rio_mport_read_config_32(mport, destid, hopcount, offset + (0x20000*table), &result);
+ result &= ~(0xf << (4*(route_destid & 0x7)));
+ rio_mport_write_config_32(mport, destid, hopcount, offset + (0x20000*table), result | (route_port << (4*(route_destid & 0x7))));
+ }
+
+ return 0;
+}
+
+static int
+tsi500_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 table, u16 route_destid, u8 *route_port)
+{
+ int ret = 0;
+ u32 offset = 0x10000 + 0xa00 + ((route_destid / 2)&~0x3);
+ u32 result;
+
+ if (table == 0xff)
+ rio_mport_read_config_32(mport, destid, hopcount, offset, &result);
+ else
+ rio_mport_read_config_32(mport, destid, hopcount, offset + (0x20000*table), &result);
+
+ result &= 0xf << (4*(route_destid & 0x7));
+ *route_port = result >> (4*(route_destid & 0x7));
+ if (*route_port > 3)
+ ret = -1;
+
+ return ret;
+}
+
+DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8fc891a9d47f..7008d32433bf 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -115,8 +115,7 @@ dasd_alloc_device(void)
void
dasd_free_device(struct dasd_device *device)
{
- if (device->private)
- kfree(device->private);
+ kfree(device->private);
free_page((unsigned long) device->erp_mem);
free_pages((unsigned long) device->ccw_mem, 1);
kfree(device);
@@ -539,8 +538,7 @@ dasd_kmalloc_request(char *magic, int cplength, int datasize,
if (datasize > 0) {
cqr->data = kmalloc(datasize, GFP_ATOMIC | GFP_DMA);
if (cqr->data == NULL) {
- if (cqr->cpaddr != NULL)
- kfree(cqr->cpaddr);
+ kfree(cqr->cpaddr);
kfree(cqr);
return ERR_PTR(-ENOMEM);
}
@@ -615,10 +613,8 @@ dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device)
clear_normalized_cda(ccw);
} while (ccw++->flags & (CCW_FLAG_CC | CCW_FLAG_DC));
#endif
- if (cqr->cpaddr != NULL)
- kfree(cqr->cpaddr);
- if (cqr->data != NULL)
- kfree(cqr->data);
+ kfree(cqr->cpaddr);
+ kfree(cqr->data);
kfree(cqr);
dasd_put_device(device);
}
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index bda896d9d788..caee16a3dc62 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -387,8 +387,7 @@ dasd_add_busid(char *bus_id, int features)
new = 0;
}
spin_unlock(&dasd_devmap_lock);
- if (new)
- kfree(new);
+ kfree(new);
return devmap;
}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 7478423b53bb..ab8754e566bc 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.49 $
+ * $Revision: 1.51 $
*/
#include <linux/config.h>
@@ -67,9 +67,9 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
static __inline__ int
dia250(void *iob, int cmd)
{
- typedef struct {
- char _[max(sizeof (struct dasd_diag_init_io),
- sizeof (struct dasd_diag_rw_io))];
+ typedef union {
+ struct dasd_diag_init_io init_io;
+ struct dasd_diag_rw_io rw_io;
} addr_type;
int rc;
@@ -190,7 +190,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;
private->iob.block_count = dreq->block_count;
private->iob.interrupt_params = (addr_t) cqr;
- private->iob.bio_list = __pa(dreq->bio);
+ private->iob.bio_list = dreq->bio;
private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
cqr->startclk = get_clock();
@@ -394,47 +394,57 @@ dasd_diag_check_device(struct dasd_device *device)
memset(&bio, 0, sizeof (struct dasd_diag_bio));
bio.type = MDSK_READ_REQ;
bio.block_number = private->pt_block + 1;
- bio.buffer = __pa(label);
+ bio.buffer = label;
memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));
private->iob.dev_nr = rdc_data->dev_nr;
private->iob.key = 0;
private->iob.flags = 0; /* do synchronous io */
private->iob.block_count = 1;
private->iob.interrupt_params = 0;
- private->iob.bio_list = __pa(&bio);
+ private->iob.bio_list = &bio;
private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
rc = dia250(&private->iob, RW_BIO);
- if (rc == 0 || rc == 3)
- break;
+ if (rc == 3) {
+ DEV_MESSAGE(KERN_WARNING, device, "%s",
+ "DIAG call failed");
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
mdsk_term_io(device);
+ if (rc == 0)
+ break;
}
- if (rc == 3) {
- DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed");
- rc = -EOPNOTSUPP;
- } else if (rc != 0) {
+ if (bsize > PAGE_SIZE) {
DEV_MESSAGE(KERN_WARNING, device, "device access failed "
"(rc=%d)", rc);
rc = -EIO;
+ goto out;
+ }
+ /* check for label block */
+ if (memcmp(label->label_id, DASD_DIAG_CMS1,
+ sizeof(DASD_DIAG_CMS1)) == 0) {
+ /* get formatted blocksize from label block */
+ bsize = (unsigned int) label->block_size;
+ device->blocks = (unsigned long) label->block_count;
+ } else
+ device->blocks = end_block;
+ device->bp_block = bsize;
+ device->s2b_shift = 0; /* bits to shift 512 to get a block */
+ for (sb = 512; sb < bsize; sb = sb << 1)
+ device->s2b_shift++;
+ rc = mdsk_init_io(device, device->bp_block, 0, NULL);
+ if (rc) {
+ DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization "
+ "failed (rc=%d)", rc);
+ rc = -EIO;
} else {
- if (memcmp(label->label_id, DASD_DIAG_CMS1,
- sizeof(DASD_DIAG_CMS1)) == 0) {
- /* get formatted blocksize from label block */
- bsize = (unsigned int) label->block_size;
- device->blocks = (unsigned long) label->block_count;
- } else
- device->blocks = end_block;
- device->bp_block = bsize;
- device->s2b_shift = 0; /* bits to shift 512 to get a block */
- for (sb = 512; sb < bsize; sb = sb << 1)
- device->s2b_shift++;
-
DEV_MESSAGE(KERN_INFO, device,
"(%ld B/blk): %ldkB",
(unsigned long) device->bp_block,
(unsigned long) (device->blocks <<
device->s2b_shift) >> 1);
- rc = 0;
}
+out:
free_page((long) label);
return rc;
}
@@ -529,7 +539,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
memset(dbio, 0, sizeof (struct dasd_diag_bio));
dbio->type = rw_cmd;
dbio->block_number = recid + 1;
- dbio->buffer = __pa(dst);
+ dbio->buffer = dst;
dbio++;
dst += blksize;
recid++;
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h
index b26eb28df4bf..df31484d73a7 100644
--- a/drivers/s390/block/dasd_diag.h
+++ b/drivers/s390/block/dasd_diag.h
@@ -6,7 +6,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
*
- * $Revision: 1.7 $
+ * $Revision: 1.8 $
*/
#define MDSK_WRITE_REQ 0x01
@@ -78,7 +78,7 @@ struct dasd_diag_bio {
u8 spare1[2];
u32 alet;
blocknum_t block_number;
- u64 buffer;
+ void *buffer;
} __attribute__ ((packed, aligned(8)));
struct dasd_diag_init_io {
@@ -104,7 +104,7 @@ struct dasd_diag_rw_io {
u32 alet;
u8 spare3[4];
u64 interrupt_params;
- u64 bio_list;
+ struct dasd_diag_bio *bio_list;
u8 spare4[8];
} __attribute__ ((packed, aligned(8)));
#else /* CONFIG_ARCH_S390X */
@@ -119,7 +119,7 @@ struct dasd_diag_bio {
u16 spare1;
blocknum_t block_number;
u32 alet;
- u32 buffer;
+ void *buffer;
} __attribute__ ((packed, aligned(8)));
struct dasd_diag_init_io {
@@ -142,7 +142,7 @@ struct dasd_diag_rw_io {
u8 spare2[2];
u32 block_count;
u32 alet;
- u32 bio_list;
+ struct dasd_diag_bio *bio_list;
u32 interrupt_params;
u8 spare3[20];
} __attribute__ ((packed, aligned(8)));
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index f11a67fda40e..75419cf9d353 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -727,8 +727,7 @@ raw3215_remove (struct ccw_device *cdev)
raw = cdev->dev.driver_data;
if (raw) {
cdev->dev.driver_data = NULL;
- if (raw->buffer)
- kfree(raw->buffer);
+ kfree(raw->buffer);
kfree(raw);
}
}
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index fd43d99b45a3..5bda2340a39d 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -99,13 +99,11 @@ out_fn_handler:
kfree(kbd->fn_handler);
out_func:
for (i = 0; i < ARRAY_SIZE(func_table); i++)
- if (kbd->func_table[i])
- kfree(kbd->func_table[i]);
+ kfree(kbd->func_table[i]);
kfree(kbd->func_table);
out_maps:
for (i = 0; i < ARRAY_SIZE(key_maps); i++)
- if (kbd->key_maps[i])
- kfree(kbd->key_maps[i]);
+ kfree(kbd->key_maps[i]);
kfree(kbd->key_maps);
out_kbd:
kfree(kbd);
@@ -121,12 +119,10 @@ kbd_free(struct kbd_data *kbd)
kfree(kbd->accent_table);
kfree(kbd->fn_handler);
for (i = 0; i < ARRAY_SIZE(func_table); i++)
- if (kbd->func_table[i])
- kfree(kbd->func_table[i]);
+ kfree(kbd->func_table[i]);
kfree(kbd->func_table);
for (i = 0; i < ARRAY_SIZE(key_maps); i++)
- if (kbd->key_maps[i])
- kfree(kbd->key_maps[i]);
+ kfree(kbd->key_maps[i]);
kfree(kbd->key_maps);
kfree(kbd);
}
@@ -452,8 +448,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
return -EFAULT;
}
p[len] = 0;
- if (kbd->func_table[kb_func])
- kfree(kbd->func_table[kb_func]);
+ kfree(kbd->func_table[kb_func]);
kbd->func_table[kb_func] = p;
break;
}
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index d66946443dfc..f5b7d360fc10 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -183,8 +183,7 @@ raw3270_request_alloc_bootmem(size_t size)
void
raw3270_request_free (struct raw3270_request *rq)
{
- if (rq->buffer)
- kfree(rq->buffer);
+ kfree(rq->buffer);
kfree(rq);
}
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 6c52e8307dc5..8f486e1a8507 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -682,8 +682,7 @@ tape_alloc_request(int cplength, int datasize)
request->cpdata = kmalloc(datasize, GFP_KERNEL | GFP_DMA);
if (request->cpdata == NULL) {
DBF_EXCEPTION(1, "cqra nomem\n");
- if (request->cpaddr != NULL)
- kfree(request->cpaddr);
+ kfree(request->cpaddr);
kfree(request);
return ERR_PTR(-ENOMEM);
}
@@ -706,10 +705,8 @@ tape_free_request (struct tape_request * request)
if (request->device != NULL) {
request->device = tape_put_device(request->device);
}
- if (request->cpdata != NULL)
- kfree(request->cpdata);
- if (request->cpaddr != NULL)
- kfree(request->cpaddr);
+ kfree(request->cpdata);
+ kfree(request->cpaddr);
kfree(request);
}
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 8990d8076e7d..19762f3476aa 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -103,8 +103,10 @@ vmcp_write(struct file *file, const char __user * buff, size_t count,
}
cmd[count] = '\0';
session = (struct vmcp_session *)file->private_data;
- if (down_interruptible(&session->mutex))
+ if (down_interruptible(&session->mutex)) {
+ kfree(cmd);
return -ERESTARTSYS;
+ }
if (!session->response)
session->response = (char *)__get_free_pages(GFP_KERNEL
| __GFP_REPEAT | GFP_DMA,
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index dbb3eb0e330b..e7bd7f37f080 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup
- * $Revision: 1.29 $
+ * $Revision: 1.32 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -274,7 +274,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev)
goto out;
}
gdrv = to_ccwgroupdrv (gdev->dev.driver);
- if ((ret = gdrv->set_online(gdev)))
+ if ((ret = gdrv->set_online ? gdrv->set_online(gdev) : 0))
goto out;
gdev->state = CCWGROUP_ONLINE;
@@ -300,7 +300,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
goto out;
}
gdrv = to_ccwgroupdrv (gdev->dev.driver);
- if ((ret = gdrv->set_offline(gdev)))
+ if ((ret = gdrv->set_offline ? gdrv->set_offline(gdev) : 0))
goto out;
gdev->state = CCWGROUP_OFFLINE;
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index c05b069c2996..b978f7fe8327 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -642,8 +642,7 @@ static void
free_cmbe (struct ccw_device *cdev)
{
spin_lock_irq(cdev->ccwlock);
- if (cdev->private->cmb)
- kfree(cdev->private->cmb);
+ kfree(cdev->private->cmb);
cdev->private->cmb = NULL;
spin_unlock_irq(cdev->ccwlock);
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index ad3fe5aeb663..85a3026e6900 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -550,10 +550,8 @@ ccw_device_stlck(struct ccw_device *cdev)
/* Clear irb. */
memset(&cdev->private->irb, 0, sizeof(struct irb));
out_unlock:
- if (buf)
- kfree(buf);
- if (buf2)
- kfree(buf2);
+ kfree(buf);
+ kfree(buf2);
spin_unlock_irqrestore(&sch->lock, flags);
return ret;
}
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 381f339e3200..eb39218b925e 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.101 $"
+#define VERSION_QDIO_C "$Revision: 1.108 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -1338,16 +1338,14 @@ qdio_release_irq_memory(struct qdio_irq *irq_ptr)
if (!irq_ptr->input_qs[i])
goto next;
- if (irq_ptr->input_qs[i]->slib)
- kfree(irq_ptr->input_qs[i]->slib);
+ kfree(irq_ptr->input_qs[i]->slib);
kfree(irq_ptr->input_qs[i]);
next:
if (!irq_ptr->output_qs[i])
continue;
- if (irq_ptr->output_qs[i]->slib)
- kfree(irq_ptr->output_qs[i]->slib);
+ kfree(irq_ptr->output_qs[i]->slib);
kfree(irq_ptr->output_qs[i]);
}
@@ -2873,10 +2871,10 @@ qdio_establish(struct qdio_initialize *init_data)
return result;
}
- wait_event_interruptible_timeout(cdev->private->wait_q,
+ /* Timeout is cared for already by using ccw_device_start_timeout(). */
+ wait_event_interruptible(cdev->private->wait_q,
irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED ||
- irq_ptr->state == QDIO_IRQ_STATE_ERR,
- QDIO_ESTABLISH_TIMEOUT);
+ irq_ptr->state == QDIO_IRQ_STATE_ERR);
if (irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED)
result = 0;
@@ -3315,8 +3313,7 @@ qdio_get_qdio_memory(void)
static void
qdio_release_qdio_memory(void)
{
- if (indicators)
- kfree(indicators);
+ kfree(indicators);
}
static void
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 0cb47eca91f3..04c2ef778ec6 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -3051,8 +3051,7 @@ destroy_crypto_device(int index)
if (dev_ptr) {
disabledFlag = dev_ptr->disabled;
t = dev_ptr->dev_type;
- if (dev_ptr->dev_resp_p)
- kfree(dev_ptr->dev_resp_p);
+ kfree(dev_ptr->dev_resp_p);
kfree(dev_ptr);
} else {
disabledFlag = 0;
@@ -3080,11 +3079,11 @@ static void
destroy_z90crypt(void)
{
int i;
+
for (i = 0; i < z90crypt.max_count; i++)
if (z90crypt.device_p[i])
destroy_crypto_device(i);
- if (z90crypt.hdware_info)
- kfree((void *)z90crypt.hdware_info);
+ kfree(z90crypt.hdware_info);
memset((void *)&z90crypt, 0, sizeof(z90crypt));
}
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 3092473991a7..1a1c3decea72 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -2743,14 +2743,10 @@ probe_error( struct ccwgroup_device *cgdev)
#endif
privptr=(struct claw_privbk *)cgdev->dev.driver_data;
if (privptr!=NULL) {
- if (privptr->p_env != NULL) {
- kfree(privptr->p_env);
- privptr->p_env=NULL;
- }
- if (privptr->p_mtc_envelope!=NULL) {
- kfree(privptr->p_mtc_envelope);
- privptr->p_mtc_envelope=NULL;
- }
+ kfree(privptr->p_env);
+ privptr->p_env=NULL;
+ kfree(privptr->p_mtc_envelope);
+ privptr->p_mtc_envelope=NULL;
kfree(privptr);
privptr=NULL;
}
@@ -4121,22 +4117,14 @@ claw_remove_device(struct ccwgroup_device *cgdev)
if (cgdev->state == CCWGROUP_ONLINE)
claw_shutdown_device(cgdev);
claw_remove_files(&cgdev->dev);
- if (priv->p_mtc_envelope!=NULL) {
- kfree(priv->p_mtc_envelope);
- priv->p_mtc_envelope=NULL;
- }
- if (priv->p_env != NULL) {
- kfree(priv->p_env);
- priv->p_env=NULL;
- }
- if (priv->channel[0].irb != NULL) {
- kfree(priv->channel[0].irb);
- priv->channel[0].irb=NULL;
- }
- if (priv->channel[1].irb != NULL) {
- kfree(priv->channel[1].irb);
- priv->channel[1].irb=NULL;
- }
+ kfree(priv->p_mtc_envelope);
+ priv->p_mtc_envelope=NULL;
+ kfree(priv->p_env);
+ priv->p_env=NULL;
+ kfree(priv->channel[0].irb);
+ priv->channel[0].irb=NULL;
+ kfree(priv->channel[1].irb);
+ priv->channel[1].irb=NULL;
kfree(priv);
cgdev->dev.driver_data=NULL;
cgdev->cdev[READ]->dev.driver_data = NULL;
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c
index 38f50b7129a2..24029bd9c7d0 100644
--- a/drivers/s390/net/fsm.c
+++ b/drivers/s390/net/fsm.c
@@ -78,8 +78,7 @@ kfree_fsm(fsm_instance *this)
{
if (this) {
if (this->f) {
- if (this->f->jumpmatrix)
- kfree(this->f->jumpmatrix);
+ kfree(this->f->jumpmatrix);
kfree(this->f);
}
kfree(this);
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index e08e74e16124..df7647c3c100 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -447,14 +447,10 @@ static void
iucv_exit(void)
{
iucv_retrieve_buffer();
- if (iucv_external_int_buffer) {
- kfree(iucv_external_int_buffer);
- iucv_external_int_buffer = NULL;
- }
- if (iucv_param_pool) {
- kfree(iucv_param_pool);
- iucv_param_pool = NULL;
- }
+ kfree(iucv_external_int_buffer);
+ iucv_external_int_buffer = NULL;
+ kfree(iucv_param_pool);
+ iucv_param_pool = NULL;
s390_root_dev_unregister(iucv_root);
bus_unregister(&iucv_bus);
printk(KERN_INFO "IUCV lowlevel driver unloaded\n");
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 46f34ba93ac5..1c8ad2fcad8a 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -145,8 +145,7 @@ lcs_free_channel(struct lcs_channel *channel)
LCS_DBF_TEXT(2, setup, "ichfree");
for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) {
- if (channel->iob[cnt].data != NULL)
- kfree(channel->iob[cnt].data);
+ kfree(channel->iob[cnt].data);
channel->iob[cnt].data = NULL;
}
}
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index f94f1f25eec6..011915d5e243 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -62,8 +62,7 @@ qeth_eddp_free_context(struct qeth_eddp_context *ctx)
for (i = 0; i < ctx->num_pages; ++i)
free_page((unsigned long)ctx->pages[i]);
kfree(ctx->pages);
- if (ctx->elements != NULL)
- kfree(ctx->elements);
+ kfree(ctx->elements);
kfree(ctx);
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index cab098556b44..c218b5c944a6 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -450,8 +450,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
kfree(sg_list);
}
- if (sense_data != NULL)
- kfree(sense_data);
+ kfree(sense_data);
return retval;
}
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index b0cc3c2588fd..ba56762b05f6 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -1125,10 +1125,9 @@ out_deregister:
misc_deregister(&envctrl_dev);
out_iounmap:
iounmap(i2c);
- for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) {
- if (i2c_childlist[i].tables)
- kfree(i2c_childlist[i].tables);
- }
+ for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++)
+ kfree(i2c_childlist[i].tables);
+
return err;
}
@@ -1141,10 +1140,8 @@ static void __exit envctrl_cleanup(void)
iounmap(i2c);
misc_deregister(&envctrl_dev);
- for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) {
- if (i2c_childlist[i].tables)
- kfree(i2c_childlist[i].tables);
- }
+ for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++)
+ kfree(i2c_childlist[i].tables);
}
module_init(envctrl_init);
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index d06ee65d668d..3ff74f472249 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1017,8 +1017,7 @@ static void twa_free_device_extension(TW_Device_Extension *tw_dev)
tw_dev->generic_buffer_virt[0],
tw_dev->generic_buffer_phys[0]);
- if (tw_dev->event_queue[0])
- kfree(tw_dev->event_queue[0]);
+ kfree(tw_dev->event_queue[0]);
} /* End twa_free_device_extension() */
/* This function will free a request id */
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index cc9ecb35b412..cba9655d0f14 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -606,10 +606,7 @@ static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
while (probe_irq == SCSI_IRQ_NONE && time_before(jiffies, timeout))
- {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ schedule_timeout_uninterruptible(1);
NCR5380_write(SELECT_ENABLE_REG, 0);
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index ee9067255930..723c0cea7c04 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1164,7 +1164,7 @@ int aac_command_thread(struct aac_dev * dev)
kfree(hw_fib_pool);
hw_fib_pool = NULL;
}
- } else if (hw_fib_pool) {
+ } else {
kfree(hw_fib_pool);
hw_fib_pool = NULL;
}
@@ -1247,17 +1247,13 @@ int aac_command_thread(struct aac_dev * dev)
hw_fib_p = hw_fib_pool;
fib_p = fib_pool;
while (hw_fib_p < &hw_fib_pool[num]) {
- if (*hw_fib_p)
- kfree(*hw_fib_p);
- if (*fib_p)
- kfree(*fib_p);
+ kfree(*hw_fib_p);
+ kfree(*fib_p);
++fib_p;
++hw_fib_p;
}
- if (hw_fib_pool)
- kfree(hw_fib_pool);
- if (fib_pool)
- kfree(fib_pool);
+ kfree(hw_fib_pool);
+ kfree(fib_pool);
}
kfree(fib);
spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags);
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index fc4c73c2a6a9..e9b775d6bec9 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -183,8 +183,7 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Yield the processor in case we are slow
*/
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (ok != 1) {
/*
@@ -452,8 +451,7 @@ int aac_rkt_init(struct aac_dev *dev)
dev->name, instance, status);
goto error_iounmap;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0)
{
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index da99046e5393..6998bc877dd6 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -183,8 +183,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Yield the processor in case we are slow
*/
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (ok != 1) {
/*
@@ -452,8 +451,7 @@ int aac_rx_init(struct aac_dev *dev)
dev->name, instance, status);
goto error_iounmap;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0)
{
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index 8b9596209164..466f05cfbf0c 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -189,8 +189,7 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command,
ok = 1;
break;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (ok != 1)
@@ -325,8 +324,7 @@ int aac_sa_init(struct aac_dev *dev)
name, instance, status);
goto error_iounmap;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) {
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 37ec5411e325..f4cfb8f29620 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -5402,10 +5402,8 @@ advansys_detect(struct scsi_host_template *tpnt)
release_region(shp->io_port, boardp->asc_n_io_port);
if (ASC_WIDE_BOARD(boardp)) {
iounmap(boardp->ioremap_addr);
- if (boardp->orig_carrp) {
- kfree(boardp->orig_carrp);
- boardp->orig_carrp = NULL;
- }
+ kfree(boardp->orig_carrp);
+ boardp->orig_carrp = NULL;
if (boardp->orig_reqp) {
kfree(boardp->orig_reqp);
boardp->orig_reqp = boardp->adv_reqp = NULL;
@@ -5457,10 +5455,8 @@ advansys_release(struct Scsi_Host *shp)
adv_sgblk_t *sgp = NULL;
iounmap(boardp->ioremap_addr);
- if (boardp->orig_carrp) {
- kfree(boardp->orig_carrp);
- boardp->orig_carrp = NULL;
- }
+ kfree(boardp->orig_carrp);
+ boardp->orig_carrp = NULL;
if (boardp->orig_reqp) {
kfree(boardp->orig_reqp);
boardp->orig_reqp = boardp->adv_reqp = NULL;
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index adda750412f2..1b1adfb384cb 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -543,10 +543,8 @@ static void aha1542_intr_handle(struct Scsi_Host *shost, void *dev_id, struct pt
return;
}
my_done = SCtmp->scsi_done;
- if (SCtmp->host_scribble) {
- kfree(SCtmp->host_scribble);
- SCtmp->host_scribble = NULL;
- }
+ kfree(SCtmp->host_scribble);
+ SCtmp->host_scribble = NULL;
/* Fetch the sense data, and tuck it away, in the required slot. The
Adaptec automatically fetches it, and there is no guarantee that
we will still have it in the cdb when we come back */
@@ -1432,10 +1430,8 @@ static int aha1542_dev_reset(Scsi_Cmnd * SCpnt)
HOSTDATA(SCpnt->host)->SCint[i]->target == SCpnt->target) {
Scsi_Cmnd *SCtmp;
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
- if (SCtmp->host_scribble) {
- kfree(SCtmp->host_scribble);
- SCtmp->host_scribble = NULL;
- }
+ kfree(SCtmp->host_scribble);
+ SCtmp->host_scribble = NULL;
HOSTDATA(SCpnt->host)->SCint[i] = NULL;
HOSTDATA(SCpnt->host)->mb[i].status = 0;
}
@@ -1495,10 +1491,8 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
*/
continue;
}
- if (SCtmp->host_scribble) {
- kfree(SCtmp->host_scribble);
- SCtmp->host_scribble = NULL;
- }
+ kfree(SCtmp->host_scribble);
+ SCtmp->host_scribble = NULL;
HOSTDATA(SCpnt->device->host)->SCint[i] = NULL;
HOSTDATA(SCpnt->device->host)->mb[i].status = 0;
}
@@ -1565,10 +1559,8 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
*/
continue;
}
- if (SCtmp->host_scribble) {
- kfree(SCtmp->host_scribble);
- SCtmp->host_scribble = NULL;
- }
+ kfree(SCtmp->host_scribble);
+ SCtmp->host_scribble = NULL;
HOSTDATA(SCpnt->device->host)->SCint[i] = NULL;
HOSTDATA(SCpnt->device->host)->mb[i].status = 0;
}
@@ -1711,10 +1703,8 @@ static int aha1542_old_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
Scsi_Cmnd *SCtmp;
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
SCtmp->result = DID_RESET << 16;
- if (SCtmp->host_scribble) {
- kfree(SCtmp->host_scribble);
- SCtmp->host_scribble = NULL;
- }
+ kfree(SCtmp->host_scribble);
+ SCtmp->host_scribble = NULL;
printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target);
SCtmp->scsi_done(SCpnt);
@@ -1757,10 +1747,8 @@ fail:
Scsi_Cmnd *SCtmp;
SCtmp = HOSTDATA(SCpnt->host)->SCint[i];
SCtmp->result = DID_RESET << 16;
- if (SCtmp->host_scribble) {
- kfree(SCtmp->host_scribble);
- SCtmp->host_scribble = NULL;
- }
+ kfree(SCtmp->host_scribble);
+ SCtmp->host_scribble = NULL;
printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target);
SCtmp->scsi_done(SCpnt);
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 52b72d7794f5..880e2d9ffe9b 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -8492,8 +8492,7 @@ aic7xxx_free(struct aic7xxx_host *p)
- scb_dma->dma_offset),
scb_dma->dma_address);
}
- if (p->scb_data->scb_array[i]->kmalloc_ptr != NULL)
- kfree(p->scb_data->scb_array[i]->kmalloc_ptr);
+ kfree(p->scb_data->scb_array[i]->kmalloc_ptr);
p->scb_data->scb_array[i] = NULL;
}
diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c
index e6d159270d29..b10750bb5c09 100644
--- a/drivers/scsi/arm/queue.c
+++ b/drivers/scsi/arm/queue.c
@@ -91,8 +91,7 @@ void queue_free (Queue_t *queue)
{
if (!list_empty(&queue->head))
printk(KERN_WARNING "freeing non-empty queue %p\n", queue);
- if (queue->alloc)
- kfree(queue->alloc);
+ kfree(queue->alloc);
}
diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c
index 7026045527fd..8d5d2a5da961 100644
--- a/drivers/scsi/atari_dma_emul.c
+++ b/drivers/scsi/atari_dma_emul.c
@@ -19,6 +19,8 @@
* this code.
*/
+#include <linux/compiler.h>
+#include <asm/thread_info.h>
#include <asm/uaccess.h>
#define hades_dma_ctrl (*(unsigned char *) 0xffff8717)
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index c44af5795b10..c8a32cf47d73 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -4270,8 +4270,7 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
- if (acb->srb_array[i].segment_x)
- kfree(acb->srb_array[i].segment_x);
+ kfree(acb->srb_array[i].segment_x);
}
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 7235f94f1191..c28e3aea1c3c 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -1037,18 +1037,10 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
if(pHba->msg_addr_virt != pHba->base_addr_virt){
iounmap(pHba->msg_addr_virt);
}
- if(pHba->hrt) {
- kfree(pHba->hrt);
- }
- if(pHba->lct){
- kfree(pHba->lct);
- }
- if(pHba->status_block) {
- kfree(pHba->status_block);
- }
- if(pHba->reply_pool){
- kfree(pHba->reply_pool);
- }
+ kfree(pHba->hrt);
+ kfree(pHba->lct);
+ kfree(pHba->status_block);
+ kfree(pHba->reply_pool);
for(d = pHba->devices; d ; d = next){
next = d->next;
@@ -1218,8 +1210,7 @@ static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len)
printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit);
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while(m == EMPTY_QUEUE);
msg = pHba->msg_addr_virt + m;
@@ -1294,8 +1285,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
printk(KERN_WARNING"Timeout waiting for message!\n");
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (m == EMPTY_QUEUE);
status = (u8*)kmalloc(4, GFP_KERNEL|ADDR32);
@@ -1327,8 +1317,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
return -ETIMEDOUT;
}
rmb();
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) {
@@ -1345,8 +1334,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name);
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (m == EMPTY_QUEUE);
// Flush the offset
adpt_send_nop(pHba, m);
@@ -1917,11 +1905,8 @@ static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd,
return -ENXIO;
}
- while((volatile u32) pHba->state & DPTI_STATE_RESET ) {
- set_task_state(current,TASK_UNINTERRUPTIBLE);
- schedule_timeout(2);
-
- }
+ while((volatile u32) pHba->state & DPTI_STATE_RESET )
+ schedule_timeout_uninterruptible(2);
switch (cmd) {
// TODO: handle 3 cases
@@ -2635,8 +2620,7 @@ static s32 adpt_send_nop(adpt_hba*pHba,u32 m)
printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name);
return 2;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
msg = (u32 __iomem *)(pHba->msg_addr_virt + m);
writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]);
@@ -2670,8 +2654,7 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name);
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while(m == EMPTY_QUEUE);
msg=(u32 __iomem *)(pHba->msg_addr_virt+m);
@@ -2709,21 +2692,18 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba)
printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name);
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while (1);
// If the command was successful, fill the fifo with our reply
// message packets
if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) {
- kfree((void*)status);
+ kfree(status);
return -2;
}
- kfree((void*)status);
+ kfree(status);
- if(pHba->reply_pool != NULL){
- kfree(pHba->reply_pool);
- }
+ kfree(pHba->reply_pool);
pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32);
if(!pHba->reply_pool){
@@ -2788,8 +2768,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba)
pHba->name);
return -ETIMEDOUT;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
} while(m==EMPTY_QUEUE);
@@ -2816,8 +2795,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba)
return -ETIMEDOUT;
}
rmb();
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
}
// Set up our number of outbound and inbound messages
@@ -2941,8 +2919,7 @@ static int adpt_i2o_build_sys_table(void)
sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
(hba_count) * sizeof(struct i2o_sys_tbl_entry);
- if(sys_tbl)
- kfree(sys_tbl);
+ kfree(sys_tbl);
sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL|ADDR32);
if(!sys_tbl) {
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index b45a4c730230..b3f9de8f7595 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -2580,8 +2580,7 @@ static int eata2x_release(struct Scsi_Host *shost)
unsigned int i;
for (i = 0; i < shost->can_queue; i++)
- if ((&ha->cp[i])->sglist)
- kfree((&ha->cp[i])->sglist);
+ kfree((&ha->cp[i])->sglist);
for (i = 0; i < shost->can_queue; i++)
pci_unmap_single(ha->pdev, ha->cp[i].cp_dma_addr,
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f04f3289938d..c888af4a4562 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -331,9 +331,9 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co
rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
buf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
if (pc == NULL || rq == NULL || buf == NULL) {
- if (pc) kfree(pc);
- if (rq) kfree(rq);
- if (buf) kfree(buf);
+ kfree(buf);
+ kfree(rq);
+ kfree(pc);
return -ENOMEM;
}
memset (pc, 0, sizeof (idescsi_pc_t));
@@ -949,8 +949,8 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
spin_lock_irq(host->host_lock);
return 0;
abort:
- if (pc) kfree (pc);
- if (rq) kfree (rq);
+ kfree (pc);
+ kfree (rq);
cmd->result = DID_ERROR << 16;
done(cmd);
return 0;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index 68e5b2ab27c4..cd9b95db5a7d 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -4517,10 +4517,8 @@ ips_free(ips_ha_t * ha)
ha->enq = NULL;
}
- if (ha->conf) {
- kfree(ha->conf);
- ha->conf = NULL;
- }
+ kfree(ha->conf);
+ ha->conf = NULL;
if (ha->adapt) {
pci_free_consistent(ha->pcidev,
@@ -4538,15 +4536,11 @@ ips_free(ips_ha_t * ha)
ha->logical_drive_info = NULL;
}
- if (ha->nvram) {
- kfree(ha->nvram);
- ha->nvram = NULL;
- }
+ kfree(ha->nvram);
+ ha->nvram = NULL;
- if (ha->subsys) {
- kfree(ha->subsys);
- ha->subsys = NULL;
- }
+ kfree(ha->subsys);
+ ha->subsys = NULL;
if (ha->ioctl_data) {
pci_free_consistent(ha->pcidev, ha->ioctl_len,
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 08a0c00cfc30..bcc29ec126dc 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -127,8 +127,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
if (((pcmd = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
((pcmd->virt = lpfc_mbuf_alloc(phba,
MEM_PRI, &(pcmd->phys))) == 0)) {
- if (pcmd)
- kfree(pcmd);
+ kfree(pcmd);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, elsiocb);
@@ -145,8 +144,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
&prsp->phys);
if (prsp == 0 || prsp->virt == 0) {
- if (prsp)
- kfree(prsp);
+ kfree(prsp);
lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
kfree(pcmd);
spin_lock_irq(phba->host->host_lock);
@@ -172,8 +170,7 @@ lpfc_prep_els_iocb(struct lpfc_hba * phba,
lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
kfree(pcmd);
kfree(prsp);
- if (pbuflist)
- kfree(pbuflist);
+ kfree(pbuflist);
return NULL;
}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4e04470321a2..c90723860a04 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -894,8 +894,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
mp1->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
&mp1->phys);
if (mp1 == 0 || mp1->virt == 0) {
- if (mp1)
- kfree(mp1);
+ kfree(mp1);
spin_lock_irq(phba->host->host_lock);
lpfc_sli_release_iocbq(phba, iocb);
spin_unlock_irq(phba->host->host_lock);
@@ -911,8 +910,7 @@ lpfc_post_buffer(struct lpfc_hba * phba, struct lpfc_sli_ring * pring, int cnt,
mp2->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
&mp2->phys);
if (mp2 == 0 || mp2->virt == 0) {
- if (mp2)
- kfree(mp2);
+ kfree(mp2);
lpfc_mbuf_free(phba, mp1->virt, mp1->phys);
kfree(mp1);
spin_lock_irq(phba->host->host_lock);
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 31c20cc00609..e3bc8d3f7302 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -248,8 +248,7 @@ lpfc_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
- if (mp)
- kfree(mp);
+ kfree(mp);
mb->mbxCommand = MBX_READ_SPARM64;
/* READ_SPARAM: no buffers */
lpfc_printf_log(phba,
@@ -363,9 +362,7 @@ lpfc_reg_login(struct lpfc_hba * phba,
/* Get a buffer to hold NPorts Service Parameters */
if (((mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == NULL) ||
((mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys))) == 0)) {
- if (mp)
- kfree(mp);
-
+ kfree(mp);
mb->mbxCommand = MBX_REG_LOGIN64;
/* REG_LOGIN: no buffers */
lpfc_printf_log(phba,
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c34d3cf4f19c..c63275e66e2e 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -825,8 +825,7 @@ __lpfc_abort_handler(struct scsi_cmnd *cmnd)
while (lpfc_cmd->pCmd == cmnd)
{
spin_unlock_irq(phba->host->host_lock);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(LPFC_ABORT_WAIT*HZ);
+ schedule_timeout_uninterruptible(LPFC_ABORT_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
if (++loop_count
> (2 * phba->cfg_nodev_tmo)/LPFC_ABORT_WAIT)
@@ -885,8 +884,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
spin_unlock_irq(phba->host->host_lock);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout( HZ/2);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(500));
spin_lock_irq(phba->host->host_lock);
}
if ((pnode) && (pnode->nlp_state == NLP_STE_MAPPED_NODE))
@@ -939,8 +937,7 @@ __lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
cmnd->device->id, cmnd->device->lun,
LPFC_CTX_LUN))) {
spin_unlock_irq(phba->host->host_lock);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(LPFC_RESET_WAIT*HZ);
+ schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
if (++loopcnt
@@ -1038,8 +1035,7 @@ __lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
&phba->sli.ring[phba->sli.fcp_ring],
0, 0, LPFC_CTX_HOST))) {
spin_unlock_irq(phba->host->host_lock);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(LPFC_RESET_WAIT*HZ);
+ schedule_timeout_uninterruptible(LPFC_RESET_WAIT*HZ);
spin_lock_irq(phba->host->host_lock);
if (++loopcnt
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 508710001ed6..e2c08c5d83fb 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -2269,11 +2269,8 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
INIT_LIST_HEAD(&(pring->txq));
- if (pring->fast_lookup) {
- kfree(pring->fast_lookup);
- pring->fast_lookup = NULL;
- }
-
+ kfree(pring->fast_lookup);
+ pring->fast_lookup = NULL;
}
spin_unlock_irqrestore(phba->host->host_lock, flags);
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index c9e743ba09ec..1a3d195a2d36 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -3937,9 +3937,8 @@ megaraid_sysfs_free_resources(adapter_t *adapter)
{
mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter);
- if (raid_dev->sysfs_uioc) kfree(raid_dev->sysfs_uioc);
-
- if (raid_dev->sysfs_mbox64) kfree(raid_dev->sysfs_mbox64);
+ kfree(raid_dev->sysfs_uioc);
+ kfree(raid_dev->sysfs_mbox64);
if (raid_dev->sysfs_buffer) {
pci_free_consistent(adapter->pdev, PAGE_SIZE,
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 37d110e864c4..8f3ce0432295 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -995,17 +995,13 @@ pthru_dma_pool_error:
memalloc_error:
- if (adapter->kioc_list)
- kfree(adapter->kioc_list);
-
- if (adapter->mbox_list)
- kfree(adapter->mbox_list);
+ kfree(adapter->kioc_list);
+ kfree(adapter->mbox_list);
if (adapter->pthru_dma_pool)
pci_pool_destroy(adapter->pthru_dma_pool);
- if (adapter)
- kfree(adapter);
+ kfree(adapter);
return rval;
}
@@ -1157,7 +1153,6 @@ mraid_mm_free_adp_resources(mraid_mmadp_t *adp)
}
kfree(adp->kioc_list);
-
kfree(adp->mbox_list);
pci_pool_destroy(adp->pthru_dma_pool);
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 1cf11c3322fb..d9946bd95492 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -862,8 +862,7 @@ static int osst_recover_wait_frame(struct osst_tape * STp, struct scsi_request *
retval = osst_write_error_recovery(STp, aSRpnt, 0);
break;
}
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout (HZ / OSST_POLL_PER_SEC);
+ schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
memset(cmd, 0, MAX_COMMAND_SIZE);
@@ -1558,8 +1557,7 @@ static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request
osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
flag = 0;
attempts--;
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
}
if (osst_get_frame_position(STp, aSRpnt) < 0) { /* additional write error */
#if DEBUG
@@ -1620,8 +1618,7 @@ static int osst_reposition_and_retry(struct osst_tape * STp, struct scsi_request
debugging = 0;
}
#endif
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10);
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
}
printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
#if DEBUG
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 290a6b92616c..72d9090df3df 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1977,8 +1977,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
}
cleanup_allocation:
- if (new_fcport)
- kfree(new_fcport);
+ kfree(new_fcport);
if (rval != QLA_SUCCESS) {
DEBUG2(printk("scsi(%ld): Configure local loop error exit: "
@@ -2348,8 +2347,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
/* Allocate temporary fcport for any new fcports discovered. */
new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
if (new_fcport == NULL) {
- if (swl)
- kfree(swl);
+ kfree(swl);
return (QLA_MEMORY_ALLOC_FAILED);
}
new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
@@ -2485,19 +2483,15 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
nxt_d_id.b24 = new_fcport->d_id.b24;
new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
if (new_fcport == NULL) {
- if (swl)
- kfree(swl);
+ kfree(swl);
return (QLA_MEMORY_ALLOC_FAILED);
}
new_fcport->flags |= (FCF_FABRIC_DEVICE | FCF_LOGIN_NEEDED);
new_fcport->d_id.b24 = nxt_d_id.b24;
}
- if (swl)
- kfree(swl);
-
- if (new_fcport)
- kfree(new_fcport);
+ kfree(swl);
+ kfree(new_fcport);
if (!list_empty(new_fcports))
ha->device_flags |= DFLG_FABRIC_DEVICES;
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index f1ea5027865f..caa0c3629626 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -4,6 +4,8 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/raid_class.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 0cc766a9aa65..edabbd05d258 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -26,6 +26,8 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/string.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 4f30a37db63c..62e3f340cc52 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -476,8 +476,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
sg_finish_rem_req(srp);
retval = count;
free_old_hdr:
- if (old_hdr)
- kfree(old_hdr);
+ kfree(old_hdr);
return retval;
}
@@ -1703,10 +1702,8 @@ exit_sg(void)
sg_sysfs_valid = 0;
unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
SG_MAX_DEVS);
- if (sg_dev_arr != NULL) {
- kfree((char *) sg_dev_arr);
- sg_dev_arr = NULL;
- }
+ kfree((char *)sg_dev_arr);
+ sg_dev_arr = NULL;
sg_dev_max = 0;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 6b85f84c8397..770c4324f3d5 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4107,8 +4107,7 @@ out_free_tape:
write_unlock(&st_dev_arr_lock);
out_put_disk:
put_disk(disk);
- if (tpnt)
- kfree(tpnt);
+ kfree(tpnt);
out_buffer_free:
kfree(buffer);
out:
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index a1a58e1d5ad3..a7420cad4547 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -39,6 +39,7 @@
*/
#include <linux/slab.h>
+#include <asm/param.h> /* for timeouts in units of HZ */
#include "sym_glue.h"
#include "sym_nvram.h"
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index cfab8f197084..1ce29ba683eb 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -1953,11 +1953,11 @@ static int u14_34f_release(struct Scsi_Host *shpnt) {
for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++);
- if (sh[j] == NULL) panic("%s: release, invalid Scsi_Host pointer.\n",
- driver_name);
+ if (sh[j] == NULL)
+ panic("%s: release, invalid Scsi_Host pointer.\n", driver_name);
for (i = 0; i < sh[j]->can_queue; i++)
- if ((&HD(j)->cp[i])->sglist) kfree((&HD(j)->cp[i])->sglist);
+ kfree((&HD(j)->cp[i])->sglist);
for (i = 0; i < sh[j]->can_queue; i++)
pci_unmap_single(HD(j)->pdev, HD(j)->cp[i].cp_dma_addr,
@@ -1965,7 +1965,8 @@ static int u14_34f_release(struct Scsi_Host *shpnt) {
free_irq(sh[j]->irq, &sha[j]);
- if (sh[j]->dma_channel != NO_DMA) free_dma(sh[j]->dma_channel);
+ if (sh[j]->dma_channel != NO_DMA)
+ free_dma(sh[j]->dma_channel);
release_region(sh[j]->io_port, sh[j]->n_io_port);
scsi_unregister(sh[j]);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 186e96c47b3d..98820603e75f 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -40,6 +40,7 @@
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
+#include <linux/nmi.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -2208,6 +2209,8 @@ serial8250_console_write(struct console *co, const char *s, unsigned int count)
unsigned int ier;
int i;
+ touch_nmi_watchdog();
+
/*
* First save the UER then disable the interrupts
*/
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 40d3e7139cfe..08c42c000188 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -4416,10 +4416,8 @@ rs_close(struct tty_struct *tty, struct file * filp)
info->event = 0;
info->tty = 0;
if (info->blocked_open) {
- if (info->close_delay) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->close_delay);
- }
+ if (info->close_delay)
+ schedule_timeout_interruptible(info->close_delay);
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
@@ -4469,8 +4467,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
while (info->xmit.head != info->xmit.tail || /* More in send queue */
(*info->ostatusadr & 0x007f) || /* more in FIFO */
(elapsed_usec < 2*info->char_time_usec)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
+ schedule_timeout_interruptible(1);
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index e2ebdcad553c..47f7404cb045 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -57,7 +57,8 @@ struct timer_list mcfrs_timer_struct;
* keep going. Perhaps one day the cflag settings for the
* console can be used instead.
*/
-#if defined(CONFIG_ARNEWSH) || defined(CONFIG_MOTOROLA) || defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
+#if defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
+ defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
#define CONSOLE_BAUD_RATE 19200
#define DEFAULT_CBAUD B19200
#endif
@@ -67,7 +68,7 @@ struct timer_list mcfrs_timer_struct;
#define DEFAULT_CBAUD B38400
#endif
-#if defined(CONFIG_MOD5272)
+#if defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
#define CONSOLE_BAUD_RATE 115200
#define DEFAULT_CBAUD B115200
#endif
@@ -95,7 +96,8 @@ static struct tty_driver *mcfrs_serial_driver;
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+ defined(CONFIG_M520x)
#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
#else
#define IRQBASE 73
@@ -1528,6 +1530,35 @@ static void mcfrs_irqinit(struct mcf_serial *info)
imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_IMRL);
*imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
+#elif defined(CONFIG_M520x)
+ volatile unsigned char *icrp, *uartp;
+ volatile unsigned long *imrp;
+
+ uartp = info->addr;
+
+ icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 +
+ MCFINTC_ICR0 + MCFINT_UART0 + info->line);
+ *icrp = 0x03;
+
+ imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
+ MCFINTC_IMRL);
+ *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
+ if (info->line < 2) {
+ unsigned short *uart_par;
+ uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+ if (info->line == 0)
+ *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD0
+ | MCF_GPIO_PAR_UART_PAR_URXD0;
+ else if (info->line == 1)
+ *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD1
+ | MCF_GPIO_PAR_UART_PAR_URXD1;
+ } else if (info->line == 2) {
+ unsigned char *feci2c_par;
+ feci2c_par = (unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
+ *feci2c_par &= ~0x0F;
+ *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2
+ | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
+ }
#else
volatile unsigned char *icrp, *uartp;
diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c
index dc119ce68e3e..55434330867b 100644
--- a/drivers/sh/superhyway/superhyway-sysfs.c
+++ b/drivers/sh/superhyway/superhyway-sysfs.c
@@ -30,7 +30,7 @@ superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb);
superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb);
/* Misc */
-superhyway_ro_attr(resource, "0x%08lx\n", resource.start);
+superhyway_ro_attr(resource, "0x%08lx\n", resource[0].start);
struct device_attribute superhyway_dev_attrs[] = {
__ATTR_RO(perr_flags),
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
index 28757cb9d246..7bdab2a7f59c 100644
--- a/drivers/sh/superhyway/superhyway.c
+++ b/drivers/sh/superhyway/superhyway.c
@@ -27,19 +27,20 @@ static struct device superhyway_bus_device = {
static void superhyway_device_release(struct device *dev)
{
- kfree(to_superhyway_device(dev));
+ struct superhyway_device *sdev = to_superhyway_device(dev);
+
+ kfree(sdev->resource);
+ kfree(sdev);
}
/**
* superhyway_add_device - Add a SuperHyway module
- * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
* @base: Physical address where module is mapped.
- * @vcr: VCR value.
+ * @sdev: SuperHyway device to add, or NULL to allocate a new one.
+ * @bus: Bus where SuperHyway module resides.
*
* This is responsible for adding a new SuperHyway module. This sets up a new
- * struct superhyway_device for the module being added. Each one of @mod_id,
- * @base, and @vcr are registered with the new device for further use
- * elsewhere.
+ * struct superhyway_device for the module being added if @sdev == NULL.
*
* Devices are initially added in the order that they are scanned (from the
* top-down of the memory map), and are assigned an ID based on the order that
@@ -49,28 +50,40 @@ static void superhyway_device_release(struct device *dev)
* Further work can and should be done in superhyway_scan_bus(), to be sure
* that any new modules are properly discovered and subsequently registered.
*/
-int superhyway_add_device(unsigned int mod_id, unsigned long base,
- unsigned long long vcr)
+int superhyway_add_device(unsigned long base, struct superhyway_device *sdev,
+ struct superhyway_bus *bus)
{
- struct superhyway_device *dev;
+ struct superhyway_device *dev = sdev;
+
+ if (!dev) {
+ dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
- dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
+ memset(dev, 0, sizeof(struct superhyway_device));
+ }
- memset(dev, 0, sizeof(struct superhyway_device));
+ dev->bus = bus;
+ superhyway_read_vcr(dev, base, &dev->vcr);
- dev->id.id = mod_id;
- sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
+ if (!dev->resource) {
+ dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL);
+ if (!dev->resource) {
+ kfree(dev);
+ return -ENOMEM;
+ }
+
+ dev->resource->name = dev->name;
+ dev->resource->start = base;
+ dev->resource->end = dev->resource->start + 0x01000000;
+ }
- dev->vcr = *((struct vcr_info *)(&vcr));
- dev->resource.name = dev->name;
- dev->resource.start = base;
- dev->resource.end = dev->resource.start + 0x01000000;
dev->dev.parent = &superhyway_bus_device;
dev->dev.bus = &superhyway_bus_type;
dev->dev.release = superhyway_device_release;
+ dev->id.id = dev->vcr.mod_id;
+ sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
superhyway_devices++;
@@ -78,10 +91,31 @@ int superhyway_add_device(unsigned int mod_id, unsigned long base,
return device_register(&dev->dev);
}
+int superhyway_add_devices(struct superhyway_bus *bus,
+ struct superhyway_device **devices,
+ int nr_devices)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < nr_devices; i++) {
+ struct superhyway_device *dev = devices[i];
+ ret |= superhyway_add_device(dev->resource[0].start, dev, bus);
+ }
+
+ return ret;
+}
+
static int __init superhyway_init(void)
{
+ struct superhyway_bus *bus;
+ int ret = 0;
+
device_register(&superhyway_bus_device);
- return superhyway_scan_bus();
+
+ for (bus = superhyway_channels; bus->ops; bus++)
+ ret |= superhyway_scan_bus(bus);
+
+ return ret;
}
postcore_initcall(superhyway_init);
@@ -197,6 +231,7 @@ module_exit(superhyway_bus_exit);
EXPORT_SYMBOL(superhyway_bus_type);
EXPORT_SYMBOL(superhyway_add_device);
+EXPORT_SYMBOL(superhyway_add_devices);
EXPORT_SYMBOL(superhyway_register_driver);
EXPORT_SYMBOL(superhyway_unregister_driver);
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 6a3cfbdc6dc9..3b0ddc55236b 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -113,7 +113,6 @@ static struct fb_ops mc68x328fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_mmap = mc68x328fb_mmap,
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 7192b770bfb6..44b6ca290ce3 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -65,15 +65,6 @@ config FB_CFB_IMAGEBLIT
blitting. This is used by drivers that don't provide their own
(accelerated) version.
-config FB_SOFT_CURSOR
- tristate
- depends on FB
- default n
- ---help---
- Include the soft_cursor function for generic software cursor support.
- This is used by drivers that don't provide their own (accelerated)
- version.
-
config FB_MACMODES
tristate
depends on FB
@@ -114,7 +105,6 @@ config FB_CIRRUS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
This enables support for Cirrus Logic GD542x/543x based boards on
Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
@@ -133,7 +123,6 @@ config FB_PM2
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Permedia2 AGP frame
buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a
@@ -152,7 +141,6 @@ config FB_ARMCLCD
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This framebuffer device driver is for the ARM PrimeCell PL110
Colour LCD controller. ARM PrimeCells provide the building
@@ -169,7 +157,6 @@ config FB_ACORN
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Acorn VIDC graphics
hardware found in Acorn RISC PCs and other ARM-based machines. If
@@ -181,7 +168,9 @@ config FB_CLPS711X
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
+ help
+ Say Y to enable the Framebuffer driver for the CLPS7111 and
+ EP7212 processors.
config FB_SA1100
bool "SA-1100 LCD support"
@@ -189,7 +178,6 @@ config FB_SA1100
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is a framebuffer device for the SA-1100 LCD Controller.
See <http://www.linux-fbdev.org/> for information on framebuffer
@@ -204,7 +192,6 @@ config FB_IMX
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
config FB_CYBER2000
tristate "CyberPro 2000/2010/5000 support"
@@ -212,7 +199,6 @@ config FB_CYBER2000
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This enables support for the Integraphics CyberPro 20x0 and 5000
VGA chips used in the Rebel.com Netwinder and other machines.
@@ -225,7 +211,6 @@ config FB_APOLLO
default y
select FB_CFB_FILLRECT
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
config FB_Q40
bool
@@ -234,12 +219,10 @@ config FB_Q40
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
config FB_AMIGA
tristate "Amiga native chipset support"
depends on FB && AMIGA
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the builtin graphics
chipset found in Amigas.
@@ -279,7 +262,6 @@ config FB_CYBER
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This enables support for the Cybervision 64 graphics card from
Phase5. Please note that its use is not all that intuitive (i.e. if
@@ -294,7 +276,6 @@ config FB_VIRGE
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This enables support for the Cybervision 64/3D graphics card from
Phase5. Please note that its use is not all that intuitive (i.e. if
@@ -317,7 +298,6 @@ config FB_FM2
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Amiga FrameMaster
card from BSC (exhibited 1992 but not shipped as a CBM product).
@@ -328,7 +308,6 @@ config FB_ARC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This enables support for the Arc Monochrome LCD board. The board
is based on the KS-108 lcd controller and is typically a matrix
@@ -351,7 +330,6 @@ config FB_OF
select FB_CFB_FILLRECT
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
@@ -363,7 +341,6 @@ config FB_CONTROL
select FB_CFB_FILLRECT
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
@@ -375,7 +352,6 @@ config FB_PLATINUM
select FB_CFB_FILLRECT
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
@@ -387,7 +363,6 @@ config FB_VALKYRIE
select FB_CFB_FILLRECT
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
@@ -399,42 +374,32 @@ config FB_CT65550
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Chips & Technologies
65550 graphics chip in PowerBooks.
config FB_ASILIANT
- bool "Chips 69000 display support"
+ bool "Asiliant (Chips) 69000 display support"
depends on (FB = y) && PCI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
config FB_IMSTT
bool "IMS Twin Turbo display support"
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.
-config FB_S3TRIO
- bool "S3 Trio display support"
- depends on (FB = y) && PPC && BROKEN
- help
- If you have a S3 Trio say Y. Say N for S3 Virge.
-
config FB_VGA16
tristate "VGA 16-color graphics support"
depends on FB && (X86 || PPC)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for VGA 16 color graphic
cards. Say Y if you have such a card.
@@ -448,7 +413,6 @@ config FB_STI
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
default y
---help---
STI refers to the HP "Standard Text Interface" which is a set of
@@ -469,7 +433,6 @@ config FB_MAC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
select FB_MACMODES
# bool ' Apple DAFB display support' CONFIG_FB_DAFB
@@ -478,7 +441,6 @@ config FB_HP300
depends on (FB = y) && HP300
select FB_CFB_FILLRECT
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
default y
config FB_TGA
@@ -487,7 +449,6 @@ config FB_TGA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for generic TGA graphic
cards. Say Y if you have one of those.
@@ -498,7 +459,6 @@ config FB_VESA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for generic VESA 2.0
compliant graphic cards. The older VESA 1.2 cards are not supported.
@@ -516,7 +476,6 @@ config FB_HGA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Say Y here if you have a Hercules mono graphics card.
@@ -545,7 +504,6 @@ config FB_SGIVW
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
SGI Visual Workstation support for framebuffer graphics.
@@ -555,7 +513,6 @@ config FB_GBE
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for SGI Graphics Backend.
This chip is used in SGI O2 and Visual Workstation 320/540.
@@ -583,7 +540,6 @@ config FB_BW2
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the BWtwo frame buffer.
@@ -592,7 +548,6 @@ config FB_CG3
depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the CGthree frame buffer.
@@ -601,7 +556,6 @@ config FB_CG6
depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the CGsix (GX, TurboGX)
frame buffer.
@@ -612,7 +566,6 @@ config FB_PVR2
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
Say Y here if you have a PowerVR 2 card in your box. If you plan to
run linux on your Dreamcast, you will have to say Y here.
@@ -634,13 +587,55 @@ config FB_EPSON1355
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Build in support for the SED1355 Epson Research Embedded RAMDAC
LCD/CRT Controller (since redesignated as the S1D13505) as a
framebuffer. Product specs at
<http://www.erd.epson.com/vdc/html/products.htm>.
+config FB_E1356
+ tristate "Epson SED1356 framebuffer support"
+ depends on FB && EXPERIMENTAL && PCI && MIPS
+
+config PB1000_CRT
+ bool "Use CRT on Pb1000 (J65)"
+ depends on MIPS_PB1000=y && FB_E1356
+
+config PB1000_NTSC
+ bool "Use Compsite NTSC on Pb1000 (J63)"
+ depends on MIPS_PB1000=y && FB_E1356
+
+config PB1000_TFT
+ bool "Use TFT Panel on Pb1000 (J64)"
+ depends on MIPS_PB1000=y && FB_E1356
+
+config PB1500_CRT
+ bool "Use CRT on Pb1500 " if MIPS_PB1500=y
+ depends on FB_E1356
+
+config PB1500_CRT
+ prompt "Use CRT on Pb1100 "
+ depends on FB_E1356 && MIPS_PB1100=y
+
+config PB1500_TFT
+ bool "Use TFT Panel on Pb1500 " if MIPS_PB1500=y
+ depends on FB_E1356
+
+config PB1500_TFT
+ prompt "Use TFT Panel on Pb1100 "
+ depends on FB_E1356 && MIPS_PB1100=y
+
+config FB_S1D13XXX
+ tristate "Epson S1D13XXX framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ 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_NVIDIA
tristate "nVidia Framebuffer Support"
depends on FB && PCI
@@ -650,7 +645,6 @@ config FB_NVIDIA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports graphics boards with the nVidia chips, TNT
and newer. For very old chipsets, such as the RIVA128, then use
@@ -662,7 +656,7 @@ config FB_NVIDIA
config FB_NVIDIA_I2C
bool "Enable DDC Support"
- depends on FB_NVIDIA && !PPC_OF
+ depends on FB_NVIDIA
help
This enables I2C support for nVidia Chipsets. This is used
only for getting EDID information from the attached display
@@ -768,7 +762,6 @@ config FB_INTEL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports the on-board graphics built in to the Intel
830M/845G/852GM/855GM/865G chipsets.
@@ -791,7 +784,6 @@ config FB_MATROX
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
select FB_TILEBLITTING
select FB_MACMODES if PPC_PMAC
---help---
@@ -932,7 +924,6 @@ config FB_RADEON_OLD
select FB_CFB_FILLRECT
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
@@ -950,7 +941,6 @@ config FB_RADEON
select FB_CFB_FILLRECT
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
@@ -988,7 +978,6 @@ config FB_ATY128
select FB_CFB_FILLRECT
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.
@@ -1004,7 +993,6 @@ config FB_ATY
select FB_CFB_FILLRECT
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.
@@ -1047,6 +1035,12 @@ config FB_ATY_GX
is at
<http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
+config FB_S3TRIO
+ bool "S3 Trio display support"
+ depends on (FB = y) && PPC && BROKEN
+ help
+ If you have a S3 Trio say Y. Say N for S3 Virge.
+
config FB_SAVAGE
tristate "S3 Savage support"
depends on FB && PCI && EXPERIMENTAL
@@ -1056,7 +1050,6 @@ config FB_SAVAGE
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports notebooks and computers with S3 Savage PCI/AGP
chips.
@@ -1093,7 +1086,6 @@ config FB_SIS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the SiS 300, 315, 330
and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets.
@@ -1123,7 +1115,6 @@ config FB_NEOMAGIC
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This driver supports notebooks with NeoMagic PCI chips.
Say Y if you have such a graphics card.
@@ -1137,7 +1128,6 @@ config FB_KYRO
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
graphics board.
@@ -1151,7 +1141,6 @@ config FB_3DFX
select FB_CFB_IMAGEBLIT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
- select FB_SOFT_CURSOR
help
This driver supports graphics boards with the 3Dfx Banshee/Voodoo3
chips. Say Y if you have such a graphics board.
@@ -1173,7 +1162,6 @@ config FB_VOODOO1
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or
Voodoo2 (cvg) based graphics card.
@@ -1190,7 +1178,6 @@ config FB_CYBLA
tristate "Cyberblade/i1 support"
depends on FB && PCI
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
select VIDEO_SELECT
---help---
This driver is supposed to support the Trident Cyberblade/i1
@@ -1218,7 +1205,6 @@ config FB_TRIDENT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
This driver is supposed to support graphics boards with the
Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops
@@ -1250,38 +1236,6 @@ config FB_PM3
similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000
and maybe other boards.
-config FB_E1356
- tristate "Epson SED1356 framebuffer support"
- depends on FB && EXPERIMENTAL && PCI && MIPS
-
-config PB1000_CRT
- bool "Use CRT on Pb1000 (J65)"
- depends on MIPS_PB1000=y && FB_E1356
-
-config PB1000_NTSC
- bool "Use Compsite NTSC on Pb1000 (J63)"
- depends on MIPS_PB1000=y && FB_E1356
-
-config PB1000_TFT
- bool "Use TFT Panel on Pb1000 (J64)"
- depends on MIPS_PB1000=y && FB_E1356
-
-config PB1500_CRT
- bool "Use CRT on Pb1500 " if MIPS_PB1500=y
- depends on FB_E1356
-
-config PB1500_CRT
- prompt "Use CRT on Pb1100 "
- depends on FB_E1356 && MIPS_PB1100=y
-
-config PB1500_TFT
- bool "Use TFT Panel on Pb1500 " if MIPS_PB1500=y
- depends on FB_E1356
-
-config PB1500_TFT
- prompt "Use TFT Panel on Pb1100 "
- depends on FB_E1356 && MIPS_PB1100=y
-
config FB_AU1100
bool "Au1100 LCD Driver"
depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
@@ -1299,7 +1253,6 @@ config FB_FFB
depends on FB_SBUS && SPARC64
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Creator, Creator3D,
and Elite3D graphics boards.
@@ -1310,7 +1263,6 @@ config FB_TCX
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the TCX 24/8bit frame
buffer.
@@ -1321,7 +1273,6 @@ config FB_CG14
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the CGfourteen frame
buffer on Desktop SPARCsystems with the SX graphics option.
@@ -1332,7 +1283,6 @@ config FB_P9100
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the P9100 card
supported on Sparcbook 3 machines.
@@ -1343,7 +1293,6 @@ config FB_LEO
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the SBUS-based Sun ZX
(leo) frame buffer cards.
@@ -1358,7 +1307,6 @@ config FB_IGA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the framebuffer device for the INTERGRAPHICS 1680 and
successor frame buffer cards.
@@ -1369,7 +1317,6 @@ config FB_HIT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
This is the frame buffer device driver for the Hitachi HD64461 LCD
frame buffer card.
@@ -1380,7 +1327,6 @@ config FB_PMAG_AA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1)
used mainly in the MIPS-based DECstation series.
@@ -1391,7 +1337,6 @@ config FB_PMAG_BA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8)
used mainly in the MIPS-based DECstation series.
@@ -1402,7 +1347,6 @@ config FB_PMAGB_B
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Support for the PMAGB-B TURBOchannel framebuffer card used mainly
in the MIPS-based DECstation series. The card is currently only
@@ -1414,7 +1358,6 @@ config FB_MAXINE
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Support for the onboard framebuffer (1024x768x8) in the Personal
DECstation series (Personal DECstation 5000/20, /25, /33, /50,
@@ -1426,7 +1369,6 @@ config FB_TX3912
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core
see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>.
@@ -1439,7 +1381,6 @@ config FB_G364
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
The G364 driver is the framebuffer used in MIPS Magnum 4000 and
Olivetti M700-10 systems.
@@ -1450,7 +1391,6 @@ config FB_68328
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
help
Say Y here if you want to support the built-in frame buffer of
the Motorola 68328 CPU family.
@@ -1461,7 +1401,6 @@ config FB_PXA
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
Frame buffer driver for the built-in LCD controller in the Intel
PXA2x0 processor.
@@ -1473,23 +1412,6 @@ config FB_PXA
If unsure, say N.
-config FB_W100
- tristate "W100 frame buffer support"
- depends on FB && PXA_SHARPSL
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
- ---help---
- Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
-
- This driver is also available as a module ( = code which can be
- inserted and removed from the running kernel whenever you want). The
- module will be called vfb. If you want to compile it as a module,
- say M here and read <file:Documentation/modules.txt>.
-
- If unsure, say N.
-
config FB_PXA_PARAMETERS
bool "PXA LCD command line parameters"
default n
@@ -1507,17 +1429,21 @@ 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_W100
+ tristate "W100 frame buffer support"
+ depends on FB && PXA_SHARPSL
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ ---help---
+ Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
+
+ This driver is also available as a module ( = code which can be
+ inserted and removed from the running kernel whenever you want). The
+ module will be called vfb. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ If unsure, say N.
config FB_S3C2410
tristate "S3C2410 LCD framebuffer support"
@@ -1525,7 +1451,6 @@ config FB_S3C2410
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
Frame buffer driver for the built-in LCD controller in the Samsung
S3C2410 processor.
@@ -1549,7 +1474,6 @@ config FB_VIRTUAL
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
This is a `virtual' frame buffer device. It operates on a chunk of
unswappable kernel memory instead of on the memory of a graphics
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 97c5d03ac8d9..aa434e725c0d 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -16,7 +16,6 @@ fb-objs := $(fb-y)
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
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 9b6a39348f81..193b482570c7 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -926,7 +926,6 @@ static struct fb_ops acornfb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = acornfb_mmap,
- .fb_cursor = soft_cursor,
};
/*
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 4fc93dc2b4d3..467a1d7ebbde 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -333,7 +333,6 @@ static struct fb_ops clcdfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_mmap = clcdfb_mmap,
};
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index cf8bb67462dc..d549e215f3c5 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1185,7 +1185,6 @@ static struct fb_ops amifb_ops = {
.fb_fillrect = amifb_fillrect,
.fb_copyarea = amifb_copyarea,
.fb_imageblit = amifb_imageblit,
- .fb_cursor = soft_cursor,
.fb_ioctl = amifb_ioctl,
};
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index 6aa9f824c185..a1fc8bbb1090 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -511,7 +511,6 @@ static struct fb_ops arcfb_ops = {
.fb_fillrect = arcfb_fillrect,
.fb_copyarea = arcfb_copyarea,
.fb_imageblit = arcfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_ioctl = arcfb_ioctl,
};
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index f4729f4df8ce..c64de59398f4 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -106,7 +106,6 @@ static struct fb_ops asiliantfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
/* Calculate the ratios for the dot clocks without using a single long long
diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/aty/ati_ids.h
index 13321c689cf6..39ab483fc250 100644
--- a/drivers/video/aty/ati_ids.h
+++ b/drivers/video/aty/ati_ids.h
@@ -150,6 +150,7 @@
#define PCI_CHIP_RV200_QX 0x5158
#define PCI_CHIP_RV100_QY 0x5159
#define PCI_CHIP_RV100_QZ 0x515A
+#define PCI_CHIP_RN50 0x515E
#define PCI_CHIP_RAGE128RE 0x5245
#define PCI_CHIP_RAGE128RF 0x5246
#define PCI_CHIP_RAGE128RG 0x5247
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index e380ee8b0247..e686185a076d 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -478,7 +478,6 @@ static struct fb_ops aty128fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
#ifdef CONFIG_PMAC_BACKLIGHT
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 037fe9d32fe3..08edbfcfca58 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -292,7 +292,6 @@ static struct fb_ops atyfb_ops = {
.fb_fillrect = atyfb_fillrect,
.fb_copyarea = atyfb_copyarea,
.fb_imageblit = atyfb_imageblit,
- .fb_cursor = soft_cursor,
#ifdef __sparc__
.fb_mmap = atyfb_mmap,
#endif
@@ -2157,11 +2156,38 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
static struct fb_info *fb_list = NULL;
+#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
+static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,
+ struct fb_var_screeninfo *var)
+{
+ int ret = -EINVAL;
+
+ if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
+ *var = default_var;
+ var->xres = var->xres_virtual = par->lcd_hdisp;
+ var->right_margin = par->lcd_right_margin;
+ var->left_margin = par->lcd_hblank_len -
+ (par->lcd_right_margin + par->lcd_hsync_dly +
+ par->lcd_hsync_len);
+ var->hsync_len = par->lcd_hsync_len + par->lcd_hsync_dly;
+ var->yres = var->yres_virtual = par->lcd_vdisp;
+ var->lower_margin = par->lcd_lower_margin;
+ var->upper_margin = par->lcd_vblank_len -
+ (par->lcd_lower_margin + par->lcd_vsync_len);
+ var->vsync_len = par->lcd_vsync_len;
+ var->pixclock = par->lcd_pixclock;
+ ret = 0;
+ }
+
+ return ret;
+}
+#endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
+
static int __init aty_init(struct fb_info *info, const char *name)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
const char *ramname = NULL, *xtal;
- int gtb_memsize;
+ int gtb_memsize, has_var = 0;
struct fb_var_screeninfo var;
u8 pll_ref_div;
u32 i;
@@ -2469,8 +2495,8 @@ static int __init aty_init(struct fb_info *info, const char *name)
* applies to all Mac video cards
*/
if (mode) {
- if (!mac_find_mode(&var, info, mode, 8))
- var = default_var;
+ if (mac_find_mode(&var, info, mode, 8))
+ has_var = 1;
} else {
if (default_vmode == VMODE_CHOOSE) {
if (M64_HAS(G3_PB_1024x768))
@@ -2492,20 +2518,23 @@ static int __init aty_init(struct fb_info *info, const char *name)
default_vmode = VMODE_640_480_60;
if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
default_cmode = CMODE_8;
- if (mac_vmode_to_var(default_vmode, default_cmode, &var))
- var = default_var;
+ if (!mac_vmode_to_var(default_vmode, default_cmode,
+ &var))
+ has_var = 1;
}
- } else
+ }
+
#endif /* !CONFIG_PPC */
- if (
-#if defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64)
- /* On Sparc, unless the user gave a specific mode
- * specification, use the PROM probed values in
- * default_var.
- */
- !mode ||
+
+#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
+ if (!atyfb_get_timings_from_lcd(par, &var))
+ has_var = 1;
#endif
- !fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
+
+ if (mode && fb_find_mode(&var, info, mode, NULL, 0, &defmode, 8))
+ has_var = 1;
+
+ if (!has_var)
var = default_var;
if (noaccel)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 8a24a66d9ba8..4f01ccc02aa4 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -69,7 +69,6 @@
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/device.h>
-#include <linux/i2c.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -113,6 +112,7 @@ static struct pci_device_id radeonfb_pci_table[] = {
/* Radeon VE/7000 */
CHIP_DEF(PCI_CHIP_RV100_QY, RV100, CHIP_HAS_CRTC2),
CHIP_DEF(PCI_CHIP_RV100_QZ, RV100, CHIP_HAS_CRTC2),
+ CHIP_DEF(PCI_CHIP_RN50, RV100, CHIP_HAS_CRTC2),
/* Radeon IGP320M (U1) */
CHIP_DEF(PCI_CHIP_RS100_4336, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
/* Radeon IGP320 (A3) */
@@ -1874,7 +1874,6 @@ static struct fb_ops radeonfb_ops = {
.fb_fillrect = radeonfb_fillrect,
.fb_copyarea = radeonfb_copyarea,
.fb_imageblit = radeonfb_imageblit,
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 01b8b2f78514..217e00ab4a2d 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -10,9 +10,10 @@
#include <linux/fb.h>
+#ifdef CONFIG_FB_RADEON_I2C
#include <linux/i2c.h>
-#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h>
+#endif
#include <asm/io.h>
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 3d20b2d47d46..f53bf3ba1278 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -51,7 +51,6 @@ static struct fb_ops bw2_ops = {
.fb_imageblit = cfb_imageblit,
.fb_mmap = bw2_mmap,
.fb_ioctl = bw2_ioctl,
- .fb_cursor = soft_cursor,
};
/* OBio addresses for the bwtwo registers */
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index 67711f7b11b1..cdc71572cf35 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -349,46 +349,10 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
unsigned long __iomem *dst = NULL, *src = NULL;
int bits = BITS_PER_LONG, bytes = bits >> 3;
int dst_idx = 0, src_idx = 0, rev_copy = 0;
- int x2, y2, vxres, vyres;
if (p->state != FBINFO_STATE_RUNNING)
return;
- /* We want rotation but lack hardware to do it for us. */
- if (!p->fbops->fb_rotate && p->var.rotate) {
- }
-
- vxres = p->var.xres_virtual;
- vyres = p->var.yres_virtual;
-
- if (area->dx > vxres || area->sx > vxres ||
- area->dy > vyres || area->sy > vyres)
- return;
-
- /* clip the destination
- * We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly.
- */
- x2 = area->dx + area->width;
- y2 = area->dy + area->height;
- dx = area->dx > 0 ? area->dx : 0;
- dy = area->dy > 0 ? area->dy : 0;
- x2 = x2 < vxres ? x2 : vxres;
- y2 = y2 < vyres ? y2 : vyres;
- width = x2 - dx;
- height = y2 - dy;
-
- if ((width==0) ||(height==0))
- return;
-
- /* update sx1,sy1 */
- sx += (dx - area->dx);
- sy += (dy - area->dy);
-
- /* the source must be completely inside the virtual screen */
- if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
- return;
-
/* if the beginning of the target area might overlap with the end of
the source area, be have to copy the area reverse. */
if ((dy == sy && dx > sx) || (dy > sy)) {
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
index e4fc42b013eb..167d9314e6eb 100644
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/cfbfillrect.c
@@ -344,7 +344,8 @@ bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat
void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
- unsigned long x2, y2, vxres, vyres, height, width, pat, fg;
+ unsigned long pat, fg;
+ unsigned long width = rect->width, height = rect->height;
int bits = BITS_PER_LONG, bytes = bits >> 3;
u32 bpp = p->var.bits_per_pixel;
unsigned long __iomem *dst;
@@ -353,27 +354,6 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
if (p->state != FBINFO_STATE_RUNNING)
return;
- /* We want rotation but lack hardware to do it for us. */
- if (!p->fbops->fb_rotate && p->var.rotate) {
- }
-
- vxres = p->var.xres_virtual;
- vyres = p->var.yres_virtual;
-
- if (!rect->width || !rect->height ||
- rect->dx > vxres || rect->dy > vyres)
- return;
-
- /* We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly. */
-
- x2 = rect->dx + rect->width;
- y2 = rect->dy + rect->height;
- x2 = x2 < vxres ? x2 : vxres;
- y2 = y2 < vyres ? y2 : vyres;
- width = x2 - rect->dx;
- height = y2 - rect->dy;
-
if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
p->fix.visual == FB_VISUAL_DIRECTCOLOR )
fg = ((u32 *) (p->pseudo_palette))[rect->color];
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 4c123abaa843..da664cea7eca 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -272,33 +272,13 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
{
u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
- u32 width = image->width, height = image->height;
+ u32 width = image->width;
u32 dx = image->dx, dy = image->dy;
- int x2, y2, vxres, vyres;
u8 __iomem *dst1;
if (p->state != FBINFO_STATE_RUNNING)
return;
- vxres = p->var.xres_virtual;
- vyres = p->var.yres_virtual;
- /*
- * We could use hardware clipping but on many cards you get around
- * hardware clipping by writing to framebuffer directly like we are
- * doing here.
- */
- if (image->dx > vxres || image->dy > vyres)
- return;
-
- x2 = image->dx + image->width;
- y2 = image->dy + image->height;
- dx = image->dx > 0 ? image->dx : 0;
- dy = image->dy > 0 ? image->dy : 0;
- x2 = x2 < vxres ? x2 : vxres;
- y2 = y2 < vyres ? y2 : vyres;
- width = x2 - dx;
- height = y2 - dy;
-
bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
start_index = bitstart & (32 - 1);
pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index 18e60b941e21..030d4b13b1c2 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -49,7 +49,6 @@ static struct fb_ops cg14_ops = {
.fb_imageblit = cfb_imageblit,
.fb_mmap = cg14_mmap,
.fb_ioctl = cg14_ioctl,
- .fb_cursor = soft_cursor,
};
#define CG14_MCR_INTENABLE_SHIFT 7
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 6e7d8d45dc68..b94eee8c42d5 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -50,7 +50,6 @@ static struct fb_ops cg3_ops = {
.fb_imageblit = cfb_imageblit,
.fb_mmap = cg3_mmap,
.fb_ioctl = cg3_ioctl,
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 49a2545671d9..3280bb9560e2 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -54,7 +54,6 @@ static struct fb_ops cg6_ops = {
.fb_sync = cg6_sync,
.fb_mmap = cg6_mmap,
.fb_ioctl = cg6_ioctl,
- .fb_cursor = soft_cursor,
};
/* Offset of interesting structures in the OBIO space */
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 4131243cfdf8..bc061d4ec786 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -91,7 +91,6 @@ static struct fb_ops chipsfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static int chipsfb_check_var(struct fb_var_screeninfo *var,
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 3a26f9cc8585..2858c5c8ba3c 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -548,7 +548,6 @@ static struct fb_ops cirrusfb_ops = {
.fb_fillrect = cirrusfb_fillrect,
.fb_copyarea = cirrusfb_copyarea,
.fb_imageblit = cirrusfb_imageblit,
- .fb_cursor = soft_cursor,
};
/*--- Hardware Specific Routines -------------------------------------------*/
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index 8692e002986b..50b78af0fa24 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -219,7 +219,6 @@ static struct fb_ops clps7111fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static int
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 6a9ae2b3d1ab..fadf7c5d216e 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -98,6 +98,8 @@ config FRAMEBUFFER_CONSOLE
tristate "Framebuffer Console support"
depends on FB
select CRC32
+ help
+ Low-level framebuffer-based console driver.
config STI_CONSOLE
tristate "STI text console"
@@ -203,5 +205,12 @@ config FONT_10x18
big letters. It fits between the sun 12x22 and the normal 8x16 font.
If other fonts are too big or too small for you, say Y, otherwise say N.
+config FONT_RL
+ bool "console Roman Large 8x16 font" if FONTS
+ depends on FRAMEBUFFER_CONSOLE
+ help
+ This is the visually-appealing "RL" console font that is
+ included with the kbd package.
+
endmenu
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index 42c7b8dcd220..5222628accce 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -15,6 +15,7 @@ font-objs-$(CONFIG_FONT_10x18) += font_10x18.o
font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
+font-objs-$(CONFIG_FONT_RL) += font_rl.o
font-objs += $(font-objs-y)
@@ -26,7 +27,7 @@ obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o
obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
-obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o
+obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o
ifeq ($(CONFIG_FB_TILEBLITTING),y)
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o
endif
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 9f70e512b88b..67857b3cfc8b 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -272,6 +272,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
int w = (vc->vc_font.width + 7) >> 3, c;
int y = real_y(p, vc->vc_y);
int attribute, use_sw = (vc->vc_cursor_type & 0x10);
+ int err = 1;
char *src;
cursor.set = 0;
@@ -408,7 +409,11 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info,
cursor.image.depth = 1;
cursor.rop = ROP_XOR;
- info->fbops->fb_cursor(info, &cursor);
+ if (info->fbops->fb_cursor)
+ err = info->fbops->fb_cursor(info, &cursor);
+
+ if (err)
+ soft_cursor(info, &cursor);
ops->cursor_reset = 0;
}
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 0fc8bb499c3f..3cf1b61ff1f8 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -281,6 +281,18 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info,
return color;
}
+static void fbcon_update_softback(struct vc_data *vc)
+{
+ int l = fbcon_softback_size / vc->vc_size_row;
+
+ if (l > 5)
+ softback_end = softback_buf + l * vc->vc_size_row;
+ else
+ /* Smaller scrollback makes no sense, and 0 would screw
+ the operation totally */
+ softback_top = 0;
+}
+
static void fb_flashcursor(void *private)
{
struct fb_info *info = private;
@@ -618,6 +630,15 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
kfree(oldinfo->fbcon_par);
oldinfo->fbcon_par = NULL;
module_put(oldinfo->fbops->owner);
+ /*
+ If oldinfo and newinfo are driving the same hardware,
+ the fb_release() method of oldinfo may attempt to
+ restore the hardware state. This will leave the
+ newinfo in an undefined state. Thus, a call to
+ fb_set_par() may be needed for the newinfo.
+ */
+ if (newinfo->fbops->fb_set_par)
+ newinfo->fbops->fb_set_par(newinfo);
}
return err;
@@ -1007,16 +1028,8 @@ static void fbcon_init(struct vc_data *vc, int init)
if (logo)
fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
- if (vc == svc && softback_buf) {
- int l = fbcon_softback_size / vc->vc_size_row;
- if (l > 5)
- softback_end = softback_buf + l * vc->vc_size_row;
- else {
- /* Smaller scrollback makes no sense, and 0 would screw
- the operation totally */
- softback_top = 0;
- }
- }
+ if (vc == svc && softback_buf)
+ fbcon_update_softback(vc);
}
static void fbcon_deinit(struct vc_data *vc)
@@ -1223,18 +1236,8 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
vc_resize(vc, cols, rows);
if (CON_IS_VISIBLE(vc)) {
update_screen(vc);
- if (softback_buf) {
- int l = fbcon_softback_size / vc->vc_size_row;
-
- if (l > 5)
- softback_end = softback_buf + l *
- vc->vc_size_row;
- else {
- /* Smaller scrollback makes no sense, and 0
- would screw the operation totally */
- softback_top = 0;
- }
- }
+ if (softback_buf)
+ fbcon_update_softback(vc);
}
}
@@ -1892,24 +1895,11 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
mode = fb_find_best_mode(&var, &info->modelist);
if (mode == NULL)
return -EINVAL;
+ display_to_var(&var, p);
fb_videomode_to_var(&var, mode);
+
if (width > var.xres/fw || height > var.yres/fh)
return -EINVAL;
- /*
- * The following can probably have any value... Do we need to
- * set all of them?
- */
- var.bits_per_pixel = p->bits_per_pixel;
- var.xres_virtual = p->xres_virtual;
- var.yres_virtual = p->yres_virtual;
- var.accel_flags = p->accel_flags;
- var.width = p->width;
- var.height = p->height;
- var.red = p->red;
- var.green = p->green;
- var.blue = p->blue;
- var.transp = p->transp;
- var.nonstd = p->nonstd;
DPRINTK("resize now %ix%i\n", var.xres, var.yres);
if (CON_IS_VISIBLE(vc)) {
@@ -1933,19 +1923,11 @@ static int fbcon_switch(struct vc_data *vc)
info = registered_fb[con2fb_map[vc->vc_num]];
if (softback_top) {
- int l = fbcon_softback_size / vc->vc_size_row;
if (softback_lines)
fbcon_set_origin(vc);
softback_top = softback_curr = softback_in = softback_buf;
softback_lines = 0;
-
- if (l > 5)
- softback_end = softback_buf + l * vc->vc_size_row;
- else {
- /* Smaller scrollback makes no sense, and 0 would screw
- the operation totally */
- softback_top = 0;
- }
+ fbcon_update_softback(vc);
}
if (logo_shown >= 0) {
@@ -2235,17 +2217,8 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
/* reset wrap/pan */
info->var.xoffset = info->var.yoffset = p->yscroll = 0;
vc_resize(vc, info->var.xres / w, info->var.yres / h);
- if (CON_IS_VISIBLE(vc) && softback_buf) {
- int l = fbcon_softback_size / vc->vc_size_row;
- if (l > 5)
- softback_end =
- softback_buf + l * vc->vc_size_row;
- else {
- /* Smaller scrollback makes no sense, and 0 would screw
- the operation totally */
- softback_top = 0;
- }
- }
+ if (CON_IS_VISIBLE(vc) && softback_buf)
+ fbcon_update_softback(vc);
} else if (CON_IS_VISIBLE(vc)
&& vc->vc_mode == KD_TEXT) {
fbcon_clear_margins(vc, 0);
@@ -2615,16 +2588,8 @@ static void fbcon_modechanged(struct fb_info *info)
update_var(vc->vc_num, info);
fbcon_set_palette(vc, color_table);
update_screen(vc);
- if (softback_buf) {
- int l = fbcon_softback_size / vc->vc_size_row;
- if (l > 5)
- softback_end = softback_buf + l * vc->vc_size_row;
- else {
- /* Smaller scrollback makes no sense, and 0
- would screw the operation totally */
- softback_top = 0;
- }
- }
+ if (softback_buf)
+ fbcon_update_softback(vc);
}
}
@@ -2659,16 +2624,8 @@ static void fbcon_set_all_vcs(struct fb_info *info)
update_var(vc->vc_num, info);
fbcon_set_palette(vc, color_table);
update_screen(vc);
- if (softback_buf) {
- int l = fbcon_softback_size / vc->vc_size_row;
- if (l > 5)
- softback_end = softback_buf + l * vc->vc_size_row;
- else {
- /* Smaller scrollback makes no sense, and 0
- would screw the operation totally */
- softback_top = 0;
- }
- }
+ if (softback_buf)
+ fbcon_update_softback(vc);
}
}
}
@@ -2758,7 +2715,8 @@ static void fbcon_new_modelist(struct fb_info *info)
continue;
vc = vc_cons[i].d;
display_to_var(&var, &fb_display[i]);
- mode = fb_find_nearest_mode(&var, &info->modelist);
+ mode = fb_find_nearest_mode(fb_display[i].mode,
+ &info->modelist);
fb_videomode_to_var(&var, mode);
if (vc)
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 0738cd62def2..b68e0e2c2d16 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -167,5 +167,5 @@ 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 int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
#endif /* _VIDEO_FBCON_H */
diff --git a/drivers/video/console/font_rl.c b/drivers/video/console/font_rl.c
new file mode 100644
index 000000000000..dfecc27d8ded
--- /dev/null
+++ b/drivers/video/console/font_rl.c
@@ -0,0 +1,4374 @@
+
+/* This font is simply the "rl.fnt" console font from the kbd utility.
+ * Converted by Zack T Smith, fbui@comcast.net.
+ * The original binary file is covered under the GNU Public License.
+ */
+
+#include <linux/font.h>
+
+#define FONTDATAMAX 4096
+
+static unsigned char patterns[4096] = {
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x3c,
+0x42,
+0x81,
+0xe7,
+0xa5,
+0x99,
+0x81,
+0x81,
+0x99,
+0x42,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x3c,
+0x7e,
+0xff,
+0x99,
+0xdb,
+0xe7,
+0xff,
+0xff,
+0xe7,
+0x7e,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x6c,
+0xfe,
+0xfe,
+0xfe,
+0xfe,
+0xfe,
+0x7c,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x7c,
+0xfe,
+0x7c,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x38,
+0x38,
+0x10,
+0xd6,
+0xfe,
+0xd6,
+0x10,
+0x10,
+0x38,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x10,
+0x38,
+0x7c,
+0xfe,
+0xfe,
+0x54,
+0x10,
+0x10,
+0x38,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x18,
+0x3c,
+0x3c,
+0x18,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xe7,
+0xc3,
+0xc3,
+0xe7,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x3c,
+0x66,
+0x42,
+0x42,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xc3,
+0x99,
+0xbd,
+0xbd,
+0x99,
+0xc3,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+
+0x00,
+0x00,
+0x0f,
+0x07,
+0x0d,
+0x18,
+0x78,
+0xcc,
+0xcc,
+0xcc,
+0xcc,
+0x78,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x3c,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x18,
+0x7e,
+0x18,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x08,
+0x0c,
+0x0a,
+0x0a,
+0x0a,
+0x08,
+0x08,
+0x08,
+0x38,
+0x78,
+0x30,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x10,
+0x18,
+0x1c,
+0x1e,
+0x1e,
+0x16,
+0x12,
+0x72,
+0xf2,
+0x62,
+0x0e,
+0x1e,
+0x0c,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x10,
+0x92,
+0x54,
+0x38,
+0xfe,
+0x38,
+0x54,
+0x92,
+0x10,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x80,
+0xc0,
+0xe0,
+0xb8,
+0x8e,
+0xb8,
+0xe0,
+0xc0,
+0x80,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x02,
+0x06,
+0x0e,
+0x3a,
+0xe2,
+0x3a,
+0x0e,
+0x06,
+0x02,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x10,
+0x38,
+0x7c,
+0xd6,
+0x10,
+0x10,
+0x10,
+0x10,
+0xd6,
+0x7c,
+0x38,
+0x10,
+0x00,
+0x00,
+
+0x00,
+0x42,
+0xe7,
+0xe7,
+0xe7,
+0xe7,
+0x42,
+0x42,
+0x42,
+0x00,
+0x66,
+0x66,
+0x66,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x7f,
+0xca,
+0xca,
+0xca,
+0xca,
+0x7a,
+0x0a,
+0x0a,
+0x0a,
+0x0a,
+0x0a,
+0x1b,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x1e,
+0x31,
+0x78,
+0xcc,
+0xc6,
+0xc3,
+0x63,
+0x33,
+0x1e,
+0x8c,
+0x78,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xfe,
+0xfe,
+0xfe,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x10,
+0x38,
+0x7c,
+0xd6,
+0x10,
+0x10,
+0x10,
+0x10,
+0xd6,
+0x7c,
+0x38,
+0x10,
+0xfe,
+0x00,
+
+0x00,
+0x00,
+0x10,
+0x38,
+0x7c,
+0xd6,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0x10,
+0xd6,
+0x7c,
+0x38,
+0x10,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x08,
+0x0c,
+0x06,
+0xff,
+0x06,
+0x0c,
+0x08,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x10,
+0x30,
+0x60,
+0xff,
+0x60,
+0x30,
+0x10,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x22,
+0x44,
+0x88,
+0xcc,
+0xee,
+0x44,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x24,
+0x42,
+0xff,
+0x42,
+0x24,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x38,
+0x6c,
+0x6c,
+0xc6,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0xfe,
+0xc6,
+0x6c,
+0x6c,
+0x38,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x18,
+0x3c,
+0x3c,
+0x3c,
+0x3c,
+0x18,
+0x18,
+0x18,
+0x10,
+0x00,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+
+0x22,
+0x77,
+0x33,
+0x11,
+0x22,
+0x44,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x12,
+0x12,
+0x12,
+0x7f,
+0x24,
+0x24,
+0x24,
+0xfe,
+0x48,
+0x48,
+0x48,
+0x00,
+0x00,
+0x00,
+
+0x10,
+0x10,
+0x7c,
+0xd2,
+0xd0,
+0xd0,
+0xd0,
+0x7c,
+0x16,
+0x16,
+0x16,
+0x96,
+0x7c,
+0x10,
+0x10,
+0x00,
+
+0x00,
+0x42,
+0xbe,
+0x44,
+0x0c,
+0x08,
+0x18,
+0x10,
+0x30,
+0x20,
+0x64,
+0x4a,
+0xc4,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x38,
+0x6c,
+0x6c,
+0x6c,
+0x38,
+0x37,
+0x72,
+0xdc,
+0xcc,
+0xcc,
+0xcc,
+0x77,
+0x00,
+0x00,
+0x00,
+
+0x10,
+0x38,
+0x18,
+0x08,
+0x10,
+0x20,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x04,
+0x08,
+0x10,
+0x10,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x10,
+0x10,
+0x08,
+0x04,
+0x00,
+0x00,
+
+0x00,
+0x20,
+0x10,
+0x08,
+0x08,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x08,
+0x08,
+0x10,
+0x20,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x44,
+0x28,
+0x38,
+0xfe,
+0x38,
+0x28,
+0x44,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x18,
+0x18,
+0x7e,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x18,
+0x08,
+0x10,
+0x20,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7e,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x06,
+0x06,
+0x0c,
+0x0c,
+0x18,
+0x18,
+0x30,
+0x30,
+0x60,
+0x60,
+0xc0,
+0xc0,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x3c,
+0x46,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc4,
+0x78,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x08,
+0x18,
+0x78,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x7e,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x7c,
+0x86,
+0x06,
+0x0c,
+0x18,
+0x20,
+0x40,
+0xc1,
+0xfe,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x3c,
+0x46,
+0x04,
+0x08,
+0x1c,
+0x06,
+0x06,
+0x06,
+0x06,
+0x0c,
+0x70,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x04,
+0x08,
+0x10,
+0x2c,
+0x4c,
+0x8c,
+0x8c,
+0xfe,
+0x0c,
+0x0c,
+0x0c,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x02,
+0x3c,
+0x20,
+0x20,
+0x70,
+0x0c,
+0x06,
+0x06,
+0x06,
+0x06,
+0x0c,
+0x70,
+0x00,
+
+0x00,
+0x00,
+0x18,
+0x20,
+0x40,
+0xc0,
+0xdc,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0x44,
+0x38,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x40,
+0x7e,
+0x82,
+0x06,
+0x04,
+0x0c,
+0x18,
+0x18,
+0x30,
+0x30,
+0x30,
+0x30,
+0x00,
+
+0x00,
+0x00,
+0x7c,
+0xc6,
+0xc6,
+0x64,
+0x38,
+0x4c,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0x7c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x38,
+0x44,
+0xc6,
+0xc6,
+0x76,
+0x06,
+0x06,
+0x06,
+0x04,
+0x08,
+0x30,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x18,
+0x08,
+0x10,
+0x20,
+
+0x00,
+0x06,
+0x0c,
+0x18,
+0x30,
+0x60,
+0xa0,
+0xa0,
+0x60,
+0x30,
+0x18,
+0x0c,
+0x06,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7e,
+0x00,
+0x00,
+0x7e,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x60,
+0x30,
+0x18,
+0x0c,
+0x06,
+0x05,
+0x05,
+0x06,
+0x0c,
+0x18,
+0x30,
+0x60,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x7c,
+0x86,
+0xc6,
+0x06,
+0x04,
+0x08,
+0x10,
+0x10,
+0x18,
+0x00,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x3c,
+0x46,
+0xc6,
+0xce,
+0xd6,
+0xd6,
+0xd6,
+0xdc,
+0xc0,
+0xc4,
+0x78,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x2c,
+0x2c,
+0x2c,
+0x7e,
+0x46,
+0x46,
+0x46,
+0xef,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xfc,
+0x66,
+0x66,
+0x66,
+0x66,
+0x7c,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xfc,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3a,
+0x66,
+0xc2,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xfc,
+0x66,
+0x63,
+0x63,
+0x63,
+0x63,
+0x63,
+0x63,
+0x63,
+0x63,
+0x66,
+0xfc,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xff,
+0x61,
+0x60,
+0x60,
+0x64,
+0x7c,
+0x64,
+0x60,
+0x60,
+0x60,
+0x61,
+0xfe,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xff,
+0x61,
+0x61,
+0x60,
+0x64,
+0x7c,
+0x64,
+0x60,
+0x60,
+0x60,
+0x60,
+0xf0,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3a,
+0x66,
+0xc2,
+0xc0,
+0xc0,
+0xc0,
+0xcf,
+0xc6,
+0xc6,
+0xc6,
+0x66,
+0x38,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xf7,
+0x62,
+0x62,
+0x62,
+0x62,
+0x7e,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0xf7,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3c,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x1e,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x08,
+0xf0,
+
+0x00,
+0xf7,
+0x64,
+0x6c,
+0x68,
+0x68,
+0x78,
+0x6c,
+0x6c,
+0x6c,
+0x66,
+0x66,
+0xf7,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xf8,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x61,
+0xfe,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xc3,
+0x66,
+0x76,
+0x7e,
+0x56,
+0x56,
+0x46,
+0x46,
+0x46,
+0x46,
+0x46,
+0xef,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xe7,
+0x62,
+0x62,
+0x72,
+0x52,
+0x5a,
+0x4a,
+0x4e,
+0x46,
+0x46,
+0x42,
+0xe2,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3c,
+0x66,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xfc,
+0x66,
+0x66,
+0x66,
+0x66,
+0x6c,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0xf0,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3c,
+0x66,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0x66,
+0x3c,
+0x10,
+0x39,
+0x0e,
+
+0x00,
+0xfc,
+0x66,
+0x66,
+0x66,
+0x66,
+0x7c,
+0x6c,
+0x66,
+0x66,
+0x66,
+0x66,
+0xf3,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x7a,
+0xc6,
+0xc2,
+0xc0,
+0x70,
+0x3c,
+0x0e,
+0x06,
+0x06,
+0x86,
+0xc6,
+0xbc,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xff,
+0x99,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xf7,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xf7,
+0x62,
+0x62,
+0x62,
+0x76,
+0x34,
+0x34,
+0x34,
+0x3c,
+0x18,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xf7,
+0x62,
+0x62,
+0x62,
+0x62,
+0x6a,
+0x6a,
+0x6a,
+0x6a,
+0x7e,
+0x7e,
+0x34,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xf7,
+0x62,
+0x62,
+0x34,
+0x34,
+0x18,
+0x18,
+0x2c,
+0x2c,
+0x46,
+0x46,
+0xef,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xf7,
+0x62,
+0x62,
+0x62,
+0x34,
+0x34,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x7f,
+0x46,
+0x86,
+0x0c,
+0x0c,
+0x18,
+0x18,
+0x30,
+0x30,
+0x61,
+0x62,
+0xfe,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3c,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xc0,
+0xc0,
+0x60,
+0x60,
+0x30,
+0x30,
+0x18,
+0x18,
+0x0c,
+0x0c,
+0x06,
+0x06,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x10,
+0x38,
+0x4c,
+0x86,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+
+0x00,
+0x18,
+0x20,
+0x30,
+0x38,
+0x10,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x78,
+0x8c,
+0x0c,
+0x3c,
+0xcc,
+0xcc,
+0xcd,
+0x76,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x20,
+0xe0,
+0x60,
+0x60,
+0x6c,
+0x76,
+0x66,
+0x66,
+0x66,
+0x66,
+0x76,
+0x6c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x3c,
+0x66,
+0x60,
+0x60,
+0x60,
+0x60,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x04,
+0x1c,
+0x0c,
+0x0c,
+0x6c,
+0xdc,
+0xcc,
+0xcc,
+0xcc,
+0xcc,
+0xdc,
+0x66,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x3c,
+0x66,
+0x7e,
+0x60,
+0x60,
+0x60,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x1e,
+0x31,
+0x33,
+0x30,
+0x30,
+0x78,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x78,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7b,
+0xce,
+0xcc,
+0xcc,
+0xcc,
+0x78,
+0x60,
+0x7c,
+0x86,
+0xc6,
+0x7c,
+
+0x00,
+0x20,
+0xe0,
+0x60,
+0x60,
+0x6c,
+0x76,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xf7,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x10,
+0x38,
+0x10,
+0x00,
+0x18,
+0x38,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x08,
+0x1c,
+0x08,
+0x00,
+0x0c,
+0x1c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x0c,
+0x6c,
+0x4c,
+0x38,
+0x00,
+
+0x00,
+0x20,
+0xe0,
+0x60,
+0x60,
+0x67,
+0x66,
+0x6c,
+0x78,
+0x6c,
+0x6c,
+0x66,
+0xe7,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x08,
+0x38,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x6a,
+0xfe,
+0x6a,
+0x6a,
+0x6a,
+0x62,
+0x62,
+0xf7,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x5c,
+0xf6,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xf7,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x3c,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x5c,
+0xe6,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x7c,
+0x60,
+0x60,
+0xf0,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x76,
+0xcc,
+0xcc,
+0xcc,
+0xcc,
+0xcc,
+0xcc,
+0x7c,
+0x0c,
+0x0c,
+0x1e,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x5e,
+0xf6,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0xf0,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7a,
+0xc6,
+0x72,
+0x1c,
+0x06,
+0x86,
+0xc6,
+0xbc,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x10,
+0x30,
+0x7c,
+0x30,
+0x30,
+0x30,
+0x30,
+0x30,
+0x34,
+0x18,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xee,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x67,
+0x3a,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xf7,
+0x62,
+0x76,
+0x34,
+0x34,
+0x3c,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xf7,
+0x62,
+0x6a,
+0x6a,
+0x6a,
+0x6a,
+0x7e,
+0x24,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xf7,
+0x62,
+0x34,
+0x18,
+0x2c,
+0x46,
+0x46,
+0xef,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xf7,
+0x62,
+0x62,
+0x34,
+0x34,
+0x18,
+0x18,
+0x18,
+0x10,
+0xb0,
+0xe0,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xfe,
+0x8c,
+0x18,
+0x30,
+0x30,
+0x60,
+0xc2,
+0xfe,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x0e,
+0x18,
+0x10,
+0x10,
+0x08,
+0x70,
+0x70,
+0x08,
+0x10,
+0x10,
+0x18,
+0x0e,
+0x00,
+0x00,
+0x00,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x00,
+0x00,
+
+0x00,
+0x70,
+0x18,
+0x08,
+0x08,
+0x10,
+0x0e,
+0x0e,
+0x10,
+0x08,
+0x08,
+0x18,
+0x70,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x76,
+0xdc,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x10,
+0x38,
+0x6c,
+0xc6,
+0xc6,
+0xc6,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x3a,
+0x66,
+0xc2,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0x62,
+0x3c,
+0x18,
+0x0c,
+0x24,
+0x18,
+
+0x00,
+0x00,
+0x66,
+0x00,
+0x00,
+0xee,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3b,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x0c,
+0x18,
+0x20,
+0x00,
+0x3c,
+0x66,
+0x7e,
+0x60,
+0x60,
+0x60,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x30,
+0x58,
+0x8c,
+0x00,
+0x78,
+0x8c,
+0x0c,
+0x3c,
+0xcc,
+0xcc,
+0xcd,
+0x76,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x66,
+0x00,
+0x00,
+0x78,
+0x8c,
+0x0c,
+0x3c,
+0xcc,
+0xcc,
+0xcd,
+0x76,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x30,
+0x18,
+0x04,
+0x00,
+0x78,
+0x8c,
+0x0c,
+0x3c,
+0xcc,
+0xcc,
+0xcd,
+0x76,
+0x00,
+0x00,
+0x00,
+
+0x38,
+0x44,
+0x44,
+0x38,
+0x00,
+0x78,
+0x8c,
+0x0c,
+0x3c,
+0xcc,
+0xcc,
+0xcd,
+0x76,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x3c,
+0x66,
+0x60,
+0x60,
+0x60,
+0x60,
+0x62,
+0x3c,
+0x08,
+0x24,
+0x18,
+
+0x00,
+0x18,
+0x2c,
+0x46,
+0x00,
+0x3c,
+0x66,
+0x7e,
+0x60,
+0x60,
+0x60,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x66,
+0x00,
+0x00,
+0x3c,
+0x66,
+0x7e,
+0x60,
+0x60,
+0x60,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x30,
+0x18,
+0x04,
+0x00,
+0x3c,
+0x66,
+0x7e,
+0x60,
+0x60,
+0x60,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x66,
+0x00,
+0x00,
+0x38,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x18,
+0x2c,
+0x46,
+0x00,
+0x38,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x60,
+0x30,
+0x08,
+0x00,
+0x38,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x66,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x2c,
+0x2c,
+0x2c,
+0x7e,
+0x46,
+0x46,
+0x46,
+0xef,
+0x00,
+0x00,
+0x00,
+
+0x18,
+0x24,
+0x18,
+0x18,
+0x3c,
+0x2c,
+0x2c,
+0x2c,
+0x7e,
+0x46,
+0x46,
+0x46,
+0xef,
+0x00,
+0x00,
+0x00,
+
+0x0c,
+0x18,
+0xff,
+0x61,
+0x60,
+0x60,
+0x64,
+0x7c,
+0x64,
+0x60,
+0x60,
+0x61,
+0xfe,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x76,
+0x9b,
+0x1b,
+0x3f,
+0xd8,
+0xd8,
+0xd9,
+0x6e,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x1f,
+0x1d,
+0x1d,
+0x3c,
+0x2c,
+0x2e,
+0x2c,
+0x7c,
+0x4c,
+0x4c,
+0x4d,
+0xef,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x18,
+0x2c,
+0x46,
+0x00,
+0x3c,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x66,
+0x00,
+0x00,
+0x3c,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x30,
+0x18,
+0x04,
+0x00,
+0x3c,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x18,
+0x2c,
+0x46,
+0x00,
+0xee,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x67,
+0x3a,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x30,
+0x18,
+0x04,
+0x00,
+0xee,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x67,
+0x3a,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x66,
+0x00,
+0x00,
+0xf7,
+0x62,
+0x62,
+0x34,
+0x34,
+0x18,
+0x18,
+0x18,
+0x10,
+0xb0,
+0xe0,
+
+0x66,
+0x00,
+0x3c,
+0x66,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x66,
+0x00,
+0xf7,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x62,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x10,
+0x10,
+0x10,
+0x7c,
+0xc6,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0xc2,
+0x7c,
+0x10,
+0x10,
+0x00,
+
+0x00,
+0x38,
+0x64,
+0x6c,
+0x60,
+0x60,
+0xf0,
+0x60,
+0x60,
+0x60,
+0x60,
+0x66,
+0xfc,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x81,
+0xc3,
+0x66,
+0x3c,
+0x18,
+0xff,
+0x18,
+0x18,
+0xff,
+0x18,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xfe,
+0x63,
+0x63,
+0x63,
+0x63,
+0x6e,
+0x60,
+0x64,
+0x6e,
+0x64,
+0x64,
+0xf5,
+0x06,
+0x00,
+0x00,
+
+0x00,
+0x0e,
+0x19,
+0x1b,
+0x18,
+0x18,
+0x3c,
+0x18,
+0x18,
+0x18,
+0x18,
+0xd8,
+0x98,
+0x70,
+0x00,
+0x00,
+
+0x00,
+0x0c,
+0x18,
+0x20,
+0x00,
+0x78,
+0x8c,
+0x0c,
+0x3c,
+0xcc,
+0xcc,
+0xcd,
+0x76,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x06,
+0x0c,
+0x10,
+0x00,
+0x38,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x0c,
+0x18,
+0x20,
+0x00,
+0x3c,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x0c,
+0x18,
+0x20,
+0x00,
+0xee,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x67,
+0x3a,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x32,
+0x4c,
+0x00,
+0x5c,
+0xf6,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xf7,
+0x00,
+0x00,
+0x00,
+
+0x32,
+0x4c,
+0x00,
+0xe7,
+0x72,
+0x52,
+0x5a,
+0x4a,
+0x4e,
+0x46,
+0x46,
+0x42,
+0xe2,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x78,
+0x8c,
+0x0c,
+0x3c,
+0xcc,
+0xcc,
+0xcd,
+0x76,
+0x00,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3c,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x00,
+0x7e,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x30,
+0x30,
+0x00,
+0x30,
+0x10,
+0x10,
+0x20,
+0x40,
+0xc0,
+0xc6,
+0xc2,
+0x7c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xfe,
+0xc0,
+0xc0,
+0xc0,
+0xc0,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xfe,
+0x06,
+0x06,
+0x06,
+0x06,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x20,
+0xe0,
+0x63,
+0x66,
+0xfc,
+0x18,
+0x30,
+0x60,
+0xce,
+0x93,
+0x06,
+0x0c,
+0x1f,
+0x00,
+0x00,
+
+0x00,
+0x20,
+0xe0,
+0x63,
+0x66,
+0xfc,
+0x18,
+0x30,
+0x64,
+0xc8,
+0x96,
+0x3f,
+0x06,
+0x06,
+0x00,
+0x00,
+
+0x00,
+0x18,
+0x18,
+0x00,
+0x08,
+0x18,
+0x18,
+0x18,
+0x3c,
+0x3c,
+0x3c,
+0x3c,
+0x18,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x36,
+0x6c,
+0xd8,
+0xd8,
+0x6c,
+0x36,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xd8,
+0x6c,
+0x36,
+0x36,
+0x6c,
+0xd8,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x82,
+0x10,
+0x82,
+0x10,
+0x82,
+0x10,
+0x82,
+0x10,
+0x82,
+0x10,
+0x82,
+0x10,
+0x82,
+0x10,
+0x82,
+0x10,
+
+0x00,
+0x95,
+0x00,
+0xa9,
+0x00,
+0x95,
+0x00,
+0xa9,
+0x00,
+0x95,
+0x00,
+0xa9,
+0x00,
+0x95,
+0x00,
+0xa9,
+
+0x92,
+0x49,
+0x92,
+0x49,
+0x92,
+0x49,
+0x92,
+0x49,
+0x92,
+0x49,
+0x92,
+0x49,
+0x92,
+0x49,
+0x92,
+0x49,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xf8,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xf8,
+0x18,
+0x18,
+0xf8,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xe6,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xfe,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xf8,
+0x18,
+0x18,
+0xf8,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xe6,
+0x06,
+0x06,
+0xe6,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xfe,
+0x06,
+0x06,
+0xe6,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xe6,
+0x06,
+0x06,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xf8,
+0x18,
+0x18,
+0xf8,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xf8,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x1f,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xff,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x1f,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xff,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x1f,
+0x18,
+0x18,
+0x1f,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x67,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x67,
+0x60,
+0x60,
+0x7f,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7f,
+0x60,
+0x60,
+0x67,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xe7,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+0xe7,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x67,
+0x60,
+0x60,
+0x67,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xe7,
+0x00,
+0x00,
+0xe7,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xff,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xff,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0x00,
+0x00,
+0xff,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x7f,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x1f,
+0x18,
+0x18,
+0x1f,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x1f,
+0x18,
+0x18,
+0x1f,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7f,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0xff,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xff,
+0x00,
+0x00,
+0xff,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xf8,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x1f,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+0xf0,
+
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+0x0f,
+
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x77,
+0xcc,
+0xcc,
+0xcc,
+0xcc,
+0xde,
+0x73,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x7c,
+0xc6,
+0xc6,
+0xc6,
+0xc4,
+0xc8,
+0xc4,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xdc,
+0xc0,
+0xc0,
+0x00,
+
+0x00,
+0xff,
+0x61,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0x60,
+0xf0,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x01,
+0x7e,
+0xa4,
+0x24,
+0x2c,
+0x6c,
+0x6c,
+0x6c,
+0x48,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xff,
+0xc1,
+0x60,
+0x30,
+0x18,
+0x0c,
+0x18,
+0x30,
+0x60,
+0xc0,
+0xc1,
+0xfe,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7f,
+0xc8,
+0xc8,
+0xc8,
+0xc8,
+0xc8,
+0xc8,
+0x70,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x22,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x7c,
+0x60,
+0x60,
+0x60,
+0xc0,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x76,
+0xdc,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x10,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x38,
+0x10,
+0x7c,
+0xd6,
+0xd6,
+0xd6,
+0xd6,
+0xd6,
+0xd6,
+0x7c,
+0x10,
+0x38,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x38,
+0x6c,
+0xc6,
+0xc6,
+0xc6,
+0xfe,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0x6c,
+0x38,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x3c,
+0x66,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0xc3,
+0x66,
+0x24,
+0x24,
+0xa5,
+0xe7,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x1e,
+0x31,
+0x30,
+0x18,
+0x0c,
+0x3e,
+0x66,
+0x66,
+0x66,
+0x66,
+0x66,
+0x3c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x6e,
+0xff,
+0x99,
+0x99,
+0x99,
+0x99,
+0xff,
+0x76,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x02,
+0x04,
+0x7c,
+0xca,
+0x92,
+0xa6,
+0x7c,
+0x40,
+0x80,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x1c,
+0x30,
+0x60,
+0x60,
+0x60,
+0x7c,
+0x60,
+0x60,
+0x60,
+0x60,
+0x30,
+0x1c,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x7c,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0xc6,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x7c,
+0x00,
+0x00,
+0x00,
+0xfe,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x18,
+0x18,
+0x7e,
+0x18,
+0x18,
+0x00,
+0x00,
+0x7e,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x30,
+0x18,
+0x0c,
+0x06,
+0x0c,
+0x18,
+0x30,
+0x00,
+0x7e,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x0c,
+0x18,
+0x30,
+0x60,
+0x30,
+0x18,
+0x0c,
+0x00,
+0x7e,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x0e,
+0x19,
+0x1b,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0x18,
+0xd8,
+0x98,
+0x70,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x18,
+0x18,
+0x00,
+0x7e,
+0x00,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x76,
+0xdc,
+0x00,
+0x00,
+0x76,
+0xdc,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x38,
+0x44,
+0x44,
+0x44,
+0x38,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x18,
+0x18,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x18,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x07,
+0x06,
+0x06,
+0x0c,
+0x0c,
+0x08,
+0x98,
+0xd0,
+0xf0,
+0x60,
+0x20,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0xcc,
+0x76,
+0x66,
+0x66,
+0x66,
+0x66,
+0xf7,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x70,
+0x98,
+0x18,
+0x30,
+0x60,
+0x88,
+0xf8,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x7c,
+0x64,
+0x64,
+0x64,
+0x64,
+0x64,
+0x7c,
+0x00,
+0x00,
+0x00,
+0x00,
+
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+0x00,
+
+};
+
+
+const struct font_desc font_rl = {
+ RL_IDX,
+ "RomanLarge",
+ 8,
+ 16,
+ patterns,
+ -1
+};
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index 4fd07d9eca03..9be83bed1959 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -64,6 +64,10 @@ static const struct font_desc *fonts[] = {
#undef NO_FONTS
&font_mini_4x6,
#endif
+#ifdef CONFIG_FONT_RL
+#undef NO_FONTS
+ &font_rl,
+#endif
};
#define num_fonts (sizeof(fonts)/sizeof(*fonts))
diff --git a/drivers/video/softcursor.c b/drivers/video/console/softcursor.c
index 229c4bc35079..8529bf08db28 100644
--- a/drivers/video/softcursor.c
+++ b/drivers/video/console/softcursor.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices
*
- * Created 14 Nov 2002 by James Simmons
+ * Created 14 Nov 2002 by James Simmons
*
* 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
@@ -55,9 +55,9 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
src[i] = image->data[i] & cursor->mask[i];
break;
}
- } else
+ } else
memcpy(src, image->data, dsize);
-
+
fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
image->data = dst;
info->fbops->fb_imageblit(info, image);
@@ -66,7 +66,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
}
EXPORT_SYMBOL(soft_cursor);
-
+
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
MODULE_DESCRIPTION("Generic software cursor");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 989e700159e0..403d17377f8d 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -176,7 +176,6 @@ static struct fb_ops controlfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 3894b2a501d6..c589d23e7f91 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1064,7 +1064,6 @@ static struct fb_ops cyber2000fb_ops = {
.fb_fillrect = cyber2000fb_fillrect,
.fb_copyarea = cyber2000fb_copyarea,
.fb_imageblit = cyber2000fb_imageblit,
- .fb_cursor = soft_cursor,
.fb_sync = cyber2000fb_sync,
};
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 6992100a508c..03fbe83d71a8 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -968,7 +968,6 @@ static struct fb_ops cyblafb_ops __devinitdata = {
.fb_fillrect = cyblafb_fillrect,
.fb_copyarea= cyblafb_copyarea,
.fb_imageblit = cyblafb_imageblit,
- .fb_cursor = soft_cursor,
};
//==========================================================================
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 1785686a7f11..957a3ada2b75 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -116,7 +116,6 @@ static struct fb_ops dn_fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = dnfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
struct fb_var_screeninfo dnfb_var __devinitdata = {
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 7363d0b25fdf..6a81a1dd8f3d 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -484,7 +484,6 @@ static struct fb_ops epson1355fb_fbops = {
.fb_imageblit = cfb_imageblit,
.fb_read = epson1355fb_read,
.fb_write = epson1355fb_write,
- .fb_cursor = soft_cursor,
};
/* ------------------------------------------------------------------------- */
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 713226cdf3c6..fc7965b66775 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -538,25 +538,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
*dbsize = 0;
- DPRINTK(" Supported VESA Modes\n");
- block = edid + ESTABLISHED_TIMING_1;
- num += get_est_timing(block, &mode[num]);
-
- DPRINTK(" Standard Timings\n");
- block = edid + STD_TIMING_DESCRIPTIONS_START;
- for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
- num += get_std_timing(block, &mode[num]);
-
DPRINTK(" Detailed Timings\n");
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
int first = 1;
- if (block[0] == 0x00 && block[1] == 0x00) {
- if (block[3] == 0xfa) {
- num += get_dst_timing(block + 5, &mode[num]);
- }
- } else {
+ if (!(block[0] == 0x00 && block[1] == 0x00)) {
get_detailed_timing(block, &mode[num]);
if (first) {
mode[num].flag |= FB_MODE_IS_FIRST;
@@ -565,6 +552,21 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
num++;
}
}
+
+ DPRINTK(" Supported VESA Modes\n");
+ block = edid + ESTABLISHED_TIMING_1;
+ num += get_est_timing(block, &mode[num]);
+
+ DPRINTK(" Standard Timings\n");
+ block = edid + STD_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+ num += get_std_timing(block, &mode[num]);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
+ num += get_dst_timing(block + 5, &mode[num]);
+ }
/* Yikes, EDID data is totally useless */
if (!num) {
@@ -827,7 +829,7 @@ int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
{
unsigned char *block;
- int i;
+ int i, found = 0;
if (edid == NULL)
return;
@@ -869,6 +871,22 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
get_monspecs(edid, specs);
specs->modedb = fb_create_modedb(edid, &specs->modedb_len);
+
+ /*
+ * Workaround for buggy EDIDs that sets that the first
+ * detailed timing is preferred but has not detailed
+ * timing specified
+ */
+ for (i = 0; i < specs->modedb_len; i++) {
+ if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ specs->misc &= ~FB_MISC_1ST_DETAIL;
+
DPRINTK("========================================\n");
}
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 10cd05059fe9..04417dc16c2e 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -57,9 +57,6 @@ static struct fb_ops ffb_ops = {
.fb_sync = ffb_sync,
.fb_mmap = ffb_mmap,
.fb_ioctl = ffb_ioctl,
-
- /* XXX Use FFB hw cursor once fb cursor API is better understood... */
- .fb_cursor = soft_cursor,
};
/* Register layout and definitions */
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index a0763283d776..998374cfae6d 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -172,7 +172,6 @@ static struct fb_ops fm2fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
/*
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index ed853bef19e9..9d5e4f342110 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1038,7 +1038,6 @@ static struct fb_ops gbefb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
/*
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
index 5a9b89c3831b..42fb9a89a792 100644
--- a/drivers/video/geode/Kconfig
+++ b/drivers/video/geode/Kconfig
@@ -14,7 +14,6 @@ config FB_GEODE_GX1
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_SOFT_CURSOR
---help---
Framebuffer driver for the display controller integrated into the
AMD Geode GX1 processor.
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 74a5fca86b8a..8e8da7433994 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -275,7 +275,6 @@ static struct fb_ops gx1fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev)
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 0d376ba54814..f04ca721f94c 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -262,7 +262,6 @@ static struct fb_ops hitfb_ops = {
.fb_fillrect = hitfb_fillrect,
.fb_copyarea = hitfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
int __init hitfb_init(void)
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index e97fe8481d59..bebdac59d231 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -193,7 +193,6 @@ static struct fb_ops hpfb_ops = {
.fb_fillrect = hpfb_fillrect,
.fb_copyarea = hpfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_sync = hpfb_sync,
};
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c
index 689d2586366d..c61bad0da20f 100644
--- a/drivers/video/i810/i810-i2c.c
+++ b/drivers/video/i810/i810-i2c.c
@@ -46,92 +46,45 @@ static void i810i2c_setscl(void *data, int state)
struct i810fb_par *par = chan->par;
u8 __iomem *mmio = par->mmio_start_virtual;
- i810_writel(mmio, GPIOB, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
+ i810_writel(mmio, chan->ddc_base, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
SCL_DIR_MASK | SCL_VAL_MASK);
- i810_readl(mmio, GPIOB); /* flush posted write */
+ i810_readl(mmio, chan->ddc_base); /* flush posted write */
}
static void i810i2c_setsda(void *data, int state)
{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_i2c_chan *chan = data;
struct i810fb_par *par = chan->par;
u8 __iomem *mmio = par->mmio_start_virtual;
- i810_writel(mmio, GPIOB, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
+ i810_writel(mmio, chan->ddc_base, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
SDA_DIR_MASK | SDA_VAL_MASK);
- i810_readl(mmio, GPIOB); /* flush posted write */
+ i810_readl(mmio, chan->ddc_base); /* flush posted write */
}
static int i810i2c_getscl(void *data)
{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_i2c_chan *chan = data;
struct i810fb_par *par = chan->par;
u8 __iomem *mmio = par->mmio_start_virtual;
- i810_writel(mmio, GPIOB, SCL_DIR_MASK);
- i810_writel(mmio, GPIOB, 0);
- return (0 != (i810_readl(mmio, GPIOB) & SCL_VAL_IN));
+ i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK);
+ i810_writel(mmio, chan->ddc_base, 0);
+ return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0);
}
static int i810i2c_getsda(void *data)
{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
+ struct i810fb_i2c_chan *chan = data;
struct i810fb_par *par = chan->par;
u8 __iomem *mmio = par->mmio_start_virtual;
- i810_writel(mmio, GPIOB, SDA_DIR_MASK);
- i810_writel(mmio, GPIOB, 0);
- return (0 != (i810_readl(mmio, GPIOB) & SDA_VAL_IN));
-}
-
-static void i810ddc_setscl(void *data, int state)
-{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
- struct i810fb_par *par = chan->par;
- u8 __iomem *mmio = par->mmio_start_virtual;
-
- i810_writel(mmio, GPIOA, (state ? SCL_VAL_OUT : 0) | SCL_DIR |
- SCL_DIR_MASK | SCL_VAL_MASK);
- i810_readl(mmio, GPIOA); /* flush posted write */
-}
-
-static void i810ddc_setsda(void *data, int state)
-{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
- struct i810fb_par *par = chan->par;
- u8 __iomem *mmio = par->mmio_start_virtual;
-
- i810_writel(mmio, GPIOA, (state ? SDA_VAL_OUT : 0) | SDA_DIR |
- SDA_DIR_MASK | SDA_VAL_MASK);
- i810_readl(mmio, GPIOA); /* flush posted write */
-}
-
-static int i810ddc_getscl(void *data)
-{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
- struct i810fb_par *par = chan->par;
- u8 __iomem *mmio = par->mmio_start_virtual;
-
- i810_writel(mmio, GPIOA, SCL_DIR_MASK);
- i810_writel(mmio, GPIOA, 0);
- return (0 != (i810_readl(mmio, GPIOA) & SCL_VAL_IN));
-}
-
-static int i810ddc_getsda(void *data)
-{
- struct i810fb_i2c_chan *chan = (struct i810fb_i2c_chan *)data;
- struct i810fb_par *par = chan->par;
- u8 __iomem *mmio = par->mmio_start_virtual;
-
- i810_writel(mmio, GPIOA, SDA_DIR_MASK);
- i810_writel(mmio, GPIOA, 0);
- return (0 != (i810_readl(mmio, GPIOA) & SDA_VAL_IN));
+ i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK);
+ i810_writel(mmio, chan->ddc_base, 0);
+ return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0);
}
-#define I2C_ALGO_DDC_I810 0x0e0000
-#define I2C_ALGO_I2C_I810 0x0f0000
-static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name,
- int conn)
+static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
{
int rc;
@@ -139,22 +92,11 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name,
chan->adapter.owner = THIS_MODULE;
chan->adapter.algo_data = &chan->algo;
chan->adapter.dev.parent = &chan->par->dev->dev;
- switch (conn) {
- case 1:
- chan->adapter.id = I2C_ALGO_DDC_I810;
- chan->algo.setsda = i810ddc_setsda;
- chan->algo.setscl = i810ddc_setscl;
- chan->algo.getsda = i810ddc_getsda;
- chan->algo.getscl = i810ddc_getscl;
- break;
- case 2:
- chan->adapter.id = I2C_ALGO_I2C_I810;
- chan->algo.setsda = i810i2c_setsda;
- chan->algo.setscl = i810i2c_setscl;
- chan->algo.getsda = i810i2c_getsda;
- chan->algo.getscl = i810i2c_getscl;
- break;
- }
+ chan->adapter.id = I2C_HW_B_I810;
+ chan->algo.setsda = i810i2c_setsda;
+ chan->algo.setscl = i810i2c_setscl;
+ chan->algo.getsda = i810i2c_getsda;
+ chan->algo.getscl = i810i2c_getscl;
chan->algo.udelay = 10;
chan->algo.mdelay = 10;
chan->algo.timeout = (HZ/2);
@@ -168,11 +110,15 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name,
udelay(20);
rc = i2c_bit_add_bus(&chan->adapter);
+
if (rc == 0)
dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name);
- else
+ else {
dev_warn(&chan->par->dev->dev, "Failed to register I2C bus "
"%s.\n", name);
+ chan->par = NULL;
+ }
+
return rc;
}
@@ -180,8 +126,14 @@ void i810_create_i2c_busses(struct i810fb_par *par)
{
par->chan[0].par = par;
par->chan[1].par = par;
- i810_setup_i2c_bus(&par->chan[0], "I810-DDC", 1);
- i810_setup_i2c_bus(&par->chan[1], "I810-I2C", 2);
+ par->chan[2].par = par;
+
+ par->chan[0].ddc_base = GPIOA;
+ i810_setup_i2c_bus(&par->chan[0], "I810-DDC");
+ par->chan[1].ddc_base = GPIOB;
+ i810_setup_i2c_bus(&par->chan[1], "I810-I2C");
+ par->chan[2].ddc_base = GPIOC;
+ i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC");
}
void i810_delete_i2c_busses(struct i810fb_par *par)
@@ -189,9 +141,14 @@ void i810_delete_i2c_busses(struct i810fb_par *par)
if (par->chan[0].par)
i2c_bit_del_bus(&par->chan[0].adapter);
par->chan[0].par = NULL;
+
if (par->chan[1].par)
i2c_bit_del_bus(&par->chan[1].adapter);
par->chan[1].par = NULL;
+
+ if (par->chan[2].par)
+ i2c_bit_del_bus(&par->chan[2].adapter);
+ par->chan[2].par = NULL;
}
static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan)
@@ -221,6 +178,7 @@ static u8 *i810_do_probe_i2c_edid(struct i810fb_i2c_chan *chan)
DPRINTK("i810-i2c: I2C Transfer successful\n");
return buf;
}
+
DPRINTK("i810-i2c: Unable to read EDID block.\n");
kfree(buf);
return NULL;
@@ -233,7 +191,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
int i;
DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn);
- if (conn < 3) {
+ if (conn < 4) {
for (i = 0; i < 3; i++) {
/* Do the real work */
edid = i810_do_probe_i2c_edid(&par->chan[conn-1]);
@@ -241,11 +199,14 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
break;
}
} else {
- DPRINTK("i810-i2c: Getting EDID from BIOS\n");
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, fb_firmware_edid(info->device),
- EDID_LENGTH);
+ const u8 *e = fb_firmware_edid(info->device);
+
+ if (e != NULL) {
+ DPRINTK("i810-i2c: Getting EDID from BIOS\n");
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, e, EDID_LENGTH);
+ }
}
if (out_edid)
@@ -253,5 +214,3 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn)
return (edid) ? 0 : 1;
}
-
-
diff --git a/drivers/video/i810/i810.h b/drivers/video/i810/i810.h
index d48949ceaacc..6c187d5fe951 100644
--- a/drivers/video/i810/i810.h
+++ b/drivers/video/i810/i810.h
@@ -249,6 +249,7 @@ struct i810fb_i2c_chan {
struct i810fb_par *par;
struct i2c_adapter adapter;
struct i2c_algo_bit_data algo;
+ unsigned long ddc_base;
};
struct i810fb_par {
@@ -262,7 +263,7 @@ struct i810fb_par {
struct heap_data iring;
struct heap_data cursor_heap;
struct vgastate state;
- struct i810fb_i2c_chan chan[2];
+ struct i810fb_i2c_chan chan[3];
atomic_t use_count;
u32 pseudo_palette[17];
unsigned long mmio_start_phys;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 0dbc9ddb6766..c0c974b1afaa 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1854,7 +1854,7 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
#ifdef CONFIG_FB_I810_I2C
i810_create_i2c_busses(par);
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < 4; i++) {
err = i810_probe_i2c_connector(info, &par->edid, i+1);
if (!err)
break;
@@ -1871,27 +1871,18 @@ static void __devinit i810fb_find_init_mode(struct fb_info *info)
fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
&info->modelist);
if (specs->modedb != NULL) {
- if (xres && yres) {
- struct fb_videomode *m;
+ struct fb_videomode *m;
+ if (xres && yres) {
if ((m = fb_find_best_mode(&var, &info->modelist))) {
mode = *m;
found = 1;
}
}
- if (!found && specs->misc & FB_MISC_1ST_DETAIL) {
- for (i = 0; i < specs->modedb_len; i++) {
- if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
- mode = specs->modedb[i];
- found = 1;
- break;
- }
- }
- }
-
if (!found) {
- mode = specs->modedb[0];
+ m = fb_find_best_display(&info->monspecs, &info->modelist);
+ mode = *m;
found = 1;
}
@@ -2066,8 +2057,7 @@ static void i810fb_release_resource(struct fb_info *info,
iounmap(par->mmio_start_virtual);
if (par->aperture.virtual)
iounmap(par->aperture.virtual);
- if (par->edid)
- kfree(par->edid);
+ kfree(par->edid);
if (par->res_flags & FRAMEBUFFER_REQ)
release_mem_region(par->aperture.physical,
par->aperture.size);
diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/i810/i810_regs.h
index 6e4b9afa4d98..91c6bd9d0d0d 100644
--- a/drivers/video/i810/i810_regs.h
+++ b/drivers/video/i810/i810_regs.h
@@ -70,6 +70,7 @@
#define HVSYNC 0x05000
#define GPIOA 0x05010
#define GPIOB 0x05014
+#define GPIOC 0x0501C
/* Clock Control and Power Management Registers (06000h 06FFFh) */
#define DCLK_0D 0x06000
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 7b9bf45ab6fe..7fbe24206b19 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1344,7 +1344,6 @@ static struct fb_ops imsttfb_ops = {
.fb_fillrect = imsttfb_fillrect,
.fb_copyarea = imsttfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_ioctl = imsttfb_ioctl,
};
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 64d9bcc38da3..e20b9f3a255f 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -298,7 +298,6 @@ static struct fb_ops imxfb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = imxfb_blank,
- .fb_cursor = soft_cursor, /* FIXME: i.MX can do hardware cursor */
};
/*
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index 011e11626558..f077ca34faba 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -10,7 +10,7 @@
/*** Version/name ***/
#define INTELFB_VERSION "0.9.2"
#define INTELFB_MODULE_NAME "intelfb"
-#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G"
+#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G/915GM"
/*** Debug/feature defines ***/
@@ -47,6 +47,7 @@
#define PCI_DEVICE_ID_INTEL_85XGM 0x3582
#define PCI_DEVICE_ID_INTEL_865G 0x2572
#define PCI_DEVICE_ID_INTEL_915G 0x2582
+#define PCI_DEVICE_ID_INTEL_915GM 0x2592
/* Size of MMIO region */
#define INTEL_REG_SIZE 0x80000
@@ -119,7 +120,8 @@ enum intel_chips {
INTEL_855GM,
INTEL_855GME,
INTEL_865G,
- INTEL_915G
+ INTEL_915G,
+ INTEL_915GM
};
struct intelfb_hwstate {
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 80a09344f1aa..0799b999b314 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -1,7 +1,7 @@
/*
* intelfb
*
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM
* integrated graphics chips.
*
* Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
@@ -186,6 +186,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
{ 0, }
};
@@ -549,10 +550,11 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
}
/* Set base addresses. */
- if (ent->device == PCI_DEVICE_ID_INTEL_915G) {
+ if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
+ (ent->device == PCI_DEVICE_ID_INTEL_915GM)) {
aperture_bar = 2;
mmio_bar = 0;
- /* Disable HW cursor on 915G (not implemented yet) */
+ /* Disable HW cursor on 915G/M (not implemented yet) */
hwcursor = 0;
}
dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
@@ -1483,7 +1485,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
#endif
if (!dinfo->hwcursor)
- return soft_cursor(info, cursor);
+ return -ENODEV;
intelfbhw_cursor_hide(dinfo);
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 5bafc3c54db7..ac94c2e5ff85 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -99,6 +99,11 @@ intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,
*chipset = INTEL_915G;
*mobile = 0;
return 0;
+ case PCI_DEVICE_ID_INTEL_915GM:
+ *name = "Intel(R) 915GM";
+ *chipset = INTEL_915GM;
+ *mobile = 1;
+ return 0;
default:
return 1;
}
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index d8bac9e97842..5eb4d5c177bd 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -669,7 +669,6 @@ static struct fb_ops kyrofb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static int __devinit kyrofb_probe(struct pci_dev *pdev,
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 7e1e7fb168bd..84a7fe435bb8 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -51,7 +51,6 @@ static struct fb_ops leo_ops = {
.fb_imageblit = cfb_imageblit,
.fb_mmap = leo_mmap,
.fb_ioctl = leo_ioctl,
- .fb_cursor = soft_cursor,
};
#define LEO_OFF_LC_SS0_KRN 0x00200000UL
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
index 3e9ccf370ab2..8cb7fb4db441 100644
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -7,6 +7,8 @@ menu "Logo configuration"
config LOGO
bool "Bootup logo"
depends on FB || SGI_NEWPORT_CONSOLE
+ help
+ Enable and select frame buffer bootup logos.
config LOGO_LINUX_MONO
bool "Standard black and white Linux logo"
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 4945a4c02209..cfc748e94272 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -589,7 +589,6 @@ static struct fb_ops macfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
void __init macfb_setup(char *options)
diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c
index 149680f8bcf0..0fbd9b5149f1 100644
--- a/drivers/video/matrox/matroxfb_DAC1064.c
+++ b/drivers/video/matrox/matroxfb_DAC1064.c
@@ -657,7 +657,6 @@ static int MGA1064_preinit(WPMINFO2) {
/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
ACCESS_FBINFO(capable.text) = 1;
ACCESS_FBINFO(capable.vxres) = vxres_mystique;
- ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
ACCESS_FBINFO(outputs[0]).output = &m1064;
ACCESS_FBINFO(outputs[0]).src = ACCESS_FBINFO(outputs[0]).default_src;
@@ -842,7 +841,6 @@ static int MGAG100_preinit(WPMINFO2) {
/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
ACCESS_FBINFO(capable.text) = 1;
ACCESS_FBINFO(capable.vxres) = vxres_g100;
- ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100
? ACCESS_FBINFO(devflags.sgram) : 1;
@@ -980,7 +978,7 @@ static void MGAG100_reset(WPMINFO2) {
hw->MXoptionReg |= 0x40; /* FIXME... */
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
}
- mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
+ mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
}
}
if (ACCESS_FBINFO(devflags.g450dac)) {
diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c
index c7f3e1321224..a5c825d99466 100644
--- a/drivers/video/matrox/matroxfb_accel.c
+++ b/drivers/video/matrox/matroxfb_accel.c
@@ -122,7 +122,7 @@ void matrox_cfbX_init(WPMINFO2) {
ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea;
ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect;
ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit;
- ACCESS_FBINFO(fbops).fb_cursor = soft_cursor;
+ ACCESS_FBINFO(fbops).fb_cursor = NULL;
accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index e02da41f1b26..1e74f4cca53b 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -264,7 +264,6 @@ static void matroxfb_disable_irq(WPMINFO2) {
}
int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
- wait_queue_t __wait;
struct matrox_vsync *vs;
unsigned int cnt;
int ret;
@@ -286,7 +285,6 @@ int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) {
if (ret) {
return ret;
}
- init_waitqueue_entry(&__wait, current);
cnt = vs->cnt;
ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10);
@@ -500,10 +498,6 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
} else {
xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp);
}
- if (!xres_new) return 0;
- if (xres != xres_new) {
- printk(KERN_INFO "matroxfb: cannot set xres to %d, rounded up to %d\n", xres, xres_new);
- }
return xres_new;
}
@@ -1285,7 +1279,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
vaddr_t vm;
unsigned int offs;
unsigned int offs2;
- unsigned char store, orig;
+ unsigned char orig;
unsigned char bytes[32];
unsigned char* tmp;
@@ -1301,16 +1295,12 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
orig = mga_inb(M_EXTVGA_DATA);
mga_outb(M_EXTVGA_DATA, orig | 0x80);
- store = mga_readb(vm, 0x1234);
tmp = bytes;
for (offs = 0x100000; offs < maxSize; offs += 0x200000)
*tmp++ = mga_readb(vm, offs);
for (offs = 0x100000; offs < maxSize; offs += 0x200000)
mga_writeb(vm, offs, 0x02);
- if (ACCESS_FBINFO(features.accel.has_cacheflush))
- mga_outb(M_CACHEFLUSH, 0x00);
- else
- mga_writeb(vm, 0x1234, 0x99);
+ mga_outb(M_CACHEFLUSH, 0x00);
for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
if (mga_readb(vm, offs) != 0x02)
break;
@@ -1321,7 +1311,6 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
tmp = bytes;
for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
mga_writeb(vm, offs2, *tmp++);
- mga_writeb(vm, 0x1234, store);
mga_outb(M_EXTVGA_INDEX, 0x03);
mga_outb(M_EXTVGA_DATA, orig);
@@ -1430,6 +1419,20 @@ static struct board {
MGA_1164,
&vbMystique,
"Mystique 220 (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0x02,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_CROSS4MB,
+ 180000,
+ MGA_1064,
+ &vbMystique,
+ "Mystique (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ MGA_1164,
+ &vbMystique,
+ "Mystique 220 (AGP)"},
#endif
#ifdef CONFIG_FB_MATROX_G
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF,
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 85a0b2558452..a8c47ad2cdb6 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -272,10 +272,6 @@ struct matrox_DAC1064_features {
u_int8_t xmiscctrl;
};
-struct matrox_accel_features {
- int has_cacheflush;
-};
-
/* current hardware status */
struct mavenregs {
u_int8_t regs[256];
@@ -440,7 +436,6 @@ struct matrox_fb_info {
struct {
struct matrox_pll_features pll;
struct matrox_DAC1064_features DAC1064;
- struct matrox_accel_features accel;
} features;
struct {
spinlock_t DAC;
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 429047ac615a..d52d7d825c41 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -576,7 +576,6 @@ static struct fb_ops matroxfb_dh_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static struct fb_var_screeninfo matroxfb_dh_defined = {
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index f192d995d030..743e7ad26acc 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -113,7 +113,6 @@ static struct fb_ops maxinefb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
int __init maxinefb_init(void)
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 47516c44a390..1789a52d776a 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -676,6 +676,8 @@ void fb_var_to_videomode(struct fb_videomode *mode,
mode->sync = var->sync;
mode->vmode = var->vmode & FB_VMODE_MASK;
mode->flag = FB_MODE_IS_FROM_VAR;
+ mode->refresh = 0;
+
if (!var->pixclock)
return;
@@ -785,39 +787,39 @@ struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
}
/**
- * fb_find_nearest_mode - find mode closest video mode
+ * fb_find_nearest_mode - find closest videomode
*
- * @var: pointer to struct fb_var_screeninfo
+ * @mode: pointer to struct fb_videomode
* @head: pointer to modelist
*
* Finds best matching videomode, smaller or greater in dimension.
* If more than 1 videomode is found, will return the videomode with
- * the closest refresh rate
+ * the closest refresh rate.
*/
-struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var,
+struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
struct list_head *head)
{
struct list_head *pos;
struct fb_modelist *modelist;
- struct fb_videomode *mode, *best = NULL;
+ struct fb_videomode *cmode, *best = NULL;
u32 diff = -1, diff_refresh = -1;
list_for_each(pos, head) {
u32 d;
modelist = list_entry(pos, struct fb_modelist, list);
- mode = &modelist->mode;
+ cmode = &modelist->mode;
- d = abs(mode->xres - var->xres) +
- abs(mode->yres - var->yres);
+ d = abs(cmode->xres - mode->xres) +
+ abs(cmode->yres - mode->yres);
if (diff > d) {
diff = d;
- best = mode;
+ best = cmode;
} else if (diff == d) {
- d = abs(mode->refresh - best->refresh);
+ d = abs(cmode->refresh - mode->refresh);
if (diff_refresh > d) {
diff_refresh = d;
- best = mode;
+ best = cmode;
}
}
}
@@ -942,6 +944,66 @@ void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
}
}
+struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
+ struct list_head *head)
+{
+ struct list_head *pos;
+ struct fb_modelist *modelist;
+ struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL;
+ int first = 0;
+
+ if (!head->prev || !head->next || list_empty(head))
+ goto finished;
+
+ /* get the first detailed mode and the very first mode */
+ list_for_each(pos, head) {
+ modelist = list_entry(pos, struct fb_modelist, list);
+ m = &modelist->mode;
+
+ if (!first) {
+ m1 = m;
+ first = 1;
+ }
+
+ if (m->flag & FB_MODE_IS_FIRST) {
+ md = m;
+ break;
+ }
+ }
+
+ /* first detailed timing is preferred */
+ if (specs->misc & FB_MISC_1ST_DETAIL) {
+ best = md;
+ goto finished;
+ }
+
+ /* find best mode based on display width and height */
+ if (specs->max_x && specs->max_y) {
+ struct fb_var_screeninfo var;
+
+ memset(&var, 0, sizeof(struct fb_var_screeninfo));
+ var.xres = (specs->max_x * 7200)/254;
+ var.yres = (specs->max_y * 7200)/254;
+ m = fb_find_best_mode(&var, head);
+ if (m) {
+ best = m;
+ goto finished;
+ }
+ }
+
+ /* use first detailed mode */
+ if (md) {
+ best = md;
+ goto finished;
+ }
+
+ /* last resort, use the very first mode */
+ best = m1;
+finished:
+ return best;
+}
+EXPORT_SYMBOL(fb_find_best_display);
+
EXPORT_SYMBOL(fb_videomode_to_var);
EXPORT_SYMBOL(fb_var_to_videomode);
EXPORT_SYMBOL(fb_mode_is_equal);
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 5d424a30270a..8486e77872dc 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1665,7 +1665,6 @@ static struct fb_ops neofb_ops = {
.fb_fillrect = neofb_fillrect,
.fb_copyarea = neofb_copyarea,
.fb_imageblit = neofb_imageblit,
- .fb_cursor = soft_cursor,
};
/* --------------------------------------------------------------------- */
diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
index afee284fc73c..4243d7fae972 100644
--- a/drivers/video/nvidia/nv_local.h
+++ b/drivers/video/nvidia/nv_local.h
@@ -105,7 +105,7 @@ do { \
*a = byte_rev[*a]; \
} while(0)
#else
-#define reverse_order(l)
+#define reverse_order(l) do { } while(0)
#endif /* __LITTLE_ENDIAN */
#endif /* __NV_LOCAL_H__ */
diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
index 4fa2cf9a8af2..7a03d040b1a3 100644
--- a/drivers/video/nvidia/nv_of.c
+++ b/drivers/video/nvidia/nv_of.c
@@ -27,34 +27,60 @@
#include "nv_local.h"
#include "nv_proto.h"
-void nvidia_create_i2c_busses(struct nvidia_par *par) {}
-void nvidia_delete_i2c_busses(struct nvidia_par *par) {}
+#include "../edid.h"
-int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid)
+int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid)
{
struct nvidia_par *par = info->par;
- struct device_node *dp;
+ struct device_node *parent, *dp;
unsigned char *pedid = NULL;
- unsigned char *disptype = NULL;
static char *propnames[] = {
- "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
+ "DFP,EDID", "LCD,EDID", "EDID", "EDID1",
+ "EDID,B", "EDID,A", NULL };
int i;
- dp = pci_device_to_OF_node(par->pci_dev);
- for (; dp != NULL; dp = dp->child) {
- disptype = (unsigned char *)get_property(dp, "display-type", NULL);
- if (disptype == NULL)
- continue;
- if (strncmp(disptype, "LCD", 3) != 0)
- continue;
+ parent = pci_device_to_OF_node(par->pci_dev);
+ if (parent == NULL)
+ return -1;
+ if (par->twoHeads) {
+ char *pname;
+ int len;
+
+ for (dp = NULL;
+ (dp = of_get_next_child(parent, dp)) != NULL;) {
+ pname = (char *)get_property(dp, "name", NULL);
+ if (!pname)
+ continue;
+ len = strlen(pname);
+ if ((pname[len-1] == 'A' && conn == 1) ||
+ (pname[len-1] == 'B' && conn == 2)) {
+ for (i = 0; propnames[i] != NULL; ++i) {
+ pedid = (unsigned char *)
+ get_property(dp, propnames[i],
+ NULL);
+ if (pedid != NULL)
+ break;
+ }
+ of_node_put(dp);
+ break;
+ }
+ }
+ }
+ if (pedid == NULL) {
for (i = 0; propnames[i] != NULL; ++i) {
pedid = (unsigned char *)
- get_property(dp, propnames[i], NULL);
- if (pedid != NULL) {
- *out_edid = pedid;
- return 0;
- }
+ get_property(parent, propnames[i], NULL);
+ if (pedid != NULL)
+ break;
}
}
- return 1;
+ if (pedid) {
+ *out_edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (*out_edid == NULL)
+ return -1;
+ memcpy(*out_edid, pedid, EDID_LENGTH);
+ printk(KERN_DEBUG "nvidiafb: Found OF EDID for head %d\n", conn);
+ return 0;
+ }
+ return -1;
}
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index cac44fc7f587..f60b1f432270 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -31,7 +31,7 @@ int NVShowHideCursor(struct nvidia_par *par, int);
void NVLockUnlock(struct nvidia_par *par, int);
/* in nvidia-i2c.c */
-#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
+#ifdef CONFIG_FB_NVIDIA_I2C
void nvidia_create_i2c_busses(struct nvidia_par *par);
void nvidia_delete_i2c_busses(struct nvidia_par *par);
int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
@@ -39,10 +39,18 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn,
#else
#define nvidia_create_i2c_busses(...)
#define nvidia_delete_i2c_busses(...)
-#define nvidia_probe_i2c_connector(p, c, edid) \
-do { \
- *(edid) = NULL; \
-} while(0)
+#define nvidia_probe_i2c_connector(p, c, edid) (-1)
+#endif
+
+#ifdef CONFIG_FB_OF
+int nvidia_probe_of_connector(struct fb_info *info, int conn,
+ u8 ** out_edid);
+#else
+static inline int nvidia_probe_of_connector(struct fb_info *info, int conn,
+ u8 ** out_edid)
+{
+ return -1;
+}
#endif
/* in nv_accel.c */
diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
index 11c84178f420..1f06a9f1bd0f 100644
--- a/drivers/video/nvidia/nv_setup.c
+++ b/drivers/video/nvidia/nv_setup.c
@@ -190,9 +190,9 @@ static int NVIsConnected(struct nvidia_par *par, int output)
present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
if (present)
- printk("nvidiafb: CRTC%i found\n", output);
+ printk("nvidiafb: CRTC%i analog found\n", output);
else
- printk("nvidiafb: CRTC%i not found\n", output);
+ printk("nvidiafb: CRTC%i analog not found\n", output);
NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
0x0000EFFF);
@@ -305,6 +305,9 @@ void NVCommonSetup(struct fb_info *info)
int FlatPanel = -1; /* really means the CRTC is slaved */
int Television = 0;
+ memset(&monitorA, 0, sizeof(struct fb_monspecs));
+ memset(&monitorB, 0, sizeof(struct fb_monspecs));
+
par->PRAMIN = par->REGS + (0x00710000 / 4);
par->PCRTC0 = par->REGS + (0x00600000 / 4);
par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
@@ -401,7 +404,8 @@ void NVCommonSetup(struct fb_info *info)
nvidia_create_i2c_busses(par);
if (!par->twoHeads) {
par->CRTCnumber = 0;
- nvidia_probe_i2c_connector(info, 1, &edidA);
+ if (nvidia_probe_i2c_connector(info, 1, &edidA))
+ nvidia_probe_of_connector(info, 1, &edidA);
if (edidA && !fb_parse_edid(edidA, &var)) {
printk("nvidiafb: EDID found from BUS1\n");
monA = &monitorA;
@@ -488,14 +492,16 @@ void NVCommonSetup(struct fb_info *info)
oldhead = NV_RD32(par->PCRTC0, 0x00000860);
NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
- nvidia_probe_i2c_connector(info, 1, &edidA);
+ if (nvidia_probe_i2c_connector(info, 1, &edidA))
+ nvidia_probe_of_connector(info, 1, &edidA);
if (edidA && !fb_parse_edid(edidA, &var)) {
printk("nvidiafb: EDID found from BUS1\n");
monA = &monitorA;
fb_edid_to_monspecs(edidA, monA);
}
- nvidia_probe_i2c_connector(info, 2, &edidB);
+ if (nvidia_probe_i2c_connector(info, 2, &edidB))
+ nvidia_probe_of_connector(info, 2, &edidB);
if (edidB && !fb_parse_edid(edidB, &var)) {
printk("nvidiafb: EDID found from BUS2\n");
monB = &monitorB;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 308defc389a2..0b40a2a721c1 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -411,6 +411,7 @@ MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
/* command line data, set in nvidiafb_setup() */
static int flatpanel __devinitdata = -1; /* Autodetect later */
+static int fpdither __devinitdata = -1;
static int forceCRTC __devinitdata = -1;
static int hwcur __devinitdata = 0;
static int noaccel __devinitdata = 0;
@@ -627,41 +628,85 @@ static void nvidia_save_vga(struct nvidia_par *par,
NVTRACE_LEAVE();
}
+#undef DUMP_REG
+
static void nvidia_write_regs(struct nvidia_par *par)
{
struct _riva_hw_state *state = &par->ModeReg;
int i;
NVTRACE_ENTER();
- NVWriteCrtc(par, 0x11, 0x00);
-
- NVLockUnlock(par, 0);
NVLoadStateExt(par, state);
NVWriteMiscOut(par, state->misc_output);
+ for (i = 1; i < NUM_SEQ_REGS; i++) {
+#ifdef DUMP_REG
+ printk(" SEQ[%02x] = %08x\n", i, state->seq[i]);
+#endif
+ NVWriteSeq(par, i, state->seq[i]);
+ }
+
+ /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
+ NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80);
+
for (i = 0; i < NUM_CRT_REGS; i++) {
switch (i) {
case 0x19:
case 0x20 ... 0x40:
break;
default:
+#ifdef DUMP_REG
+ printk("CRTC[%02x] = %08x\n", i, state->crtc[i]);
+#endif
NVWriteCrtc(par, i, state->crtc[i]);
}
}
- for (i = 0; i < NUM_ATC_REGS; i++)
- NVWriteAttr(par, i, state->attr[i]);
-
- for (i = 0; i < NUM_GRC_REGS; i++)
+ for (i = 0; i < NUM_GRC_REGS; i++) {
+#ifdef DUMP_REG
+ printk(" GRA[%02x] = %08x\n", i, state->gra[i]);
+#endif
NVWriteGr(par, i, state->gra[i]);
+ }
+
+ for (i = 0; i < NUM_ATC_REGS; i++) {
+#ifdef DUMP_REG
+ printk("ATTR[%02x] = %08x\n", i, state->attr[i]);
+#endif
+ NVWriteAttr(par, i, state->attr[i]);
+ }
- for (i = 0; i < NUM_SEQ_REGS; i++)
- NVWriteSeq(par, i, state->seq[i]);
NVTRACE_LEAVE();
}
+static void nvidia_vga_protect(struct nvidia_par *par, int on)
+{
+ unsigned char tmp;
+
+ if (on) {
+ /*
+ * Turn off screen and disable sequencer.
+ */
+ tmp = NVReadSeq(par, 0x01);
+
+ NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
+ NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
+ } else {
+ /*
+ * Reenable sequencer, then turn on screen.
+ */
+
+ tmp = NVReadSeq(par, 0x01);
+
+ NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
+ NVWriteSeq(par, 0x00, 0x03); /* End Reset */
+ }
+}
+
+
+
static int nvidia_calc_regs(struct fb_info *info)
{
struct nvidia_par *par = info->par;
@@ -868,7 +913,7 @@ static void nvidia_init_vga(struct fb_info *info)
for (i = 0; i < 0x10; i++)
state->attr[i] = i;
state->attr[0x10] = 0x41;
- state->attr[0x11] = 0x01;
+ state->attr[0x11] = 0xff;
state->attr[0x12] = 0x0f;
state->attr[0x13] = 0x00;
state->attr[0x14] = 0x00;
@@ -982,16 +1027,24 @@ static int nvidiafb_set_par(struct fb_info *info)
NVTRACE_ENTER();
NVLockUnlock(par, 1);
- if (!par->FlatPanel || (info->var.bits_per_pixel != 24) ||
- !par->twoHeads)
+ if (!par->FlatPanel || !par->twoHeads)
par->FPDither = 0;
+ if (par->FPDither < 0) {
+ if ((par->Chipset & 0x0ff0) == 0x0110)
+ par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528)
+ & 0x00010000);
+ else
+ par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1);
+ printk(KERN_INFO PFX "Flat panel dithering %s\n",
+ par->FPDither ? "enabled" : "disabled");
+ }
+
info->fix.visual = (info->var.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
nvidia_init_vga(info);
nvidia_calc_regs(info);
- nvidia_write_regs(par);
NVLockUnlock(par, 0);
if (par->twoHeads) {
@@ -1000,7 +1053,22 @@ static int nvidiafb_set_par(struct fb_info *info)
NVLockUnlock(par, 0);
}
- NVWriteCrtc(par, 0x11, 0x00);
+ nvidia_vga_protect(par, 1);
+
+ nvidia_write_regs(par);
+
+#if defined (__BIG_ENDIAN)
+ /* turn on LFB swapping */
+ {
+ unsigned char tmp;
+
+ VGA_WR08(par->PCIO, 0x3d4, 0x46);
+ tmp = VGA_RD08(par->PCIO, 0x3d5);
+ tmp |= (1 << 7);
+ VGA_WR08(par->PCIO, 0x3d5, tmp);
+ }
+#endif
+
info->fix.line_length = (info->var.xres_virtual *
info->var.bits_per_pixel) >> 3;
if (info->var.accel_flags) {
@@ -1022,7 +1090,7 @@ static int nvidiafb_set_par(struct fb_info *info)
par->cursor_reset = 1;
- NVWriteCrtc(par, 0x11, 0xff);
+ nvidia_vga_protect(par, 0);
NVTRACE_LEAVE();
return 0;
@@ -1315,22 +1383,10 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
fb_var_to_videomode(&modedb, &nvidiafb_default_var);
if (specs->modedb != NULL) {
- /* get preferred timing */
- if (specs->misc & FB_MISC_1ST_DETAIL) {
- int i;
-
- for (i = 0; i < specs->modedb_len; i++) {
- if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
- modedb = specs->modedb[i];
- break;
- }
- }
- } else {
- /* otherwise, get first mode in database */
- modedb = specs->modedb[0];
- }
+ struct fb_videomode *modedb;
- fb_videomode_to_var(&nvidiafb_default_var, &modedb);
+ modedb = fb_find_best_display(specs, &info->modelist);
+ fb_videomode_to_var(&nvidiafb_default_var, modedb);
nvidiafb_default_var.bits_per_pixel = 8;
} else if (par->fpWidth && par->fpHeight) {
char buf[16];
@@ -1365,7 +1421,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
info->pixmap.flags = FB_PIXMAP_SYSTEM;
if (!hwcur)
- info->fbops->fb_cursor = soft_cursor;
+ info->fbops->fb_cursor = NULL;
info->var.accel_flags = (!noaccel);
@@ -1490,9 +1546,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
par->FlatPanel = flatpanel;
-
if (flatpanel == 1)
printk(KERN_INFO PFX "flatpanel support enabled\n");
+ par->FPDither = fpdither;
par->CRTCnumber = forceCRTC;
par->FpScale = (!noscale);
@@ -1671,6 +1727,8 @@ static int __devinit nvidiafb_setup(char *options)
} else if (!strncmp(this_opt, "nomtrr", 6)) {
nomtrr = 1;
#endif
+ } else if (!strncmp(this_opt, "fpdither:", 9)) {
+ fpdither = simple_strtol(this_opt+9, NULL, 0);
} else
mode_option = this_opt;
}
@@ -1717,7 +1775,11 @@ module_exit(nvidiafb_exit);
module_param(flatpanel, int, 0);
MODULE_PARM_DESC(flatpanel,
"Enables experimental flat panel support for some chipsets. "
- "(0 or 1=enabled) (default=0)");
+ "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
+module_param(fpdither, int, 0);
+MODULE_PARM_DESC(fpdither,
+ "Enables dithering of flat panel for 6 bits panels. "
+ "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
module_param(hwcur, int, 0);
MODULE_PARM_DESC(hwcur,
"Enables hardware cursor implementation. (0 or 1=enabled) "
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 611922c0b22f..2c856838694e 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -85,7 +85,6 @@ static struct fb_ops offb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
/*
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index b76a5a9a125b..9aaf65fb623a 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -48,7 +48,6 @@ static struct fb_ops p9100_ops = {
.fb_imageblit = cfb_imageblit,
.fb_mmap = p9100_mmap,
.fb_ioctl = p9100_ioctl,
- .fb_cursor = soft_cursor,
};
/* P9100 control registers */
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index b00887e9851c..ca4082ae5a18 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -109,7 +109,6 @@ static struct fb_ops platinumfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
/*
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 42c17efa9fb0..0277ce031e5e 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -1034,7 +1034,6 @@ static struct fb_ops pm2fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
/*
@@ -1121,6 +1120,22 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
default_par->mem_control, default_par->boot_address,
default_par->mem_config);
+ if(default_par->mem_control == 0 &&
+ default_par->boot_address == 0x31 &&
+ default_par->mem_config == 0x259fffff &&
+ pdev->subsystem_vendor == 0x1048 &&
+ pdev->subsystem_device == 0x0a31) {
+ DPRINTK("subsystem_vendor: %04x, subsystem_device: %04x\n",
+ pdev->subsystem_vendor, pdev->subsystem_device);
+ DPRINTK("We have not been initialized by VGA BIOS "
+ "and are running on an Elsa Winner 2000 Office\n");
+ DPRINTK("Initializing card timings manually...\n");
+ default_par->mem_control=0;
+ default_par->boot_address=0x20;
+ default_par->mem_config=0xe6002021;
+ default_par->memclock=100000;
+ }
+
/* Now work out how big lfb is going to be. */
switch(default_par->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
case PM2F_MEM_BANKS_1:
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index c98f1c8d7dc2..f3927b6cda9d 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -128,7 +128,6 @@ static struct fb_ops pmagbafb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index a483b13e117b..25148de5fe67 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -132,7 +132,6 @@ static struct fb_ops pmagbbfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 31c547fd383b..ec4bacf9dd2e 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -230,7 +230,6 @@ static struct fb_ops pvr2fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static struct fb_videomode pvr2_modedb[] __initdata = {
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index efd9333b05c2..f305a5b77b23 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -418,7 +418,6 @@ static struct fb_ops pxafb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = pxafb_blank,
- .fb_cursor = soft_cursor,
.fb_mmap = pxafb_mmap,
};
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 8416b2e2b501..bfc41f2c902a 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -84,7 +84,6 @@ static struct fb_ops q40fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static int __init q40fb_probe(struct device *device)
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index a78b9bd8f897..600318f708f2 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -2218,7 +2218,6 @@ static struct fb_ops radeonfb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
#endif
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index f4437430dc5f..3edbd14c5c46 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -388,7 +388,6 @@ static struct fb_ops s1d13xxxfb_fbops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor
};
static int s1d13xxxfb_width_tab[2][4] __devinitdata = {
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 3cef90456a4b..855a6778b9eb 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -495,7 +495,6 @@ static struct fb_ops s3c2410fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
@@ -885,6 +884,7 @@ static int s3c2410fb_resume(struct device *dev)
static struct device_driver s3c2410fb_driver = {
.name = "s3c2410-lcd",
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
.probe = s3c2410fb_probe,
.suspend = s3c2410fb_suspend,
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index 3d35b28aaac7..a5184575cfae 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -853,7 +853,6 @@ static struct fb_ops sa1100fb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_blank = sa1100fb_blank,
- .fb_cursor = soft_cursor,
.fb_mmap = sa1100fb_mmap,
};
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index ea17f7e0482c..58cfdfb41833 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -169,6 +169,7 @@ struct savagefb_par {
struct savagefb_i2c_chan chan;
unsigned char *edid;
u32 pseudo_palette[16];
+ int paletteEnabled;
int pm_state;
int display_type;
int dvi;
@@ -244,105 +245,150 @@ struct savagefb_par {
/* IO functions */
+static inline u8 savage_in8(u32 addr, struct savagefb_par *par)
+{
+ return readb(par->mmio.vbase + addr);
+}
+
+static inline u16 savage_in16(u32 addr, struct savagefb_par *par)
+{
+ return readw(par->mmio.vbase + addr);
+}
+
+static inline u32 savage_in32(u32 addr, struct savagefb_par *par)
+{
+ return readl(par->mmio.vbase + addr);
+}
+
+static inline void savage_out8(u32 addr, u8 val, struct savagefb_par *par)
+{
+ writeb(val, par->mmio.vbase + addr);
+}
+
+static inline void savage_out16(u32 addr, u16 val, struct savagefb_par *par)
+{
+ writew(val, par->mmio.vbase + addr);
+}
+
+static inline void savage_out32(u32 addr, u32 val, struct savagefb_par *par)
+{
+ writel(val, par->mmio.vbase + addr);
+}
+
+static inline u8 vga_in8(int addr, struct savagefb_par *par)
+{
+ return savage_in8(0x8000 + addr, par);
+}
+
+static inline u16 vga_in16(int addr, struct savagefb_par *par)
+{
+ return savage_in16(0x8000 + addr, par);
+}
+
+static inline u8 vga_in32(int addr, struct savagefb_par *par)
+{
+ return savage_in32(0x8000 + addr, par);
+}
+
+static inline void vga_out8(int addr, u8 val, struct savagefb_par *par)
+{
+ savage_out8(0x8000 + addr, val, par);
+}
+
+static inline void vga_out16(int addr, u16 val, struct savagefb_par *par)
+{
+ savage_out16(0x8000 + addr, val, par);
+}
+
+static inline void vga_out32(int addr, u32 val, struct savagefb_par *par)
+{
+ savage_out32(0x8000 + addr, val, par);
+}
-#define vga_in8(addr) (inb (addr))
-#define vga_in16(addr) (inw (addr))
-#define vga_in32(addr) (inl (addr))
+static inline u8 VGArCR (u8 index, struct savagefb_par *par)
+{
+ vga_out8(0x3d4, index, par);
+ return vga_in8(0x3d5, par);
+}
+
+static inline u8 VGArGR (u8 index, struct savagefb_par *par)
+{
+ vga_out8(0x3ce, index, par);
+ return vga_in8(0x3cf, par);
+}
+
+static inline u8 VGArSEQ (u8 index, struct savagefb_par *par)
+{
+ vga_out8(0x3c4, index, par);
+ return vga_in8(0x3c5, par);
+}
-#define vga_out8(addr,val) (outb ((val), (addr)))
-#define vga_out16(addr,val) (outw ((val), (addr)))
-#define vga_out32(addr,val) (outl ((val), (addr)))
+static inline void VGAwCR(u8 index, u8 val, struct savagefb_par *par)
+{
+ vga_out8(0x3d4, index, par);
+ vga_out8(0x3d5, val, par);
+}
-#define savage_in16(addr) readw(par->mmio.vbase + (addr))
-#define savage_in32(addr) readl(par->mmio.vbase + (addr))
+static inline void VGAwGR(u8 index, u8 val, struct savagefb_par *par)
+{
+ vga_out8(0x3ce, index, par);
+ vga_out8(0x3cf, val, par);
+}
-#define savage_out16(addr,val) writew((val), par->mmio.vbase + (addr))
-#define savage_out32(addr,val) writel((val), par->mmio.vbase + (addr))
+static inline void VGAwSEQ(u8 index, u8 val, struct savagefb_par *par)
+{
+ vga_out8(0x3c4, index, par);
+ vga_out8 (0x3c5, val, par);
+}
-static inline u8 VGArCR (u8 index)
+static inline void VGAenablePalette(struct savagefb_par *par)
{
- outb (index, 0x3d4);
- return inb (0x3d5);
+ u8 tmp;
+
+ tmp = vga_in8(0x3da, par);
+ vga_out8(0x3c0, 0x00, par);
+ par->paletteEnabled = 1;
}
-static inline u8 VGArGR (u8 index)
+static inline void VGAdisablePalette(struct savagefb_par *par)
{
- outb (index, 0x3ce);
- return inb (0x3cf);
+ u8 tmp;
+
+ tmp = vga_in8(0x3da, par);
+ vga_out8(0x3c0, 0x20, par);
+ par->paletteEnabled = 0;
}
-static inline u8 VGArSEQ (u8 index)
+static inline void VGAwATTR(u8 index, u8 value, struct savagefb_par *par)
{
- outb (index, 0x3c4);
- return inb (0x3c5);
+ u8 tmp;
+
+ if (par->paletteEnabled)
+ index &= ~0x20;
+ else
+ index |= 0x20;
+
+ tmp = vga_in8(0x3da, par);
+ vga_out8(0x3c0, index, par);
+ vga_out8 (0x3c0, value, par);
}
-#define VGAwCR(index, val) \
-do { \
- vga_out8 (0x3d4, index); \
- vga_out8 (0x3d5, val); \
-} while (0)
-
-#define VGAwGR(index, val) \
-do { \
- vga_out8 (0x3ce, index); \
- vga_out8 (0x3cf, val); \
-} while (0)
-
-#define VGAwSEQ(index, val) \
-do { \
- vga_out8 (0x3c4, index); \
- vga_out8 (0x3c5, val); \
-} while (0)
-
-#define VGAenablePalette() \
-do { \
- u8 tmp; \
- \
- tmp = vga_in8 (0x3da); \
- vga_out8 (0x3c0, 0x00); \
- paletteEnabled = 1; \
-} while (0)
-
-#define VGAdisablePalette() \
-do { \
- u8 tmp; \
- \
- tmp = vga_in8 (0x3da); \
- vga_out8 (0x3c0, 0x20); \
- paletteEnabled = 0; \
-} while (0)
-
-#define VGAwATTR(index, value) \
-do { \
- u8 tmp; \
- \
- if (paletteEnabled) \
- index &= ~0x20; \
- else \
- index |= 0x20; \
- \
- tmp = vga_in8 (0x3da); \
- vga_out8 (0x3c0, index); \
- vga_out8 (0x3c0, value); \
-} while (0)
-
-#define VGAwMISC(value) \
-do { \
- vga_out8 (0x3c2, value); \
-} while (0)
+static inline void VGAwMISC(u8 value, struct savagefb_par *par)
+{
+ vga_out8(0x3c2, value, par);
+}
#ifndef CONFIG_FB_SAVAGE_ACCEL
#define savagefb_set_clip(x)
#endif
-#define VerticalRetraceWait() \
-{ \
- vga_out8 (0x3d4, 0x17); \
- if (vga_in8 (0x3d5) & 0x80) { \
- while ((vga_in8(0x3da) & 0x08) == 0x08) ; \
- while ((vga_in8(0x3da) & 0x08) == 0x00) ; \
- } \
+static inline void VerticalRetraceWait(struct savagefb_par *par)
+{
+ vga_out8(0x3d4, 0x17, par);
+ if (vga_in8(0x3d5, par) & 0x80) {
+ while ((vga_in8(0x3da, par) & 0x08) == 0x08);
+ while ((vga_in8(0x3da, par) & 0x08) == 0x00);
+ }
}
extern int savagefb_probe_i2c_connector(struct fb_info *info,
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 7c285455c924..f0dfb35e3191 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -74,7 +74,6 @@
static char *mode_option __initdata = NULL;
-static int paletteEnabled = 0;
#ifdef MODULE
@@ -90,9 +89,9 @@ MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");
static void vgaHWSeqReset (struct savagefb_par *par, int start)
{
if (start)
- VGAwSEQ (0x00, 0x01); /* Synchronous Reset */
+ VGAwSEQ (0x00, 0x01, par); /* Synchronous Reset */
else
- VGAwSEQ (0x00, 0x03); /* End Reset */
+ VGAwSEQ (0x00, 0x03, par); /* End Reset */
}
static void vgaHWProtect (struct savagefb_par *par, int on)
@@ -103,23 +102,23 @@ static void vgaHWProtect (struct savagefb_par *par, int on)
/*
* Turn off screen and disable sequencer.
*/
- tmp = VGArSEQ (0x01);
+ tmp = VGArSEQ (0x01, par);
vgaHWSeqReset (par, 1); /* start synchronous reset */
- VGAwSEQ (0x01, tmp | 0x20); /* disable the display */
+ VGAwSEQ (0x01, tmp | 0x20, par);/* disable the display */
- VGAenablePalette();
+ VGAenablePalette(par);
} else {
/*
* Reenable sequencer, then turn on screen.
*/
- tmp = VGArSEQ (0x01);
+ tmp = VGArSEQ (0x01, par);
- VGAwSEQ (0x01, tmp & ~0x20); /* reenable display */
+ VGAwSEQ (0x01, tmp & ~0x20, par);/* reenable display */
vgaHWSeqReset (par, 0); /* clear synchronous reset */
- VGAdisablePalette();
+ VGAdisablePalette(par);
}
}
@@ -127,27 +126,27 @@ static void vgaHWRestore (struct savagefb_par *par)
{
int i;
- VGAwMISC (par->MiscOutReg);
+ VGAwMISC (par->MiscOutReg, par);
for (i = 1; i < 5; i++)
- VGAwSEQ (i, par->Sequencer[i]);
+ VGAwSEQ (i, par->Sequencer[i], par);
/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
CRTC[17] */
- VGAwCR (17, par->CRTC[17] & ~0x80);
+ VGAwCR (17, par->CRTC[17] & ~0x80, par);
for (i = 0; i < 25; i++)
- VGAwCR (i, par->CRTC[i]);
+ VGAwCR (i, par->CRTC[i], par);
for (i = 0; i < 9; i++)
- VGAwGR (i, par->Graphics[i]);
+ VGAwGR (i, par->Graphics[i], par);
- VGAenablePalette();
+ VGAenablePalette(par);
for (i = 0; i < 21; i++)
- VGAwATTR (i, par->Attribute[i]);
+ VGAwATTR (i, par->Attribute[i], par);
- VGAdisablePalette();
+ VGAdisablePalette(par);
}
static void vgaHWInit (struct fb_var_screeninfo *var,
@@ -267,7 +266,7 @@ savage3D_waitfifo(struct savagefb_par *par, int space)
{
int slots = MAXFIFO - space;
- while ((savage_in32(0x48C00) & 0x0000ffff) > slots);
+ while ((savage_in32(0x48C00, par) & 0x0000ffff) > slots);
}
static void
@@ -275,7 +274,7 @@ savage4_waitfifo(struct savagefb_par *par, int space)
{
int slots = MAXFIFO - space;
- while ((savage_in32(0x48C60) & 0x001fffff) > slots);
+ while ((savage_in32(0x48C60, par) & 0x001fffff) > slots);
}
static void
@@ -283,26 +282,26 @@ savage2000_waitfifo(struct savagefb_par *par, int space)
{
int slots = MAXFIFO - space;
- while ((savage_in32(0x48C60) & 0x0000ffff) > slots);
+ while ((savage_in32(0x48C60, par) & 0x0000ffff) > slots);
}
/* Wait for idle accelerator */
static void
savage3D_waitidle(struct savagefb_par *par)
{
- while ((savage_in32(0x48C00) & 0x0008ffff) != 0x80000);
+ while ((savage_in32(0x48C00, par) & 0x0008ffff) != 0x80000);
}
static void
savage4_waitidle(struct savagefb_par *par)
{
- while ((savage_in32(0x48C60) & 0x00a00000) != 0x00a00000);
+ while ((savage_in32(0x48C60, par) & 0x00a00000) != 0x00a00000);
}
static void
savage2000_waitidle(struct savagefb_par *par)
{
- while ((savage_in32(0x48C60) & 0x009fffff));
+ while ((savage_in32(0x48C60, par) & 0x009fffff));
}
@@ -319,59 +318,64 @@ SavageSetup2DEngine (struct savagefb_par *par)
case S3_SAVAGE3D:
case S3_SAVAGE_MX:
/* Disable BCI */
- savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
+ savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
/* Setup BCI command overflow buffer */
- savage_out32(0x48C14, (par->cob_offset >> 11) | (par->cob_index << 29));
+ savage_out32(0x48C14,
+ (par->cob_offset >> 11) | (par->cob_index << 29),
+ par);
/* Program shadow status update. */
- savage_out32(0x48C10, 0x78207220);
- savage_out32(0x48C0C, 0);
+ savage_out32(0x48C10, 0x78207220, par);
+ savage_out32(0x48C0C, 0, par);
/* Enable BCI and command overflow buffer */
- savage_out32(0x48C18, savage_in32(0x48C18) | 0x0C);
+ savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par);
break;
case S3_SAVAGE4:
case S3_PROSAVAGE:
case S3_SUPERSAVAGE:
/* Disable BCI */
- savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
+ savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
/* Program shadow status update */
- savage_out32(0x48C10, 0x00700040);
- savage_out32(0x48C0C, 0);
+ savage_out32(0x48C10, 0x00700040, par);
+ savage_out32(0x48C0C, 0, par);
/* Enable BCI without the COB */
- savage_out32(0x48C18, savage_in32(0x48C18) | 0x08);
+ savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x08, par);
break;
case S3_SAVAGE2000:
/* Disable BCI */
- savage_out32(0x48C18, 0);
+ savage_out32(0x48C18, 0, par);
/* Setup BCI command overflow buffer */
- savage_out32(0x48C18, (par->cob_offset >> 7) | (par->cob_index));
+ savage_out32(0x48C18,
+ (par->cob_offset >> 7) | (par->cob_index),
+ par);
/* Disable shadow status update */
- savage_out32(0x48A30, 0);
+ savage_out32(0x48A30, 0, par);
/* Enable BCI and command overflow buffer */
- savage_out32(0x48C18, savage_in32(0x48C18) | 0x00280000 );
+ savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x00280000,
+ par);
break;
default:
break;
}
/* Turn on 16-bit register access. */
- vga_out8(0x3d4, 0x31);
- vga_out8(0x3d5, 0x0c);
+ vga_out8(0x3d4, 0x31, par);
+ vga_out8(0x3d5, 0x0c, par);
/* Set stride to use GBD. */
- vga_out8 (0x3d4, 0x50);
- vga_out8 (0x3d5, vga_in8 (0x3d5 ) | 0xC1);
+ vga_out8 (0x3d4, 0x50, par);
+ vga_out8 (0x3d5, vga_in8(0x3d5, par) | 0xC1, par);
/* Enable 2D engine. */
- vga_out8 (0x3d4, 0x40 );
- vga_out8 (0x3d5, 0x01 );
+ vga_out8 (0x3d4, 0x40, par);
+ vga_out8 (0x3d5, 0x01, par);
- savage_out32 (MONO_PAT_0, ~0);
- savage_out32 (MONO_PAT_1, ~0);
+ savage_out32 (MONO_PAT_0, ~0, par);
+ savage_out32 (MONO_PAT_1, ~0, par);
/* Setup plane masks */
- savage_out32 (0x8128, ~0 ); /* enable all write planes */
- savage_out32 (0x812C, ~0 ); /* enable all read planes */
- savage_out16 (0x8134, 0x27 );
- savage_out16 (0x8136, 0x07 );
+ savage_out32 (0x8128, ~0, par); /* enable all write planes */
+ savage_out32 (0x812C, ~0, par); /* enable all read planes */
+ savage_out16 (0x8134, 0x27, par);
+ savage_out16 (0x8136, 0x07, par);
/* Now set the GBD */
par->bci_ptr = 0;
@@ -489,8 +493,8 @@ static void SavagePrintRegs(void)
for( i = 0; i < 0x70; i++ ) {
if( !(i % 16) )
printk(KERN_DEBUG "\nSR%xx ", i >> 4 );
- vga_out8( 0x3c4, i );
- printk(KERN_DEBUG " %02x", vga_in8(0x3c5) );
+ vga_out8( 0x3c4, i, par);
+ printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par) );
}
printk(KERN_DEBUG "\n\nCR x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
@@ -499,8 +503,8 @@ static void SavagePrintRegs(void)
for( i = 0; i < 0xB7; i++ ) {
if( !(i % 16) )
printk(KERN_DEBUG "\nCR%xx ", i >> 4 );
- vga_out8( vgaCRIndex, i );
- printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg) );
+ vga_out8( vgaCRIndex, i, par);
+ printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par) );
}
printk(KERN_DEBUG "\n\n");
@@ -513,152 +517,152 @@ static void savage_get_default_par(struct savagefb_par *par)
{
unsigned char cr3a, cr53, cr66;
- vga_out16 (0x3d4, 0x4838);
- vga_out16 (0x3d4, 0xa039);
- vga_out16 (0x3c4, 0x0608);
-
- vga_out8 (0x3d4, 0x66);
- cr66 = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr66 | 0x80);
- vga_out8 (0x3d4, 0x3a);
- cr3a = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr3a | 0x80);
- vga_out8 (0x3d4, 0x53);
- cr53 = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr53 & 0x7f);
-
- vga_out8 (0x3d4, 0x66);
- vga_out8 (0x3d5, cr66);
- vga_out8 (0x3d4, 0x3a);
- vga_out8 (0x3d5, cr3a);
-
- vga_out8 (0x3d4, 0x66);
- vga_out8 (0x3d5, cr66);
- vga_out8 (0x3d4, 0x3a);
- vga_out8 (0x3d5, cr3a);
+ vga_out16 (0x3d4, 0x4838, par);
+ vga_out16 (0x3d4, 0xa039, par);
+ vga_out16 (0x3c4, 0x0608, par);
+
+ vga_out8 (0x3d4, 0x66, par);
+ cr66 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr66 | 0x80, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ cr3a = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr3a | 0x80, par);
+ vga_out8 (0x3d4, 0x53, par);
+ cr53 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr53 & 0x7f, par);
+
+ vga_out8 (0x3d4, 0x66, par);
+ vga_out8 (0x3d5, cr66, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ vga_out8 (0x3d5, cr3a, par);
+
+ vga_out8 (0x3d4, 0x66, par);
+ vga_out8 (0x3d5, cr66, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ vga_out8 (0x3d5, cr3a, par);
/* unlock extended seq regs */
- vga_out8 (0x3c4, 0x08);
- par->SR08 = vga_in8 (0x3c5);
- vga_out8 (0x3c5, 0x06);
+ vga_out8 (0x3c4, 0x08, par);
+ par->SR08 = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c5, 0x06, par);
/* now save all the extended regs we need */
- vga_out8 (0x3d4, 0x31);
- par->CR31 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x32);
- par->CR32 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x34);
- par->CR34 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x36);
- par->CR36 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x3a);
- par->CR3A = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x40);
- par->CR40 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x42);
- par->CR42 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x45);
- par->CR45 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x50);
- par->CR50 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x51);
- par->CR51 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x53);
- par->CR53 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x58);
- par->CR58 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x60);
- par->CR60 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x66);
- par->CR66 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x67);
- par->CR67 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x68);
- par->CR68 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x69);
- par->CR69 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x6f);
- par->CR6F = vga_in8 (0x3d5);
-
- vga_out8 (0x3d4, 0x33);
- par->CR33 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x86);
- par->CR86 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x88);
- par->CR88 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x90);
- par->CR90 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x91);
- par->CR91 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0xb0);
- par->CRB0 = vga_in8 (0x3d5) | 0x80;
+ vga_out8 (0x3d4, 0x31, par);
+ par->CR31 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x32, par);
+ par->CR32 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x34, par);
+ par->CR34 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x36, par);
+ par->CR36 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ par->CR3A = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x40, par);
+ par->CR40 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x42, par);
+ par->CR42 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x45, par);
+ par->CR45 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x50, par);
+ par->CR50 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x51, par);
+ par->CR51 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x53, par);
+ par->CR53 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x58, par);
+ par->CR58 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x60, par);
+ par->CR60 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x66, par);
+ par->CR66 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x67, par);
+ par->CR67 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x68, par);
+ par->CR68 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x69, par);
+ par->CR69 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x6f, par);
+ par->CR6F = vga_in8 (0x3d5, par);
+
+ vga_out8 (0x3d4, 0x33, par);
+ par->CR33 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x86, par);
+ par->CR86 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x88, par);
+ par->CR88 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x90, par);
+ par->CR90 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x91, par);
+ par->CR91 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0xb0, par);
+ par->CRB0 = vga_in8 (0x3d5, par) | 0x80;
/* extended mode timing regs */
- vga_out8 (0x3d4, 0x3b);
- par->CR3B = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x3c);
- par->CR3C = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x43);
- par->CR43 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x5d);
- par->CR5D = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x5e);
- par->CR5E = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x65);
- par->CR65 = vga_in8 (0x3d5);
+ vga_out8 (0x3d4, 0x3b, par);
+ par->CR3B = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x3c, par);
+ par->CR3C = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x43, par);
+ par->CR43 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x5d, par);
+ par->CR5D = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x5e, par);
+ par->CR5E = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x65, par);
+ par->CR65 = vga_in8 (0x3d5, par);
/* save seq extended regs for DCLK PLL programming */
- vga_out8 (0x3c4, 0x0e);
- par->SR0E = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x0f);
- par->SR0F = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x10);
- par->SR10 = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x11);
- par->SR11 = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x12);
- par->SR12 = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x13);
- par->SR13 = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x29);
- par->SR29 = vga_in8 (0x3c5);
-
- vga_out8 (0x3c4, 0x15);
- par->SR15 = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x30);
- par->SR30 = vga_in8 (0x3c5);
- vga_out8 (0x3c4, 0x18);
- par->SR18 = vga_in8 (0x3c5);
+ vga_out8 (0x3c4, 0x0e, par);
+ par->SR0E = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x0f, par);
+ par->SR0F = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x10, par);
+ par->SR10 = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x11, par);
+ par->SR11 = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x12, par);
+ par->SR12 = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x13, par);
+ par->SR13 = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x29, par);
+ par->SR29 = vga_in8 (0x3c5, par);
+
+ vga_out8 (0x3c4, 0x15, par);
+ par->SR15 = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x30, par);
+ par->SR30 = vga_in8 (0x3c5, par);
+ vga_out8 (0x3c4, 0x18, par);
+ par->SR18 = vga_in8 (0x3c5, par);
/* Save flat panel expansion regsters. */
if (par->chip == S3_SAVAGE_MX) {
int i;
for (i = 0; i < 8; i++) {
- vga_out8 (0x3c4, 0x54+i);
- par->SR54[i] = vga_in8 (0x3c5);
+ vga_out8 (0x3c4, 0x54+i, par);
+ par->SR54[i] = vga_in8 (0x3c5, par);
}
}
- vga_out8 (0x3d4, 0x66);
- cr66 = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr66 | 0x80);
- vga_out8 (0x3d4, 0x3a);
- cr3a = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr3a | 0x80);
+ vga_out8 (0x3d4, 0x66, par);
+ cr66 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr66 | 0x80, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ cr3a = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr3a | 0x80, par);
/* now save MIU regs */
if (par->chip != S3_SAVAGE_MX) {
- par->MMPR0 = savage_in32(FIFO_CONTROL_REG);
- par->MMPR1 = savage_in32(MIU_CONTROL_REG);
- par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG);
- par->MMPR3 = savage_in32(MISC_TIMEOUT_REG);
+ par->MMPR0 = savage_in32(FIFO_CONTROL_REG, par);
+ par->MMPR1 = savage_in32(MIU_CONTROL_REG, par);
+ par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par);
+ par->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par);
}
- vga_out8 (0x3d4, 0x3a);
- vga_out8 (0x3d5, cr3a);
- vga_out8 (0x3d4, 0x66);
- vga_out8 (0x3d5, cr66);
+ vga_out8 (0x3d4, 0x3a, par);
+ vga_out8 (0x3d5, cr3a, par);
+ vga_out8 (0x3d4, 0x66, par);
+ vga_out8 (0x3d5, cr66, par);
}
static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
@@ -868,8 +872,8 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var,
* match. Fall back to traditional register-crunching.
*/
- vga_out8 (0x3d4, 0x3a);
- tmp = vga_in8 (0x3d5);
+ vga_out8 (0x3d4, 0x3a, par);
+ tmp = vga_in8 (0x3d5, par);
if (1 /*FIXME:psav->pci_burst*/)
par->CR3A = (tmp & 0x7f) | 0x15;
else
@@ -879,16 +883,16 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var,
par->CR31 = 0x8c;
par->CR66 = 0x89;
- vga_out8 (0x3d4, 0x58);
- par->CR58 = vga_in8 (0x3d5) & 0x80;
+ vga_out8 (0x3d4, 0x58, par);
+ par->CR58 = vga_in8 (0x3d5, par) & 0x80;
par->CR58 |= 0x13;
par->SR15 = 0x03 | 0x80;
par->SR18 = 0x00;
par->CR43 = par->CR45 = par->CR65 = 0x00;
- vga_out8 (0x3d4, 0x40);
- par->CR40 = vga_in8 (0x3d5) & ~0x01;
+ vga_out8 (0x3d4, 0x40, par);
+ par->CR40 = vga_in8 (0x3d5, par) & ~0x01;
par->MMPR0 = 0x010400;
par->MMPR1 = 0x00;
@@ -992,19 +996,19 @@ static int savagefb_decode_var (struct fb_var_screeninfo *var,
par->CR67 |= 1;
- vga_out8(0x3d4, 0x36);
- par->CR36 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x68);
- par->CR68 = vga_in8 (0x3d5);
+ vga_out8(0x3d4, 0x36, par);
+ par->CR36 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x68, par);
+ par->CR68 = vga_in8 (0x3d5, par);
par->CR69 = 0;
- vga_out8 (0x3d4, 0x6f);
- par->CR6F = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x86);
- par->CR86 = vga_in8 (0x3d5);
- vga_out8 (0x3d4, 0x88);
- par->CR88 = vga_in8 (0x3d5) | 0x08;
- vga_out8 (0x3d4, 0xb0);
- par->CRB0 = vga_in8 (0x3d5) | 0x80;
+ vga_out8 (0x3d4, 0x6f, par);
+ par->CR6F = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x86, par);
+ par->CR86 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d4, 0x88, par);
+ par->CR88 = vga_in8 (0x3d5, par) | 0x08;
+ vga_out8 (0x3d4, 0xb0, par);
+ par->CRB0 = vga_in8 (0x3d5, par) | 0x80;
return 0;
}
@@ -1033,11 +1037,11 @@ static int savagefb_setcolreg(unsigned regno,
switch (info->var.bits_per_pixel) {
case 8:
- vga_out8 (0x3c8, regno);
+ vga_out8 (0x3c8, regno, par);
- vga_out8 (0x3c9, red >> 10);
- vga_out8 (0x3c9, green >> 10);
- vga_out8 (0x3c9, blue >> 10);
+ vga_out8 (0x3c9, red >> 10, par);
+ vga_out8 (0x3c9, green >> 10, par);
+ vga_out8 (0x3c9, blue >> 10, par);
break;
case 16:
@@ -1079,11 +1083,11 @@ static void savagefb_set_par_int (struct savagefb_par *par)
par->SavageWaitIdle (par);
- vga_out8 (0x3c2, 0x23);
+ vga_out8 (0x3c2, 0x23, par);
- vga_out16 (0x3d4, 0x4838);
- vga_out16 (0x3d4, 0xa539);
- vga_out16 (0x3c4, 0x0608);
+ vga_out16 (0x3d4, 0x4838, par);
+ vga_out16 (0x3d4, 0xa539, par);
+ vga_out16 (0x3c4, 0x0608, par);
vgaHWProtect (par, 1);
@@ -1094,197 +1098,197 @@ static void savagefb_set_par_int (struct savagefb_par *par)
* switch to mode 3 here seems to eliminate the issue.
*/
- VerticalRetraceWait();
- vga_out8 (0x3d4, 0x67);
- cr67 = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c); /* no STREAMS yet */
+ VerticalRetraceWait(par);
+ vga_out8 (0x3d4, 0x67, par);
+ cr67 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */
- vga_out8 (0x3d4, 0x23);
- vga_out8 (0x3d5, 0x00);
- vga_out8 (0x3d4, 0x26);
- vga_out8 (0x3d5, 0x00);
+ vga_out8 (0x3d4, 0x23, par);
+ vga_out8 (0x3d5, 0x00, par);
+ vga_out8 (0x3d4, 0x26, par);
+ vga_out8 (0x3d5, 0x00, par);
/* restore extended regs */
- vga_out8 (0x3d4, 0x66);
- vga_out8 (0x3d5, par->CR66);
- vga_out8 (0x3d4, 0x3a);
- vga_out8 (0x3d5, par->CR3A);
- vga_out8 (0x3d4, 0x31);
- vga_out8 (0x3d5, par->CR31);
- vga_out8 (0x3d4, 0x32);
- vga_out8 (0x3d5, par->CR32);
- vga_out8 (0x3d4, 0x58);
- vga_out8 (0x3d5, par->CR58);
- vga_out8 (0x3d4, 0x53);
- vga_out8 (0x3d5, par->CR53 & 0x7f);
-
- vga_out16 (0x3c4, 0x0608);
+ vga_out8 (0x3d4, 0x66, par);
+ vga_out8 (0x3d5, par->CR66, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ vga_out8 (0x3d5, par->CR3A, par);
+ vga_out8 (0x3d4, 0x31, par);
+ vga_out8 (0x3d5, par->CR31, par);
+ vga_out8 (0x3d4, 0x32, par);
+ vga_out8 (0x3d5, par->CR32, par);
+ vga_out8 (0x3d4, 0x58, par);
+ vga_out8 (0x3d5, par->CR58, par);
+ vga_out8 (0x3d4, 0x53, par);
+ vga_out8 (0x3d5, par->CR53 & 0x7f, par);
+
+ vga_out16 (0x3c4, 0x0608, par);
/* Restore DCLK registers. */
- vga_out8 (0x3c4, 0x0e);
- vga_out8 (0x3c5, par->SR0E);
- vga_out8 (0x3c4, 0x0f);
- vga_out8 (0x3c5, par->SR0F);
- vga_out8 (0x3c4, 0x29);
- vga_out8 (0x3c5, par->SR29);
- vga_out8 (0x3c4, 0x15);
- vga_out8 (0x3c5, par->SR15);
+ vga_out8 (0x3c4, 0x0e, par);
+ vga_out8 (0x3c5, par->SR0E, par);
+ vga_out8 (0x3c4, 0x0f, par);
+ vga_out8 (0x3c5, par->SR0F, par);
+ vga_out8 (0x3c4, 0x29, par);
+ vga_out8 (0x3c5, par->SR29, par);
+ vga_out8 (0x3c4, 0x15, par);
+ vga_out8 (0x3c5, par->SR15, par);
/* Restore flat panel expansion regsters. */
if( par->chip == S3_SAVAGE_MX ) {
int i;
for( i = 0; i < 8; i++ ) {
- vga_out8 (0x3c4, 0x54+i);
- vga_out8 (0x3c5, par->SR54[i]);
+ vga_out8 (0x3c4, 0x54+i, par);
+ vga_out8 (0x3c5, par->SR54[i], par);
}
}
vgaHWRestore (par);
/* extended mode timing registers */
- vga_out8 (0x3d4, 0x53);
- vga_out8 (0x3d5, par->CR53);
- vga_out8 (0x3d4, 0x5d);
- vga_out8 (0x3d5, par->CR5D);
- vga_out8 (0x3d4, 0x5e);
- vga_out8 (0x3d5, par->CR5E);
- vga_out8 (0x3d4, 0x3b);
- vga_out8 (0x3d5, par->CR3B);
- vga_out8 (0x3d4, 0x3c);
- vga_out8 (0x3d5, par->CR3C);
- vga_out8 (0x3d4, 0x43);
- vga_out8 (0x3d5, par->CR43);
- vga_out8 (0x3d4, 0x65);
- vga_out8 (0x3d5, par->CR65);
+ vga_out8 (0x3d4, 0x53, par);
+ vga_out8 (0x3d5, par->CR53, par);
+ vga_out8 (0x3d4, 0x5d, par);
+ vga_out8 (0x3d5, par->CR5D, par);
+ vga_out8 (0x3d4, 0x5e, par);
+ vga_out8 (0x3d5, par->CR5E, par);
+ vga_out8 (0x3d4, 0x3b, par);
+ vga_out8 (0x3d5, par->CR3B, par);
+ vga_out8 (0x3d4, 0x3c, par);
+ vga_out8 (0x3d5, par->CR3C, par);
+ vga_out8 (0x3d4, 0x43, par);
+ vga_out8 (0x3d5, par->CR43, par);
+ vga_out8 (0x3d4, 0x65, par);
+ vga_out8 (0x3d5, par->CR65, par);
/* restore the desired video mode with cr67 */
- vga_out8 (0x3d4, 0x67);
+ vga_out8 (0x3d4, 0x67, par);
/* following part not present in X11 driver */
- cr67 = vga_in8 (0x3d5) & 0xf;
- vga_out8 (0x3d5, 0x50 | cr67);
+ cr67 = vga_in8 (0x3d5, par) & 0xf;
+ vga_out8 (0x3d5, 0x50 | cr67, par);
udelay (10000);
- vga_out8 (0x3d4, 0x67);
+ vga_out8 (0x3d4, 0x67, par);
/* end of part */
- vga_out8 (0x3d5, par->CR67 & ~0x0c);
+ vga_out8 (0x3d5, par->CR67 & ~0x0c, par);
/* other mode timing and extended regs */
- vga_out8 (0x3d4, 0x34);
- vga_out8 (0x3d5, par->CR34);
- vga_out8 (0x3d4, 0x40);
- vga_out8 (0x3d5, par->CR40);
- vga_out8 (0x3d4, 0x42);
- vga_out8 (0x3d5, par->CR42);
- vga_out8 (0x3d4, 0x45);
- vga_out8 (0x3d5, par->CR45);
- vga_out8 (0x3d4, 0x50);
- vga_out8 (0x3d5, par->CR50);
- vga_out8 (0x3d4, 0x51);
- vga_out8 (0x3d5, par->CR51);
+ vga_out8 (0x3d4, 0x34, par);
+ vga_out8 (0x3d5, par->CR34, par);
+ vga_out8 (0x3d4, 0x40, par);
+ vga_out8 (0x3d5, par->CR40, par);
+ vga_out8 (0x3d4, 0x42, par);
+ vga_out8 (0x3d5, par->CR42, par);
+ vga_out8 (0x3d4, 0x45, par);
+ vga_out8 (0x3d5, par->CR45, par);
+ vga_out8 (0x3d4, 0x50, par);
+ vga_out8 (0x3d5, par->CR50, par);
+ vga_out8 (0x3d4, 0x51, par);
+ vga_out8 (0x3d5, par->CR51, par);
/* memory timings */
- vga_out8 (0x3d4, 0x36);
- vga_out8 (0x3d5, par->CR36);
- vga_out8 (0x3d4, 0x60);
- vga_out8 (0x3d5, par->CR60);
- vga_out8 (0x3d4, 0x68);
- vga_out8 (0x3d5, par->CR68);
- vga_out8 (0x3d4, 0x69);
- vga_out8 (0x3d5, par->CR69);
- vga_out8 (0x3d4, 0x6f);
- vga_out8 (0x3d5, par->CR6F);
-
- vga_out8 (0x3d4, 0x33);
- vga_out8 (0x3d5, par->CR33);
- vga_out8 (0x3d4, 0x86);
- vga_out8 (0x3d5, par->CR86);
- vga_out8 (0x3d4, 0x88);
- vga_out8 (0x3d5, par->CR88);
- vga_out8 (0x3d4, 0x90);
- vga_out8 (0x3d5, par->CR90);
- vga_out8 (0x3d4, 0x91);
- vga_out8 (0x3d5, par->CR91);
+ vga_out8 (0x3d4, 0x36, par);
+ vga_out8 (0x3d5, par->CR36, par);
+ vga_out8 (0x3d4, 0x60, par);
+ vga_out8 (0x3d5, par->CR60, par);
+ vga_out8 (0x3d4, 0x68, par);
+ vga_out8 (0x3d5, par->CR68, par);
+ vga_out8 (0x3d4, 0x69, par);
+ vga_out8 (0x3d5, par->CR69, par);
+ vga_out8 (0x3d4, 0x6f, par);
+ vga_out8 (0x3d5, par->CR6F, par);
+
+ vga_out8 (0x3d4, 0x33, par);
+ vga_out8 (0x3d5, par->CR33, par);
+ vga_out8 (0x3d4, 0x86, par);
+ vga_out8 (0x3d5, par->CR86, par);
+ vga_out8 (0x3d4, 0x88, par);
+ vga_out8 (0x3d5, par->CR88, par);
+ vga_out8 (0x3d4, 0x90, par);
+ vga_out8 (0x3d5, par->CR90, par);
+ vga_out8 (0x3d4, 0x91, par);
+ vga_out8 (0x3d5, par->CR91, par);
if (par->chip == S3_SAVAGE4) {
- vga_out8 (0x3d4, 0xb0);
- vga_out8 (0x3d5, par->CRB0);
+ vga_out8 (0x3d4, 0xb0, par);
+ vga_out8 (0x3d5, par->CRB0, par);
}
- vga_out8 (0x3d4, 0x32);
- vga_out8 (0x3d5, par->CR32);
+ vga_out8 (0x3d4, 0x32, par);
+ vga_out8 (0x3d5, par->CR32, par);
/* unlock extended seq regs */
- vga_out8 (0x3c4, 0x08);
- vga_out8 (0x3c5, 0x06);
+ vga_out8 (0x3c4, 0x08, par);
+ vga_out8 (0x3c5, 0x06, par);
/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
* that we should leave the default SR10 and SR11 values there.
*/
if (par->SR10 != 255) {
- vga_out8 (0x3c4, 0x10);
- vga_out8 (0x3c5, par->SR10);
- vga_out8 (0x3c4, 0x11);
- vga_out8 (0x3c5, par->SR11);
+ vga_out8 (0x3c4, 0x10, par);
+ vga_out8 (0x3c5, par->SR10, par);
+ vga_out8 (0x3c4, 0x11, par);
+ vga_out8 (0x3c5, par->SR11, par);
}
/* restore extended seq regs for dclk */
- vga_out8 (0x3c4, 0x0e);
- vga_out8 (0x3c5, par->SR0E);
- vga_out8 (0x3c4, 0x0f);
- vga_out8 (0x3c5, par->SR0F);
- vga_out8 (0x3c4, 0x12);
- vga_out8 (0x3c5, par->SR12);
- vga_out8 (0x3c4, 0x13);
- vga_out8 (0x3c5, par->SR13);
- vga_out8 (0x3c4, 0x29);
- vga_out8 (0x3c5, par->SR29);
-
- vga_out8 (0x3c4, 0x18);
- vga_out8 (0x3c5, par->SR18);
+ vga_out8 (0x3c4, 0x0e, par);
+ vga_out8 (0x3c5, par->SR0E, par);
+ vga_out8 (0x3c4, 0x0f, par);
+ vga_out8 (0x3c5, par->SR0F, par);
+ vga_out8 (0x3c4, 0x12, par);
+ vga_out8 (0x3c5, par->SR12, par);
+ vga_out8 (0x3c4, 0x13, par);
+ vga_out8 (0x3c5, par->SR13, par);
+ vga_out8 (0x3c4, 0x29, par);
+ vga_out8 (0x3c5, par->SR29, par);
+
+ vga_out8 (0x3c4, 0x18, par);
+ vga_out8 (0x3c5, par->SR18, par);
/* load new m, n pll values for dclk & mclk */
- vga_out8 (0x3c4, 0x15);
- tmp = vga_in8 (0x3c5) & ~0x21;
+ vga_out8 (0x3c4, 0x15, par);
+ tmp = vga_in8 (0x3c5, par) & ~0x21;
- vga_out8 (0x3c5, tmp | 0x03);
- vga_out8 (0x3c5, tmp | 0x23);
- vga_out8 (0x3c5, tmp | 0x03);
- vga_out8 (0x3c5, par->SR15);
+ vga_out8 (0x3c5, tmp | 0x03, par);
+ vga_out8 (0x3c5, tmp | 0x23, par);
+ vga_out8 (0x3c5, tmp | 0x03, par);
+ vga_out8 (0x3c5, par->SR15, par);
udelay (100);
- vga_out8 (0x3c4, 0x30);
- vga_out8 (0x3c5, par->SR30);
- vga_out8 (0x3c4, 0x08);
- vga_out8 (0x3c5, par->SR08);
+ vga_out8 (0x3c4, 0x30, par);
+ vga_out8 (0x3c5, par->SR30, par);
+ vga_out8 (0x3c4, 0x08, par);
+ vga_out8 (0x3c5, par->SR08, par);
/* now write out cr67 in full, possibly starting STREAMS */
- VerticalRetraceWait();
- vga_out8 (0x3d4, 0x67);
- vga_out8 (0x3d5, par->CR67);
+ VerticalRetraceWait(par);
+ vga_out8 (0x3d4, 0x67, par);
+ vga_out8 (0x3d5, par->CR67, par);
- vga_out8 (0x3d4, 0x66);
- cr66 = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr66 | 0x80);
- vga_out8 (0x3d4, 0x3a);
- cr3a = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr3a | 0x80);
+ vga_out8 (0x3d4, 0x66, par);
+ cr66 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr66 | 0x80, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ cr3a = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr3a | 0x80, par);
if (par->chip != S3_SAVAGE_MX) {
- VerticalRetraceWait();
- savage_out32 (FIFO_CONTROL_REG, par->MMPR0);
+ VerticalRetraceWait(par);
+ savage_out32 (FIFO_CONTROL_REG, par->MMPR0, par);
par->SavageWaitIdle (par);
- savage_out32 (MIU_CONTROL_REG, par->MMPR1);
+ savage_out32 (MIU_CONTROL_REG, par->MMPR1, par);
par->SavageWaitIdle (par);
- savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2);
+ savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2, par);
par->SavageWaitIdle (par);
- savage_out32 (MISC_TIMEOUT_REG, par->MMPR3);
+ savage_out32 (MISC_TIMEOUT_REG, par->MMPR3, par);
}
- vga_out8 (0x3d4, 0x66);
- vga_out8 (0x3d5, cr66);
- vga_out8 (0x3d4, 0x3a);
- vga_out8 (0x3d5, cr3a);
+ vga_out8 (0x3d4, 0x66, par);
+ vga_out8 (0x3d5, cr66, par);
+ vga_out8 (0x3d4, 0x3a, par);
+ vga_out8 (0x3d5, cr3a, par);
SavageSetup2DEngine (par);
vgaHWProtect (par, 0);
@@ -1299,10 +1303,10 @@ static void savagefb_update_start (struct savagefb_par *par,
* ((var->bits_per_pixel+7) / 8)) >> 2;
/* now program the start address registers */
- vga_out16(0x3d4, (base & 0x00ff00) | 0x0c);
- vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d);
- vga_out8 (0x3d4, 0x69);
- vga_out8 (0x3d5, (base & 0x7f0000) >> 16);
+ vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
+ vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
+ vga_out8 (0x3d4, 0x69, par);
+ vga_out8 (0x3d5, (base & 0x7f0000) >> 16, par);
}
@@ -1406,12 +1410,12 @@ static int savagefb_blank(int blank, struct fb_info *info)
u8 sr8 = 0, srd = 0;
if (par->display_type == DISP_CRT) {
- vga_out8(0x3c4, 0x08);
- sr8 = vga_in8(0x3c5);
+ vga_out8(0x3c4, 0x08, par);
+ sr8 = vga_in8(0x3c5, par);
sr8 |= 0x06;
- vga_out8(0x3c5, sr8);
- vga_out8(0x3c4, 0x0d);
- srd = vga_in8(0x3c5);
+ vga_out8(0x3c5, sr8, par);
+ vga_out8(0x3c4, 0x0d, par);
+ srd = vga_in8(0x3c5, par);
srd &= 0x03;
switch (blank) {
@@ -1429,8 +1433,8 @@ static int savagefb_blank(int blank, struct fb_info *info)
break;
}
- vga_out8(0x3c4, 0x0d);
- vga_out8(0x3c5, srd);
+ vga_out8(0x3c4, 0x0d, par);
+ vga_out8(0x3c5, srd, par);
}
if (par->display_type == DISP_LCD ||
@@ -1438,14 +1442,14 @@ static int savagefb_blank(int blank, struct fb_info *info)
switch(blank) {
case FB_BLANK_UNBLANK:
case FB_BLANK_NORMAL:
- vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
- vga_out8(0x3c5, vga_in8(0x3c5) | 0x10);
+ vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
+ vga_out8(0x3c5, vga_in8(0x3c5, par) | 0x10, par);
break;
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
- vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
- vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10);
+ vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
+ vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x10, par);
break;
}
}
@@ -1470,7 +1474,6 @@ static struct fb_ops savagefb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
#endif
- .fb_cursor = soft_cursor,
};
/* --------------------------------------------------------------------- */
@@ -1499,15 +1502,15 @@ static void savage_enable_mmio (struct savagefb_par *par)
DBG ("savage_enable_mmio\n");
- val = vga_in8 (0x3c3);
- vga_out8 (0x3c3, val | 0x01);
- val = vga_in8 (0x3cc);
- vga_out8 (0x3c2, val | 0x01);
+ val = vga_in8 (0x3c3, par);
+ vga_out8 (0x3c3, val | 0x01, par);
+ val = vga_in8 (0x3cc, par);
+ vga_out8 (0x3c2, val | 0x01, par);
if (par->chip >= S3_SAVAGE4) {
- vga_out8 (0x3d4, 0x40);
- val = vga_in8 (0x3d5);
- vga_out8 (0x3d5, val | 1);
+ vga_out8 (0x3d4, 0x40, par);
+ val = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, val | 1, par);
}
}
@@ -1519,9 +1522,9 @@ static void savage_disable_mmio (struct savagefb_par *par)
DBG ("savage_disable_mmio\n");
if(par->chip >= S3_SAVAGE4 ) {
- vga_out8 (0x3d4, 0x40);
- val = vga_in8 (0x3d5);
- vga_out8 (0x3d5, val | 1);
+ vga_out8 (0x3d4, 0x40, par);
+ val = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, val | 1, par);
}
}
@@ -1641,30 +1644,30 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
DBG("savage_init_hw");
/* unprotect CRTC[0-7] */
- vga_out8(0x3d4, 0x11);
- tmp = vga_in8(0x3d5);
- vga_out8(0x3d5, tmp & 0x7f);
+ vga_out8(0x3d4, 0x11, par);
+ tmp = vga_in8(0x3d5, par);
+ vga_out8(0x3d5, tmp & 0x7f, par);
/* unlock extended regs */
- vga_out16(0x3d4, 0x4838);
- vga_out16(0x3d4, 0xa039);
- vga_out16(0x3c4, 0x0608);
+ vga_out16(0x3d4, 0x4838, par);
+ vga_out16(0x3d4, 0xa039, par);
+ vga_out16(0x3c4, 0x0608, par);
- vga_out8(0x3d4, 0x40);
- tmp = vga_in8(0x3d5);
- vga_out8(0x3d5, tmp & ~0x01);
+ vga_out8(0x3d4, 0x40, par);
+ tmp = vga_in8(0x3d5, par);
+ vga_out8(0x3d5, tmp & ~0x01, par);
/* unlock sys regs */
- vga_out8(0x3d4, 0x38);
- vga_out8(0x3d5, 0x48);
+ vga_out8(0x3d4, 0x38, par);
+ vga_out8(0x3d5, 0x48, par);
/* Unlock system registers. */
- vga_out16(0x3d4, 0x4838);
+ vga_out16(0x3d4, 0x4838, par);
/* Next go on to detect amount of installed ram */
- vga_out8(0x3d4, 0x36); /* for register CR36 (CONFG_REG1), */
- config1 = vga_in8(0x3d5); /* get amount of vram installed */
+ vga_out8(0x3d4, 0x36, par); /* for register CR36 (CONFG_REG1), */
+ config1 = vga_in8(0x3d5, par); /* get amount of vram installed */
/* Compute the amount of video memory and offscreen memory. */
@@ -1680,8 +1683,8 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
* when it really means 8MB. Why do it the same when you
* can do it different...
*/
- vga_out8(0x3d4, 0x68); /* memory control 1 */
- if( (vga_in8(0x3d5) & 0xC0) == (0x01 << 6) )
+ vga_out8(0x3d4, 0x68, par); /* memory control 1 */
+ if( (vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6) )
RamSavage4[1] = 8;
/*FALLTHROUGH*/
@@ -1710,13 +1713,13 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
printk (KERN_INFO "savagefb: probed videoram: %dk\n", videoRam);
/* reset graphics engine to avoid memory corruption */
- vga_out8 (0x3d4, 0x66);
- cr66 = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr66 | 0x02);
+ vga_out8 (0x3d4, 0x66, par);
+ cr66 = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr66 | 0x02, par);
udelay (10000);
- vga_out8 (0x3d4, 0x66);
- vga_out8 (0x3d5, cr66 & ~0x02); /* clear reset flag */
+ vga_out8 (0x3d4, 0x66, par);
+ vga_out8 (0x3d5, cr66 & ~0x02, par); /* clear reset flag */
udelay (10000);
@@ -1724,13 +1727,13 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
* reset memory interface, 3D engine, AGP master, PCI master,
* master engine unit, motion compensation/LPB
*/
- vga_out8 (0x3d4, 0x3f);
- cr3f = vga_in8 (0x3d5);
- vga_out8 (0x3d5, cr3f | 0x08);
+ vga_out8 (0x3d4, 0x3f, par);
+ cr3f = vga_in8 (0x3d5, par);
+ vga_out8 (0x3d5, cr3f | 0x08, par);
udelay (10000);
- vga_out8 (0x3d4, 0x3f);
- vga_out8 (0x3d5, cr3f & ~0x08); /* clear reset flags */
+ vga_out8 (0x3d4, 0x3f, par);
+ vga_out8 (0x3d5, cr3f & ~0x08, par); /* clear reset flags */
udelay (10000);
/* Savage ramdac speeds */
@@ -1741,15 +1744,15 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
par->clock[3] = 220000;
/* detect current mclk */
- vga_out8(0x3c4, 0x08);
- sr8 = vga_in8(0x3c5);
- vga_out8(0x3c5, 0x06);
- vga_out8(0x3c4, 0x10);
- n = vga_in8(0x3c5);
- vga_out8(0x3c4, 0x11);
- m = vga_in8(0x3c5);
- vga_out8(0x3c4, 0x08);
- vga_out8(0x3c5, sr8);
+ vga_out8(0x3c4, 0x08, par);
+ sr8 = vga_in8(0x3c5, par);
+ vga_out8(0x3c5, 0x06, par);
+ vga_out8(0x3c4, 0x10, par);
+ n = vga_in8(0x3c5, par);
+ vga_out8(0x3c4, 0x11, par);
+ m = vga_in8(0x3c5, par);
+ vga_out8(0x3c4, 0x08, par);
+ vga_out8(0x3c5, sr8, par);
m &= 0x7f;
n1 = n & 0x1f;
n2 = (n >> 5) & 0x03;
@@ -1763,10 +1766,10 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
if (par->chip == S3_SAVAGE4) {
unsigned char sr30 = 0x00;
- vga_out8(0x3c4, 0x30);
+ vga_out8(0x3c4, 0x30, par);
/* clear bit 1 */
- vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02);
- sr30 = vga_in8(0x3c5);
+ vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x02, par);
+ sr30 = vga_in8(0x3c5, par);
if (sr30 & 0x02 /*0x04 */) {
dvi = 1;
printk("savagefb: Digital Flat Panel Detected\n");
@@ -1783,12 +1786,12 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
/* Check LCD panel parrmation */
if (par->display_type == DISP_LCD) {
- unsigned char cr6b = VGArCR( 0x6b );
+ unsigned char cr6b = VGArCR( 0x6b, par);
- int panelX = (VGArSEQ (0x61) +
- ((VGArSEQ (0x66) & 0x02) << 7) + 1) * 8;
- int panelY = (VGArSEQ (0x69) +
- ((VGArSEQ (0x6e) & 0x70) << 4) + 1);
+ int panelX = (VGArSEQ (0x61, par) +
+ ((VGArSEQ (0x66, par) & 0x02) << 7) + 1) * 8;
+ int panelY = (VGArSEQ (0x69, par) +
+ ((VGArSEQ (0x6e, par) & 0x70) << 4) + 1);
char * sTechnology = "Unknown";
@@ -1810,9 +1813,9 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
ActiveDUO = 0x80
};
- if ((VGArSEQ (0x39) & 0x03) == 0) {
+ if ((VGArSEQ (0x39, par) & 0x03) == 0) {
sTechnology = "TFT";
- } else if ((VGArSEQ (0x30) & 0x01) == 0) {
+ } else if ((VGArSEQ (0x30, par) & 0x01) == 0) {
sTechnology = "DSTN";
} else {
sTechnology = "STN";
@@ -2049,24 +2052,11 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
info->monspecs.modedb, info->monspecs.modedb_len,
NULL, 8);
} else if (info->monspecs.modedb != NULL) {
- struct fb_monspecs *specs = &info->monspecs;
- struct fb_videomode modedb;
+ struct fb_videomode *modedb;
- if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
- int i;
-
- for (i = 0; i < specs->modedb_len; i++) {
- if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
- modedb = specs->modedb[i];
- break;
- }
- }
- } else {
- /* otherwise, get first mode in database */
- modedb = specs->modedb[0];
- }
-
- savage_update_var(&info->var, &modedb);
+ modedb = fb_find_best_display(&info->monspecs,
+ &info->modelist);
+ savage_update_var(&info->var, modedb);
}
/* maximize virtual vertical length */
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 5ce81f44c769..2e8769dd345a 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -126,7 +126,6 @@ static struct fb_ops sgivwfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_mmap = sgivwfb_mmap,
};
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 42c54b69726e..dea1a46c67c4 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -2002,7 +2002,9 @@ static struct fb_ops sisfb_ops = {
.fb_fillrect = fbcon_sis_fillrect,
.fb_copyarea = fbcon_sis_copyarea,
.fb_imageblit = cfb_imageblit,
+#ifdef CONFIG_FB_SOFT_CURSOR
.fb_cursor = soft_cursor,
+#endif
.fb_sync = fbcon_sis_sync,
#ifdef SIS_NEW_CONFIG_COMPAT
.fb_compat_ioctl= sisfb_compat_ioctl,
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 7b43716ab665..a01e7ecc15ed 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -457,11 +457,8 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image)
}
/**
- * xxxfb_cursor - REQUIRED function. If your hardware lacks support
- * for a cursor you can use the default cursor whose
- * function is called soft_cursor. It will always
- * work since it uses xxxfb_imageblit function which
- * is required.
+ * xxxfb_cursor - OPTIONAL. If your hardware lacks support
+ * for a cursor, leave this field NULL.
*
* @info: frame buffer structure that represents a single frame buffer
* @cursor: structure defining the cursor to draw.
@@ -663,7 +660,7 @@ static struct fb_ops xxxfb_ops = {
.fb_fillrect = xxxfb_fillrect, /* Needed !!! */
.fb_copyarea = xxxfb_copyarea, /* Needed !!! */
.fb_imageblit = xxxfb_imageblit, /* Needed !!! */
- .fb_cursor = xxxfb_cursor, /* Needed !!! */
+ .fb_cursor = xxxfb_cursor, /* Optional !!! */
.fb_rotate = xxxfb_rotate,
.fb_poll = xxxfb_poll,
.fb_sync = xxxfb_sync,
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 663d53657fa4..e0f14df840d9 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1382,7 +1382,6 @@ static struct fb_ops sstfb_ops = {
.fb_fillrect = cfb_fillrect, /* sstfb_fillrect */
.fb_copyarea = cfb_copyarea, /* sstfb_copyarea */
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_ioctl = sstfb_ioctl,
};
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 9e52794768e6..fbb17332afd7 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -1147,7 +1147,6 @@ static struct fb_ops stifb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 1986a8b3833c..59fff29bc02e 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -52,7 +52,6 @@ static struct fb_ops tcx_ops = {
.fb_imageblit = cfb_imageblit,
.fb_mmap = tcx_mmap,
.fb_ioctl = tcx_ioctl,
- .fb_cursor = soft_cursor,
};
/* THC definitions */
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 7044226c5d4c..9d53387e6a66 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -184,7 +184,6 @@ static struct fb_ops tdfxfb_ops = {
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
#endif
- .fb_cursor = soft_cursor,
};
/*
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 9d9d2009ad8c..7398bd48ba6c 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -63,7 +63,6 @@ static struct fb_ops tgafb_ops = {
.fb_fillrect = tgafb_fillrect,
.fb_copyarea = tgafb_copyarea,
.fb_imageblit = tgafb_imageblit,
- .fb_cursor = soft_cursor,
};
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 81a6d9f188cf..9ac2d3171187 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1293,7 +1293,6 @@ static struct fb_ops tridentfb_ops = {
.fb_fillrect = tridentfb_fillrect,
.fb_copyarea= tridentfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
module_init(tridentfb_init);
diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
index 39d9ca71856b..d904da44e1aa 100644
--- a/drivers/video/tx3912fb.c
+++ b/drivers/video/tx3912fb.c
@@ -89,7 +89,6 @@ static struct fb_ops tx3912fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index 31a2bbc53974..ce97ec8eae97 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -135,7 +135,6 @@ static struct fb_ops valkyriefb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
/* Sets the video mode according to info->var */
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 3cc23106641d..e25eae1a78c1 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -48,7 +48,7 @@ static struct fb_fix_screeninfo vesafb_fix __initdata = {
};
static int inverse = 0;
-static int mtrr = 3; /* default to write-combining */
+static int mtrr = 0; /* disable mtrr */
static int vram_remap __initdata = 0; /* Set amount of memory to be used */
static int vram_total __initdata = 0; /* Set total amount of memory */
static int pmi_setpal = 0; /* pmi for palette changes ??? */
@@ -166,45 +166,39 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
if (regno >= info->cmap.len)
return 1;
- switch (info->var.bits_per_pixel) {
- case 8:
+ if (info->var.bits_per_pixel == 8)
vesa_setpalette(regno,red,green,blue);
- break;
- case 16:
- if (info->var.red.offset == 10) {
- /* 1:5:5:5 */
- ((u32*) (info->pseudo_palette))[regno] =
+ else if (regno < 16) {
+ switch (info->var.bits_per_pixel) {
+ case 16:
+ if (info->var.red.offset == 10) {
+ /* 1:5:5:5 */
+ ((u32*) (info->pseudo_palette))[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) |
((blue & 0xf800) >> 11);
- } else {
- /* 0:5:6:5 */
- ((u32*) (info->pseudo_palette))[regno] =
+ } else {
+ /* 0:5:6:5 */
+ ((u32*) (info->pseudo_palette))[regno] =
((red & 0xf800) ) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
+ }
+ break;
+ case 24:
+ case 32:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ ((u32 *)(info->pseudo_palette))[regno] =
+ (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset);
+ break;
}
- break;
- case 24:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- break;
- case 32:
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- ((u32 *)(info->pseudo_palette))[regno] =
- (red << info->var.red.offset) |
- (green << info->var.green.offset) |
- (blue << info->var.blue.offset);
- break;
- }
- return 0;
+ }
+
+ return 0;
}
static struct fb_ops vesafb_ops = {
@@ -215,7 +209,6 @@ static struct fb_ops vesafb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
static int __init vesafb_setup(char *options)
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 92d46555dd86..8794dc5d2466 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -92,7 +92,6 @@ static struct fb_ops vfb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
.fb_mmap = vfb_mmap,
};
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index b46454c55c91..690bb6fe8281 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1326,7 +1326,6 @@ static struct fb_ops vga16fb_ops = {
.fb_fillrect = vga16fb_fillrect,
.fb_copyarea = vga16fb_copyarea,
.fb_imageblit = vga16fb_imageblit,
- .fb_cursor = soft_cursor,
};
#ifndef MODULE
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index cf8cdb108fd9..48e70f153c4b 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -397,7 +397,6 @@ static struct fb_ops w100fb_ops = {
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
- .fb_cursor = soft_cursor,
};
#ifdef CONFIG_PM
diff --git a/drivers/w1/w1_ds2433.c b/drivers/w1/w1_ds2433.c
index 279e0e0363d6..1e3d98aac12d 100644
--- a/drivers/w1/w1_ds2433.c
+++ b/drivers/w1/w1_ds2433.c
@@ -299,10 +299,8 @@ static int w1_f23_add_slave(struct w1_slave *sl)
static void w1_f23_remove_slave(struct w1_slave *sl)
{
#ifdef CONFIG_W1_F23_CRC
- if (sl->family_data) {
- kfree(sl->family_data);
- sl->family_data = NULL;
- }
+ kfree(sl->family_data);
+ sl->family_data = NULL;
#endif /* CONFIG_W1_F23_CRC */
sysfs_remove_bin_file(&sl->dev.kobj, &w1_f23_bin_attr);
}
diff --git a/fs/9p/error.c b/fs/9p/error.c
index fee5d19179c5..834cb179e388 100644
--- a/fs/9p/error.c
+++ b/fs/9p/error.c
@@ -33,6 +33,7 @@
#include <linux/list.h>
#include <linux/jhash.h>
+#include <linux/string.h>
#include "debug.h"
#include "error.h"
diff --git a/fs/9p/trans_sock.c b/fs/9p/trans_sock.c
index 01e26f0013ac..a93c2bf94c33 100644
--- a/fs/9p/trans_sock.c
+++ b/fs/9p/trans_sock.c
@@ -269,8 +269,7 @@ static void v9fs_sock_close(struct v9fs_transport *trans)
dprintk(DEBUG_TRANS, "socket closed\n");
}
- if (ts)
- kfree(ts);
+ kfree(ts);
trans->priv = NULL;
}
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 82303f3bf76f..418c3743fdee 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -266,7 +266,7 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
v9ses->remotename = __getname();
if (!v9ses->remotename) {
- putname(v9ses->name);
+ __putname(v9ses->name);
return -ENOMEM;
}
@@ -411,8 +411,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
if (v9ses->transport)
v9ses->transport->close(v9ses->transport);
- putname(v9ses->name);
- putname(v9ses->remotename);
+ __putname(v9ses->name);
+ __putname(v9ses->remotename);
}
/**
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 2b696ae6655a..be7288184fa9 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1105,7 +1105,7 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
}
}
- putname(link);
+ __putname(link);
return retval;
}
@@ -1129,7 +1129,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
len = v9fs_readlink(dentry, link, strlen(link));
if (len < 0) {
- putname(link);
+ __putname(link);
link = ERR_PTR(len);
} else
link[len] = 0;
@@ -1152,7 +1152,7 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
if (!IS_ERR(s))
- putname(s);
+ __putname(s);
}
/**
@@ -1228,7 +1228,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
FreeMem:
kfree(mistat);
kfree(fcall);
- putname(symname);
+ __putname(symname);
return retval;
}
@@ -1319,7 +1319,7 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
FreeMem:
kfree(mistat);
kfree(fcall);
- putname(symname);
+ __putname(symname);
return retval;
}
diff --git a/fs/Kconfig b/fs/Kconfig
index 01a295232f75..7cf36ca157ff 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -898,6 +898,7 @@ config AFFS_FS
config HFS_FS
tristate "Apple Macintosh file system support (EXPERIMENTAL)"
depends on EXPERIMENTAL
+ select NLS
help
If you say Y here, you will be able to mount Macintosh-formatted
floppy disks and hard drive partitions with full read-write access.
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 6744924b6905..f72fb776ecdf 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -22,14 +22,13 @@ static int affs_grow_extcache(struct inode *inode, u32 lc_idx);
static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext);
static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext);
static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
-static ssize_t affs_file_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos);
static int affs_file_open(struct inode *inode, struct file *filp);
static int affs_file_release(struct inode *inode, struct file *filp);
struct file_operations affs_file_operations = {
.llseek = generic_file_llseek,
.read = generic_file_read,
- .write = affs_file_write,
+ .write = generic_file_write,
.mmap = generic_file_mmap,
.open = affs_file_open,
.release = affs_file_release,
@@ -473,21 +472,6 @@ affs_getemptyblk_ino(struct inode *inode, int block)
return ERR_PTR(err);
}
-static ssize_t
-affs_file_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- ssize_t retval;
-
- retval = generic_file_write (file, buf, count, ppos);
- if (retval >0) {
- struct inode *inode = file->f_dentry->d_inode;
- inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
- mark_inode_dirty(inode);
- }
- return retval;
-}
-
static int
affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
{
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 9c3080716c92..aaec015a16e4 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -35,8 +35,7 @@ affs_put_super(struct super_block *sb)
mark_buffer_dirty(sbi->s_root_bh);
}
- if (sbi->s_prefix)
- kfree(sbi->s_prefix);
+ kfree(sbi->s_prefix);
affs_free_bitmap(sb);
affs_brelse(sbi->s_root_bh);
kfree(sbi);
@@ -198,10 +197,9 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s
*mount_opts |= SF_MUFS;
break;
case Opt_prefix:
- if (*prefix) { /* Free any previous prefix */
- kfree(*prefix);
- *prefix = NULL;
- }
+ /* Free any previous prefix */
+ kfree(*prefix);
+ *prefix = NULL;
*prefix = match_strdup(&args[0]);
if (!*prefix)
return 0;
@@ -462,11 +460,9 @@ got_root:
out_error:
if (root_inode)
iput(root_inode);
- if (sbi->s_bitmap)
- kfree(sbi->s_bitmap);
+ kfree(sbi->s_bitmap);
affs_brelse(root_bh);
- if (sbi->s_prefix)
- kfree(sbi->s_prefix);
+ kfree(sbi->s_prefix);
kfree(sbi);
sb->s_fs_info = NULL;
return -EINVAL;
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 4975c9c193dd..150b19227922 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -31,24 +31,10 @@ static int afs_file_readpage(struct file *file, struct page *page);
static int afs_file_invalidatepage(struct page *page, unsigned long offset);
static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
-static ssize_t afs_file_write(struct file *file, const char __user *buf,
- size_t size, loff_t *off);
-
struct inode_operations afs_file_inode_operations = {
.getattr = afs_inode_getattr,
};
-struct file_operations afs_file_file_operations = {
- .read = generic_file_read,
- .write = afs_file_write,
- .mmap = generic_file_mmap,
-#if 0
- .open = afs_file_open,
- .release = afs_file_release,
- .fsync = afs_file_fsync,
-#endif
-};
-
struct address_space_operations afs_fs_aops = {
.readpage = afs_file_readpage,
.sync_page = block_sync_page,
@@ -59,22 +45,6 @@ struct address_space_operations afs_fs_aops = {
/*****************************************************************************/
/*
- * AFS file write
- */
-static ssize_t afs_file_write(struct file *file, const char __user *buf,
- size_t size, loff_t *off)
-{
- struct afs_vnode *vnode;
-
- vnode = AFS_FS_I(file->f_dentry->d_inode);
- if (vnode->flags & AFS_VNODE_DELETED)
- return -ESTALE;
-
- return -EIO;
-} /* end afs_file_write() */
-
-/*****************************************************************************/
-/*
* deal with notification that a page was read from the cache
*/
#ifdef AFS_CACHING_SUPPORT
@@ -295,8 +265,7 @@ static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
set_page_private(page, 0);
ClearPagePrivate(page);
- if (pageio)
- kfree(pageio);
+ kfree(pageio);
}
_leave(" = 0");
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index c476fde33fbc..4ebb30a50ed5 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -49,7 +49,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
case AFS_FTYPE_FILE:
inode->i_mode = S_IFREG | vnode->status.mode;
inode->i_op = &afs_file_inode_operations;
- inode->i_fop = &afs_file_file_operations;
+ inode->i_fop = &generic_ro_fops;
break;
case AFS_FTYPE_DIR:
inode->i_mode = S_IFDIR | vnode->status.mode;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index f09860b45c1a..ab8f87c66319 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -71,7 +71,6 @@ extern struct file_operations afs_dir_file_operations;
*/
extern struct address_space_operations afs_fs_aops;
extern struct inode_operations afs_file_inode_operations;
-extern struct file_operations afs_file_file_operations;
#ifdef AFS_CACHING_SUPPORT
extern int afs_cache_get_page_cookie(struct page *page,
diff --git a/fs/aio.c b/fs/aio.c
index edfca5b75535..20bb919eb195 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -42,8 +42,9 @@
#endif
/*------ sysctl variables----*/
-atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */
-unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
+static DEFINE_SPINLOCK(aio_nr_lock);
+unsigned long aio_nr; /* current system wide number of aio requests */
+unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
/*----end sysctl variables---*/
static kmem_cache_t *kiocb_cachep;
@@ -208,7 +209,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
return ERR_PTR(-EINVAL);
}
- if (nr_events > aio_max_nr)
+ if ((unsigned long)nr_events > aio_max_nr)
return ERR_PTR(-EAGAIN);
ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL);
@@ -233,8 +234,14 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
goto out_freectx;
/* limit the number of system wide aios */
- atomic_add(ctx->max_reqs, &aio_nr); /* undone by __put_ioctx */
- if (unlikely(atomic_read(&aio_nr) > aio_max_nr))
+ spin_lock(&aio_nr_lock);
+ if (aio_nr + ctx->max_reqs > aio_max_nr ||
+ aio_nr + ctx->max_reqs < aio_nr)
+ ctx->max_reqs = 0;
+ else
+ aio_nr += ctx->max_reqs;
+ spin_unlock(&aio_nr_lock);
+ if (ctx->max_reqs == 0)
goto out_cleanup;
/* now link into global list. kludge. FIXME */
@@ -248,8 +255,6 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
return ctx;
out_cleanup:
- atomic_sub(ctx->max_reqs, &aio_nr);
- ctx->max_reqs = 0; /* prevent __put_ioctx from sub'ing aio_nr */
__put_ioctx(ctx);
return ERR_PTR(-EAGAIN);
@@ -374,7 +379,12 @@ void fastcall __put_ioctx(struct kioctx *ctx)
pr_debug("__put_ioctx: freeing %p\n", ctx);
kmem_cache_free(kioctx_cachep, ctx);
- atomic_sub(nr_events, &aio_nr);
+ if (nr_events) {
+ spin_lock(&aio_nr_lock);
+ BUG_ON(aio_nr - nr_events > aio_nr);
+ aio_nr -= nr_events;
+ spin_unlock(&aio_nr_lock);
+ }
}
/* aio_get_req
@@ -1258,8 +1268,9 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
goto out;
ret = -EINVAL;
- if (unlikely(ctx || (int)nr_events <= 0)) {
- pr_debug("EINVAL: io_setup: ctx or nr_events > max\n");
+ if (unlikely(ctx || nr_events == 0)) {
+ pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
+ ctx, nr_events);
goto out;
}
diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
index 1fcaa1568541..633f628005b4 100644
--- a/fs/autofs/waitq.c
+++ b/fs/autofs/waitq.c
@@ -150,10 +150,8 @@ int autofs_wait(struct autofs_sb_info *sbi, struct qstr *name)
if ( sbi->catatonic ) {
/* We might have slept, so check again for catatonic mode */
wq->status = -ENOENT;
- if ( wq->name ) {
- kfree(wq->name);
- wq->name = NULL;
- }
+ kfree(wq->name);
+ wq->name = NULL;
}
if ( wq->name ) {
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 0a3c05d10167..818b37be5153 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -22,10 +22,8 @@
static void ino_lnkfree(struct autofs_info *ino)
{
- if (ino->u.symlink) {
- kfree(ino->u.symlink);
- ino->u.symlink = NULL;
- }
+ kfree(ino->u.symlink);
+ ino->u.symlink = NULL;
}
struct autofs_info *autofs4_init_ino(struct autofs_info *ino,
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 3df86285a1c7..394ff36ef8f1 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -243,10 +243,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
if ( sbi->catatonic ) {
/* We might have slept, so check again for catatonic mode */
wq->status = -ENOENT;
- if ( wq->name ) {
- kfree(wq->name);
- wq->name = NULL;
- }
+ kfree(wq->name);
+ wq->name = NULL;
}
if ( wq->name ) {
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index e0a6025f1d06..2d365cb8eec6 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -73,12 +73,6 @@ static struct inode_operations befs_dir_inode_operations = {
.lookup = befs_lookup,
};
-static struct file_operations befs_file_operations = {
- .llseek = default_llseek,
- .read = generic_file_read,
- .mmap = generic_file_readonly_mmap,
-};
-
static struct address_space_operations befs_aops = {
.readpage = befs_readpage,
.sync_page = block_sync_page,
@@ -398,7 +392,7 @@ befs_read_inode(struct inode *inode)
inode->i_mapping->a_ops = &befs_aops;
if (S_ISREG(inode->i_mode)) {
- inode->i_fop = &befs_file_operations;
+ inode->i_fop = &generic_ro_fops;
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &befs_dir_inode_operations;
inode->i_fop = &befs_dir_operations;
@@ -731,20 +725,16 @@ parse_options(char *options, befs_mount_options * opts)
static void
befs_put_super(struct super_block *sb)
{
- if (BEFS_SB(sb)->mount_opts.iocharset) {
- kfree(BEFS_SB(sb)->mount_opts.iocharset);
- BEFS_SB(sb)->mount_opts.iocharset = NULL;
- }
+ kfree(BEFS_SB(sb)->mount_opts.iocharset);
+ BEFS_SB(sb)->mount_opts.iocharset = NULL;
if (BEFS_SB(sb)->nls) {
unload_nls(BEFS_SB(sb)->nls);
BEFS_SB(sb)->nls = NULL;
}
- if (sb->s_fs_info) {
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- }
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
return;
}
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 6fa6adc40972..f36f2210204f 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1006,8 +1006,7 @@ out_free_dentry:
if (interpreter)
fput(interpreter);
out_free_interp:
- if (elf_interpreter)
- kfree(elf_interpreter);
+ kfree(elf_interpreter);
out_free_file:
sys_close(elf_exec_fileno);
out_free_fh:
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index dda87c4c82a3..e0344f69c79d 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -411,16 +411,11 @@ error:
allow_write_access(interpreter);
fput(interpreter);
}
- if (interpreter_name)
- kfree(interpreter_name);
- if (exec_params.phdrs)
- kfree(exec_params.phdrs);
- if (exec_params.loadmap)
- kfree(exec_params.loadmap);
- if (interp_params.phdrs)
- kfree(interp_params.phdrs);
- if (interp_params.loadmap)
- kfree(interp_params.loadmap);
+ kfree(interpreter_name);
+ kfree(exec_params.phdrs);
+ kfree(exec_params.loadmap);
+ kfree(interp_params.phdrs);
+ kfree(interp_params.loadmap);
return retval;
/* unrecoverable error - kill the process */
diff --git a/fs/buffer.c b/fs/buffer.c
index 35fa34977e81..5287be18633b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -396,7 +396,7 @@ asmlinkage long sys_fdatasync(unsigned int fd)
* private_lock is contended then so is mapping->tree_lock).
*/
static struct buffer_head *
-__find_get_block_slow(struct block_device *bdev, sector_t block, int unused)
+__find_get_block_slow(struct block_device *bdev, sector_t block)
{
struct inode *bd_inode = bdev->bd_inode;
struct address_space *bd_mapping = bd_inode->i_mapping;
@@ -1438,7 +1438,7 @@ __find_get_block(struct block_device *bdev, sector_t block, int size)
struct buffer_head *bh = lookup_bh_lru(bdev, block, size);
if (bh == NULL) {
- bh = __find_get_block_slow(bdev, block, size);
+ bh = __find_get_block_slow(bdev, block);
if (bh)
bh_lru_install(bh);
}
@@ -1705,7 +1705,7 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block)
might_sleep();
- old_bh = __find_get_block_slow(bdev, block, 0);
+ old_bh = __find_get_block_slow(bdev, block);
if (old_bh) {
clear_buffer_dirty(old_bh);
wait_on_buffer(old_bh);
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 98539e2afe81..086ae8f4a207 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -553,8 +553,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
*(oid + 3)));
rc = compare_oid(oid, oidlen, NTLMSSP_OID,
NTLMSSP_OID_LEN);
- if(oid)
- kfree(oid);
+ kfree(oid);
if (rc)
use_ntlmssp = TRUE;
}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d74367a08d51..450ab75d6546 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1265,8 +1265,7 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
the helper that resolves tcp names, mount to it, try to
tcon to it unmount it if fail */
- if(referrals)
- kfree(referrals);
+ kfree(referrals);
return rc;
}
@@ -1535,10 +1534,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
memset(&volume_info,0,sizeof(struct smb_vol));
if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
@@ -1551,10 +1548,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifserror("No username specified ");
/* In userspace mount helper we can get user name from alternate
locations such as env variables and files on disk */
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
@@ -1573,10 +1568,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if(rc <= 0) {
/* we failed translating address */
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
@@ -1587,19 +1580,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
} else if (volume_info.UNCip){
/* BB using ip addr as server name connect to the DFS root below */
cERROR(1,("Connecting to DFS root not implemented yet"));
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
} else /* which servers DFS root would we conect to */ {
cERROR(1,
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
@@ -1612,10 +1601,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->local_nls = load_nls(volume_info.iocharset);
if(cifs_sb->local_nls == NULL) {
cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -ELIBACC;
}
@@ -1630,10 +1617,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
&sin_server6.sin6_addr,
volume_info.username, &srvTcp);
else {
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return -EINVAL;
}
@@ -1654,10 +1639,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
("Error connecting to IPv4 socket. Aborting operation"));
if(csocket != NULL)
sock_release(csocket);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return rc;
}
@@ -1666,10 +1649,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (srvTcp == NULL) {
rc = -ENOMEM;
sock_release(csocket);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return rc;
} else {
@@ -1692,10 +1673,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if(rc < 0) {
rc = -ENOMEM;
sock_release(csocket);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.UNC);
+ kfree(volume_info.password);
FreeXid(xid);
return rc;
}
@@ -1710,8 +1689,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (existingCifsSes) {
pSesInfo = existingCifsSes;
cFYI(1, ("Existing smb sess found "));
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.password);
/* volume_info.UNC freed at end of function */
} else if (!rc) {
cFYI(1, ("Existing smb sess not found "));
@@ -1741,8 +1719,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if(!rc)
atomic_inc(&srvTcp->socketUseCount);
} else
- if(volume_info.password)
- kfree(volume_info.password);
+ kfree(volume_info.password);
}
/* search for existing tcon to this server share */
@@ -1821,8 +1798,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
"", cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if(volume_info.UNC)
- kfree(volume_info.UNC);
+ kfree(volume_info.UNC);
FreeXid(xid);
return -ENODEV;
} else {
@@ -1925,8 +1901,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
(in which case it is not needed anymore) but when new sesion is created
the password ptr is put in the new session structure (in which case the
password will be freed at unmount time) */
- if(volume_info.UNC)
- kfree(volume_info.UNC);
+ kfree(volume_info.UNC);
FreeXid(xid);
return rc;
}
@@ -3283,8 +3258,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
if ((bcc_ptr + (2 * length)) -
pByteArea(smb_buffer_response) <=
BCC(smb_buffer_response)) {
- if(tcon->nativeFileSystem)
- kfree(tcon->nativeFileSystem);
+ kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
kzalloc(length + 2, GFP_KERNEL);
cifs_strfromUCS_le(tcon->nativeFileSystem,
@@ -3301,8 +3275,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
if ((bcc_ptr + length) -
pByteArea(smb_buffer_response) <=
BCC(smb_buffer_response)) {
- if(tcon->nativeFileSystem)
- kfree(tcon->nativeFileSystem);
+ kfree(tcon->nativeFileSystem);
tcon->nativeFileSystem =
kzalloc(length + 1, GFP_KERNEL);
strncpy(tcon->nativeFileSystem, bcc_ptr,
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index b43e071fe110..0f99aae33162 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -84,10 +84,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifsInode->time = 0; /* will force revalidate to go get info when needed */
cifs_hl_exit:
- if (fromName)
- kfree(fromName);
- if (toName)
- kfree(toName);
+ kfree(fromName);
+ kfree(toName);
FreeXid(xid);
return rc;
}
@@ -206,8 +204,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
}
}
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
@@ -253,8 +250,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
len = buflen;
tmpbuffer = kmalloc(len,GFP_KERNEL);
if(tmpbuffer == NULL) {
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
@@ -303,8 +299,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
strncpy(tmpbuffer, referrals, len-1);
}
}
- if(referrals)
- kfree(referrals);
+ kfree(referrals);
kfree(tmp_path);
}
/* BB add code like else decode referrals then memcpy to
@@ -323,12 +318,8 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
rc));
}
- if (tmpbuffer) {
- kfree(tmpbuffer);
- }
- if (full_path) {
- kfree(full_path);
- }
+ kfree(tmpbuffer);
+ kfree(full_path);
FreeXid(xid);
return rc;
}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index eba1de917f2a..34a06692e4fa 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -98,14 +98,10 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
atomic_dec(&sesInfoAllocCount);
list_del(&buf_to_free->cifsSessionList);
write_unlock(&GlobalSMBSeslock);
- if (buf_to_free->serverOS)
- kfree(buf_to_free->serverOS);
- if (buf_to_free->serverDomain)
- kfree(buf_to_free->serverDomain);
- if (buf_to_free->serverNOS)
- kfree(buf_to_free->serverNOS);
- if (buf_to_free->password)
- kfree(buf_to_free->password);
+ kfree(buf_to_free->serverOS);
+ kfree(buf_to_free->serverDomain);
+ kfree(buf_to_free->serverNOS);
+ kfree(buf_to_free->password);
kfree(buf_to_free);
}
@@ -144,8 +140,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free)
atomic_dec(&tconInfoAllocCount);
list_del(&buf_to_free->cifsConnectionList);
write_unlock(&GlobalSMBSeslock);
- if (buf_to_free->nativeFileSystem)
- kfree(buf_to_free->nativeFileSystem);
+ kfree(buf_to_free->nativeFileSystem);
kfree(buf_to_free);
}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index c1e02eff1d25..f375f87c7dbd 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -87,8 +87,7 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name)
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
}
remove_ea_exit:
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
#endif
return rc;
@@ -132,8 +131,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
returns as xattrs */
if(value_size > MAX_EA_VALUE_SIZE) {
cFYI(1,("size of EA value too large"));
- if(full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
return -EOPNOTSUPP;
}
@@ -195,8 +193,7 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name,
}
set_ea_exit:
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
#endif
return rc;
@@ -298,8 +295,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
rc = -EOPNOTSUPP;
get_ea_exit:
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
#endif
return rc;
@@ -345,8 +341,7 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (full_path)
- kfree(full_path);
+ kfree(full_path);
FreeXid(xid);
#endif
return rc;
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 43dbcb0b21eb..4909754ea84a 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -2235,7 +2235,8 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
if (err)
err = -EFAULT;
-out: if (karg) kfree(karg);
+out:
+ kfree(karg);
return err;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index e90512ed35a4..17e439138681 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -644,7 +644,7 @@ void shrink_dcache_parent(struct dentry * parent)
*
* Prune the dentries that are anonymous
*
- * parsing d_hash list does not hlist_for_each_rcu() as it
+ * parsing d_hash list does not hlist_for_each_entry_rcu() as it
* done under dcache_lock.
*
*/
@@ -1043,15 +1043,13 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
struct hlist_head *head = d_hash(parent,hash);
struct dentry *found = NULL;
struct hlist_node *node;
+ struct dentry *dentry;
rcu_read_lock();
- hlist_for_each_rcu(node, head) {
- struct dentry *dentry;
+ hlist_for_each_entry_rcu(dentry, node, head, d_hash) {
struct qstr *qstr;
- dentry = hlist_entry(node, struct dentry, d_hash);
-
if (dentry->d_name.hash != hash)
continue;
if (dentry->d_parent != parent)
@@ -1123,7 +1121,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
spin_lock(&dcache_lock);
base = d_hash(dparent, dentry->d_name.hash);
hlist_for_each(lhp,base) {
- /* hlist_for_each_rcu() not required for d_hash list
+ /* hlist_for_each_entry_rcu() not required for d_hash list
* as it is parsed under dcache_lock
*/
if (dentry == hlist_entry(lhp, struct dentry, d_hash)) {
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 8b679b67e5e0..1274422a5384 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -2738,10 +2738,8 @@ static int devfsd_close(struct inode *inode, struct file *file)
entry = fs_info->devfsd_first_event;
fs_info->devfsd_first_event = NULL;
fs_info->devfsd_last_event = NULL;
- if (fs_info->devfsd_info) {
- kfree(fs_info->devfsd_info);
- fs_info->devfsd_info = NULL;
- }
+ kfree(fs_info->devfsd_info);
+ fs_info->devfsd_info = NULL;
spin_unlock(&fs_info->devfsd_buffer_lock);
fs_info->devfsd_pgrp = 0;
fs_info->devfsd_task = NULL;
diff --git a/fs/dquot.c b/fs/dquot.c
index ea7644227a65..afa06a893468 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -77,6 +77,7 @@
#include <linux/kmod.h>
#include <linux/namei.h>
#include <linux/buffer_head.h>
+#include <linux/quotaops.h>
#include <asm/uaccess.h>
diff --git a/fs/exec.c b/fs/exec.c
index 10d493fea7ce..cd6c574557dc 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -48,6 +48,7 @@
#include <linux/syscalls.h>
#include <linux/rmap.h>
#include <linux/acct.h>
+#include <linux/cn_proc.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -1096,6 +1097,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
fput(bprm->file);
bprm->file = NULL;
current->did_exec = 1;
+ proc_exec_connector(current);
return retval;
}
read_lock(&binfmt_lock);
@@ -1509,7 +1511,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
goto close_fail;
if (!file->f_op->write)
goto close_fail;
- if (do_truncate(file->f_dentry, 0) != 0)
+ if (do_truncate(file->f_dentry, 0, file) != 0)
goto close_fail;
retval = binfmt->core_dump(signr, regs, file);
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 213148c36ebe..6af2f4130290 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -194,8 +194,7 @@ ext2_get_acl(struct inode *inode, int type)
acl = NULL;
else
acl = ERR_PTR(retval);
- if (value)
- kfree(value);
+ kfree(value);
if (!IS_ERR(acl)) {
switch(type) {
@@ -262,8 +261,7 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
error = ext2_xattr_set(inode, name_index, "", value, size, 0);
- if (value)
- kfree(value);
+ kfree(value);
if (!error) {
switch(type) {
case ACL_TYPE_ACCESS:
diff --git a/fs/file_table.c b/fs/file_table.c
index 4dc205546547..c3a5e2fd663b 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(filp_count_lock);
* context and must be fully threaded - use a local spinlock
* to protect files_stat.nr_files
*/
-void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags)
+void filp_ctor(void *objp, struct kmem_cache *cachep, unsigned long cflags)
{
if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) {
@@ -46,7 +46,7 @@ void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags)
}
}
-void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags)
+void filp_dtor(void *objp, struct kmem_cache *cachep, unsigned long dflags)
{
unsigned long flags;
spin_lock_irqsave(&filp_count_lock, flags);
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index d8be917f9797..927acf70c591 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -38,7 +38,7 @@
*/
-struct kmem_cache_s;
+struct kmem_cache;
struct super_block;
struct vxfs_inode_info;
struct inode;
@@ -51,7 +51,7 @@ extern daddr_t vxfs_bmap1(struct inode *, long);
extern int vxfs_read_fshead(struct super_block *);
/* vxfs_inode.c */
-extern struct kmem_cache_s *vxfs_inode_cachep;
+extern struct kmem_cache *vxfs_inode_cachep;
extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t);
extern struct inode * vxfs_get_fake_inode(struct super_block *,
struct vxfs_inode_info *);
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index 9672d2facffe..f544aae9169f 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -46,15 +46,6 @@ extern struct address_space_operations vxfs_immed_aops;
extern struct inode_operations vxfs_immed_symlink_iops;
-static struct file_operations vxfs_file_operations = {
- .open = generic_file_open,
- .llseek = generic_file_llseek,
- .read = generic_file_read,
- .mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
-};
-
-
kmem_cache_t *vxfs_inode_cachep;
@@ -318,7 +309,7 @@ vxfs_read_inode(struct inode *ip)
aops = &vxfs_aops;
if (S_ISREG(ip->i_mode)) {
- ip->i_fop = &vxfs_file_operations;
+ ip->i_fop = &generic_ro_fops;
ip->i_mapping->a_ops = aops;
} else if (S_ISDIR(ip->i_mode)) {
ip->i_op = &vxfs_dir_inode_ops;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index c27f8d4098be..785c7213a54f 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -562,7 +562,7 @@ int write_inode_now(struct inode *inode, int sync)
};
if (!mapping_cap_writeback_dirty(inode->i_mapping))
- return 0;
+ wbc.nr_to_write = 0;
might_sleep();
spin_lock(&inode_lock);
@@ -606,7 +606,7 @@ EXPORT_SYMBOL(sync_inode);
* O_SYNC flag set, to flush dirty writes to disk.
*
* @what is a bitmask, specifying which part of the inode's data should be
- * written and waited upon:
+ * written and waited upon.
*
* OSYNC_DATA: i_mapping's dirty data
* OSYNC_METADATA: the buffers at i_mapping->private_list
@@ -672,8 +672,9 @@ int writeback_acquire(struct backing_dev_info *bdi)
/**
* writeback_in_progress: determine whether there is writeback in progress
- * against a backing device.
* @bdi: the device's backing_dev_info structure.
+ *
+ * Determine whether there is writeback in progress against a backing device.
*/
int writeback_in_progress(struct backing_dev_info *bdi)
{
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index a6f90a6c754a..8f873e621f41 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -184,6 +184,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
fuse_putback_request() */
for (i = 1; i < FUSE_MAX_OUTSTANDING; i++)
up(&fc->outstanding_sem);
+ } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) {
+ /* Special case for failed iget in CREATE */
+ u64 nodeid = req->in.h.nodeid;
+ __fuse_get_request(req);
+ fuse_reset_request(req);
+ fuse_send_forget(fc, req, nodeid, 1);
+ putback = 0;
}
if (putback)
fuse_putback_request(fc, req);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 70dba721acab..c045cc70c749 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -13,6 +13,7 @@
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/namei.h>
+#include <linux/mount.h>
static inline unsigned long time_to_jiffies(unsigned long sec,
unsigned long nsec)
@@ -134,6 +135,101 @@ static void fuse_invalidate_entry(struct dentry *entry)
entry->d_time = jiffies - 1;
}
+static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
+ struct nameidata *nd)
+{
+ int err;
+ struct inode *inode;
+ struct fuse_conn *fc = get_fuse_conn(dir);
+ struct fuse_req *req;
+ struct fuse_open_in inarg;
+ struct fuse_open_out outopen;
+ struct fuse_entry_out outentry;
+ struct fuse_inode *fi;
+ struct fuse_file *ff;
+ struct file *file;
+ int flags = nd->intent.open.flags - 1;
+
+ err = -ENOSYS;
+ if (fc->no_create)
+ goto out;
+
+ err = -ENAMETOOLONG;
+ if (entry->d_name.len > FUSE_NAME_MAX)
+ goto out;
+
+ err = -EINTR;
+ req = fuse_get_request(fc);
+ if (!req)
+ goto out;
+
+ ff = fuse_file_alloc();
+ if (!ff)
+ goto out_put_request;
+
+ flags &= ~O_NOCTTY;
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.flags = flags;
+ inarg.mode = mode;
+ req->in.h.opcode = FUSE_CREATE;
+ req->in.h.nodeid = get_node_id(dir);
+ req->inode = dir;
+ req->in.numargs = 2;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->in.args[1].size = entry->d_name.len + 1;
+ req->in.args[1].value = entry->d_name.name;
+ req->out.numargs = 2;
+ req->out.args[0].size = sizeof(outentry);
+ req->out.args[0].value = &outentry;
+ req->out.args[1].size = sizeof(outopen);
+ req->out.args[1].value = &outopen;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (err) {
+ if (err == -ENOSYS)
+ fc->no_create = 1;
+ goto out_free_ff;
+ }
+
+ err = -EIO;
+ if (!S_ISREG(outentry.attr.mode))
+ goto out_free_ff;
+
+ inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
+ &outentry.attr);
+ err = -ENOMEM;
+ if (!inode) {
+ flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
+ ff->fh = outopen.fh;
+ fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0);
+ goto out_put_request;
+ }
+ fuse_put_request(fc, req);
+ entry->d_time = time_to_jiffies(outentry.entry_valid,
+ outentry.entry_valid_nsec);
+ fi = get_fuse_inode(inode);
+ fi->i_time = time_to_jiffies(outentry.attr_valid,
+ outentry.attr_valid_nsec);
+
+ d_instantiate(entry, inode);
+ file = lookup_instantiate_filp(nd, entry, generic_file_open);
+ if (IS_ERR(file)) {
+ ff->fh = outopen.fh;
+ fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0);
+ return PTR_ERR(file);
+ }
+ fuse_finish_open(inode, file, ff, &outopen);
+ return 0;
+
+ out_free_ff:
+ fuse_file_free(ff);
+ out_put_request:
+ fuse_put_request(fc, req);
+ out:
+ return err;
+}
+
static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
struct inode *dir, struct dentry *entry,
int mode)
@@ -208,6 +304,12 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
struct nameidata *nd)
{
+ if (nd && (nd->flags & LOOKUP_CREATE)) {
+ int err = fuse_create_open(dir, entry, mode, nd);
+ if (err != -ENOSYS)
+ return err;
+ /* Fall back on mknod */
+ }
return fuse_mknod(dir, entry, mode, 0);
}
@@ -461,6 +563,38 @@ static int fuse_revalidate(struct dentry *entry)
return fuse_do_getattr(inode);
}
+static int fuse_access(struct inode *inode, int mask)
+{
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+ struct fuse_access_in inarg;
+ int err;
+
+ if (fc->no_access)
+ return 0;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.mask = mask;
+ req->in.h.opcode = FUSE_ACCESS;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ if (err == -ENOSYS) {
+ fc->no_access = 1;
+ err = 0;
+ }
+ return err;
+}
+
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct fuse_conn *fc = get_fuse_conn(inode);
@@ -491,11 +625,11 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
return err;
} else {
int mode = inode->i_mode;
- if ((mask & MAY_WRITE) && IS_RDONLY(inode) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
- return -EROFS;
if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO))
return -EACCES;
+
+ if (nd && (nd->flags & LOOKUP_ACCESS))
+ return fuse_access(inode, mask);
return 0;
}
}
@@ -629,29 +763,29 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
}
-static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
+static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
{
unsigned ivalid = iattr->ia_valid;
- unsigned fvalid = 0;
-
- memset(fattr, 0, sizeof(*fattr));
if (ivalid & ATTR_MODE)
- fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode;
+ arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
if (ivalid & ATTR_UID)
- fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid;
+ arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid;
if (ivalid & ATTR_GID)
- fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid;
+ arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid;
if (ivalid & ATTR_SIZE)
- fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size;
+ arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
/* You can only _set_ these together (they may change by themselves) */
if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
- fvalid |= FATTR_ATIME | FATTR_MTIME;
- fattr->atime = iattr->ia_atime.tv_sec;
- fattr->mtime = iattr->ia_mtime.tv_sec;
+ arg->valid |= FATTR_ATIME | FATTR_MTIME;
+ arg->atime = iattr->ia_atime.tv_sec;
+ arg->mtime = iattr->ia_mtime.tv_sec;
+ }
+ if (ivalid & ATTR_FILE) {
+ struct fuse_file *ff = iattr->ia_file->private_data;
+ arg->valid |= FATTR_FH;
+ arg->fh = ff->fh;
}
-
- return fvalid;
}
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
@@ -686,7 +820,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
return -EINTR;
memset(&inarg, 0, sizeof(inarg));
- inarg.valid = iattr_to_fattr(attr, &inarg.attr);
+ iattr_to_fattr(attr, &inarg);
req->in.h.opcode = FUSE_SETATTR;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;
@@ -735,7 +869,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
struct nameidata *nd)
{
struct inode *inode;
- int err = fuse_lookup_iget(dir, entry, &inode);
+ int err;
+
+ err = fuse_lookup_iget(dir, entry, &inode);
if (err)
return ERR_PTR(err);
if (inode && S_ISDIR(inode->i_mode)) {
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 657ab11c173b..2ca86141d13a 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -14,11 +14,69 @@
static struct file_operations fuse_direct_io_file_operations;
-int fuse_open_common(struct inode *inode, struct file *file, int isdir)
+static int fuse_send_open(struct inode *inode, struct file *file, int isdir,
+ struct fuse_open_out *outargp)
{
struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req;
struct fuse_open_in inarg;
+ struct fuse_req *req;
+ int err;
+
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+ req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
+ req->in.h.nodeid = get_node_id(inode);
+ req->inode = inode;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->out.numargs = 1;
+ req->out.args[0].size = sizeof(*outargp);
+ req->out.args[0].value = outargp;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+
+ return err;
+}
+
+struct fuse_file *fuse_file_alloc(void)
+{
+ struct fuse_file *ff;
+ ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
+ if (ff) {
+ ff->release_req = fuse_request_alloc();
+ if (!ff->release_req) {
+ kfree(ff);
+ ff = NULL;
+ }
+ }
+ return ff;
+}
+
+void fuse_file_free(struct fuse_file *ff)
+{
+ fuse_request_free(ff->release_req);
+ kfree(ff);
+}
+
+void fuse_finish_open(struct inode *inode, struct file *file,
+ struct fuse_file *ff, struct fuse_open_out *outarg)
+{
+ if (outarg->open_flags & FOPEN_DIRECT_IO)
+ file->f_op = &fuse_direct_io_file_operations;
+ if (!(outarg->open_flags & FOPEN_KEEP_CACHE))
+ invalidate_inode_pages(inode->i_mapping);
+ ff->fh = outarg->fh;
+ file->private_data = ff;
+}
+
+int fuse_open_common(struct inode *inode, struct file *file, int isdir)
+{
struct fuse_open_out outarg;
struct fuse_file *ff;
int err;
@@ -34,73 +92,53 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
/* If opening the root node, no lookup has been performed on
it, so the attributes must be refreshed */
if (get_node_id(inode) == FUSE_ROOT_ID) {
- int err = fuse_do_getattr(inode);
+ err = fuse_do_getattr(inode);
if (err)
return err;
}
- req = fuse_get_request(fc);
- if (!req)
- return -EINTR;
-
- err = -ENOMEM;
- ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
+ ff = fuse_file_alloc();
if (!ff)
- goto out_put_request;
+ return -ENOMEM;
- ff->release_req = fuse_request_alloc();
- if (!ff->release_req) {
- kfree(ff);
- goto out_put_request;
- }
-
- memset(&inarg, 0, sizeof(inarg));
- inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
- req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
- req->in.h.nodeid = get_node_id(inode);
- req->inode = inode;
- req->in.numargs = 1;
- req->in.args[0].size = sizeof(inarg);
- req->in.args[0].value = &inarg;
- req->out.numargs = 1;
- req->out.args[0].size = sizeof(outarg);
- req->out.args[0].value = &outarg;
- request_send(fc, req);
- err = req->out.h.error;
- if (err) {
- fuse_request_free(ff->release_req);
- kfree(ff);
- } else {
- if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO))
- file->f_op = &fuse_direct_io_file_operations;
- if (!(outarg.open_flags & FOPEN_KEEP_CACHE))
- invalidate_inode_pages(inode->i_mapping);
- ff->fh = outarg.fh;
- file->private_data = ff;
+ err = fuse_send_open(inode, file, isdir, &outarg);
+ if (err)
+ fuse_file_free(ff);
+ else {
+ if (isdir)
+ outarg.open_flags &= ~FOPEN_DIRECT_IO;
+ fuse_finish_open(inode, file, ff, &outarg);
}
- out_put_request:
- fuse_put_request(fc, req);
return err;
}
-int fuse_release_common(struct inode *inode, struct file *file, int isdir)
+void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
+ u64 nodeid, struct inode *inode, int flags, int isdir)
{
- struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_file *ff = file->private_data;
- struct fuse_req *req = ff->release_req;
+ struct fuse_req * req = ff->release_req;
struct fuse_release_in *inarg = &req->misc.release_in;
inarg->fh = ff->fh;
- inarg->flags = file->f_flags & ~O_EXCL;
+ inarg->flags = flags;
req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
- req->in.h.nodeid = get_node_id(inode);
+ req->in.h.nodeid = nodeid;
req->inode = inode;
req->in.numargs = 1;
req->in.args[0].size = sizeof(struct fuse_release_in);
req->in.args[0].value = inarg;
request_send_background(fc, req);
kfree(ff);
+}
+
+int fuse_release_common(struct inode *inode, struct file *file, int isdir)
+{
+ struct fuse_file *ff = file->private_data;
+ if (ff) {
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ u64 nodeid = get_node_id(inode);
+ fuse_send_release(fc, ff, nodeid, inode, file->f_flags, isdir);
+ }
/* Return value is ignored by VFS */
return 0;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5cb456f572c1..0ea5301f86be 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -266,6 +266,12 @@ struct fuse_conn {
/** Is removexattr not implemented by fs? */
unsigned no_removexattr : 1;
+ /** Is access not implemented by fs? */
+ unsigned no_access : 1;
+
+ /** Is create not implemented by fs? */
+ unsigned no_create : 1;
+
/** Backing dev info */
struct backing_dev_info bdi;
};
@@ -337,6 +343,17 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
*/
int fuse_open_common(struct inode *inode, struct file *file, int isdir);
+struct fuse_file *fuse_file_alloc(void);
+void fuse_file_free(struct fuse_file *ff);
+void fuse_finish_open(struct inode *inode, struct file *file,
+ struct fuse_file *ff, struct fuse_open_out *outarg);
+
+/**
+ * Send a RELEASE request
+ */
+void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
+ u64 nodeid, struct inode *inode, int flags, int isdir);
+
/**
* Send RELEASE or RELEASEDIR request
*/
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index dd7113106269..a33fb1d91373 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -294,8 +294,7 @@ static void hostfs_delete_inode(struct inode *inode)
static void hostfs_destroy_inode(struct inode *inode)
{
- if(HOSTFS_I(inode)->host_filename)
- kfree(HOSTFS_I(inode)->host_filename);
+ kfree(HOSTFS_I(inode)->host_filename);
/*XXX: This should not happen, probably. The check is here for
* additional safety.*/
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c
index 1d21307730a8..229ff2fb1809 100644
--- a/fs/hpfs/dnode.c
+++ b/fs/hpfs/dnode.c
@@ -244,12 +244,12 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
go_up:
if (namelen >= 256) {
hpfs_error(i->i_sb, "hpfs_add_to_dnode: namelen == %d", namelen);
- if (nd) kfree(nd);
+ kfree(nd);
kfree(nname);
return 1;
}
if (!(d = hpfs_map_dnode(i->i_sb, dno, &qbh))) {
- if (nd) kfree(nd);
+ kfree(nd);
kfree(nname);
return 1;
}
@@ -257,7 +257,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
if (hpfs_sb(i->i_sb)->sb_chk)
if (hpfs_stop_cycles(i->i_sb, dno, &c1, &c2, "hpfs_add_to_dnode")) {
hpfs_brelse4(&qbh);
- if (nd) kfree(nd);
+ kfree(nd);
kfree(nname);
return 1;
}
@@ -270,7 +270,7 @@ static int hpfs_add_to_dnode(struct inode *i, dnode_secno dno,
for_all_poss(i, hpfs_pos_subst, 5, t + 1);
hpfs_mark_4buffers_dirty(&qbh);
hpfs_brelse4(&qbh);
- if (nd) kfree(nd);
+ kfree(nd);
kfree(nname);
return 0;
}
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 8eefa6366db7..63e88d7e2c3b 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -75,7 +75,7 @@ void hpfs_error(struct super_block *s, char *m,...)
} else if (s->s_flags & MS_RDONLY) printk("; going on - but anything won't be destroyed because it's read-only\n");
else printk("; corrupted filesystem mounted read/write - your computer will explode within 20 seconds ... but you wanted it so!\n");
} else printk("\n");
- if (buf) kfree(buf);
+ kfree(buf);
hpfs_sb(s)->sb_was_error = 1;
}
@@ -102,8 +102,8 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2,
static void hpfs_put_super(struct super_block *s)
{
struct hpfs_sb_info *sbi = hpfs_sb(s);
- if (sbi->sb_cp_table) kfree(sbi->sb_cp_table);
- if (sbi->sb_bmp_dir) kfree(sbi->sb_bmp_dir);
+ kfree(sbi->sb_cp_table);
+ kfree(sbi->sb_bmp_dir);
unmark_dirty(s);
s->s_fs_info = NULL;
kfree(sbi);
@@ -654,8 +654,8 @@ bail3: brelse(bh1);
bail2: brelse(bh0);
bail1:
bail0:
- if (sbi->sb_bmp_dir) kfree(sbi->sb_bmp_dir);
- if (sbi->sb_cp_table) kfree(sbi->sb_cp_table);
+ kfree(sbi->sb_bmp_dir);
+ kfree(sbi->sb_cp_table);
s->s_fs_info = NULL;
kfree(sbi);
return -EINVAL;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 1652de1b6cb9..298f08be22d4 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -855,8 +855,7 @@ root_found:
if (opt.check == 'r') table++;
s->s_root->d_op = &isofs_dentry_ops[table];
- if (opt.iocharset)
- kfree(opt.iocharset);
+ kfree(opt.iocharset);
return 0;
@@ -895,8 +894,7 @@ out_unknown_format:
out_freebh:
brelse(bh);
out_freesbi:
- if (opt.iocharset)
- kfree(opt.iocharset);
+ kfree(opt.iocharset);
kfree(sbi);
s->s_fs_info = NULL;
return -EINVAL;
@@ -1164,8 +1162,7 @@ out_nomem:
out_noread:
printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block);
- if (tmpde)
- kfree(tmpde);
+ kfree(tmpde);
return -EIO;
out_toomany:
@@ -1334,8 +1331,7 @@ static void isofs_read_inode(struct inode *inode)
init_special_inode(inode, inode->i_mode, inode->i_rdev);
out:
- if (tmpde)
- kfree(tmpde);
+ kfree(tmpde);
if (bh)
brelse(bh);
return;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 2a3e310f79ef..002ad2bbc769 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -261,10 +261,8 @@ void journal_commit_transaction(journal_t *journal)
struct buffer_head *bh = jh2bh(jh);
jbd_lock_bh_state(bh);
- if (jh->b_committed_data) {
- kfree(jh->b_committed_data);
- jh->b_committed_data = NULL;
- }
+ kfree(jh->b_committed_data);
+ jh->b_committed_data = NULL;
jbd_unlock_bh_state(bh);
}
journal_refile_buffer(journal, jh);
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index 103c34e4fb28..80d7f53fd0a7 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -210,7 +210,7 @@ do { \
} while (0)
/**
- * int journal_recover(journal_t *journal) - recovers a on-disk journal
+ * journal_recover - recovers a on-disk journal
* @journal: the journal to recover
*
* The primary function for recovering the log contents when mounting a
@@ -266,7 +266,7 @@ int journal_recover(journal_t *journal)
}
/**
- * int journal_skip_recovery() - Start journal and wipe exiting records
+ * journal_skip_recovery - Start journal and wipe exiting records
* @journal: journal to startup
*
* Locate any valid recovery information from the journal and set up the
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 13cb05bf6048..429f4b263cf1 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -227,8 +227,7 @@ repeat_locked:
spin_unlock(&transaction->t_handle_lock);
spin_unlock(&journal->j_state_lock);
out:
- if (new_transaction)
- kfree(new_transaction);
+ kfree(new_transaction);
return ret;
}
@@ -725,8 +724,7 @@ done:
journal_cancel_revoke(handle, jh);
out:
- if (frozen_buffer)
- kfree(frozen_buffer);
+ kfree(frozen_buffer);
JBUFFER_TRACE(jh, "exit");
return error;
@@ -905,8 +903,7 @@ repeat:
jbd_unlock_bh_state(bh);
out:
journal_put_journal_head(jh);
- if (committed_data)
- kfree(committed_data);
+ kfree(committed_data);
return err;
}
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 27f199e94cfc..b2e95421d932 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -462,7 +462,7 @@ jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size, __u32 *result)
}
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
/* Return result */
D3(printk("checksum result: 0x%08x\n", sum));
@@ -1011,12 +1011,12 @@ jffs_scan_flash(struct jffs_control *c)
offset , fmc->sector_size);
flash_safe_release(fmc->mtd);
- kfree (read_buf);
+ kfree(read_buf);
return -1; /* bad, bad, bad! */
}
flash_safe_release(fmc->mtd);
- kfree (read_buf);
+ kfree(read_buf);
return -EAGAIN; /* erased offending sector. Try mount one more time please. */
}
@@ -1112,7 +1112,7 @@ jffs_scan_flash(struct jffs_control *c)
if (!node) {
if (!(node = jffs_alloc_node())) {
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
/* Release the flash device */
flash_safe_release(fmc->mtd);
@@ -1269,7 +1269,7 @@ jffs_scan_flash(struct jffs_control *c)
DJM(no_jffs_node--);
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
/* Release the flash device */
flash_safe_release(fmc->mtd);
@@ -1296,7 +1296,7 @@ jffs_scan_flash(struct jffs_control *c)
flash_safe_release(fmc->flash_part);
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
return -ENOMEM;
}
@@ -1324,7 +1324,7 @@ jffs_scan_flash(struct jffs_control *c)
jffs_build_end(fmc);
/* Free read buffer */
- kfree (read_buf);
+ kfree(read_buf);
if(!num_free_space){
printk(KERN_WARNING "jffs_scan_flash(): Did not find even a single "
@@ -1747,9 +1747,7 @@ jffs_find_child(struct jffs_file *dir, const char *name, int len)
}
printk("jffs_find_child(): Didn't find the file \"%s\".\n",
(copy ? copy : ""));
- if (copy) {
- kfree(copy);
- }
+ kfree(copy);
});
return f;
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 5b2a83599d73..1a96903e3ef3 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -490,7 +490,7 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i
up(&f->sem);
jffs2_do_clear_inode(c, f);
}
- kfree (f);
+ kfree(f);
return ret;
}
@@ -742,10 +742,8 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
/* For symlink inodes we us f->dents to store the target path name */
if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) {
- if (f->dents) {
- kfree(f->dents);
- f->dents = NULL;
- }
+ kfree(f->dents);
+ f->dents = NULL;
} else {
fds = f->dents;
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 316133c626b7..7bc7f2d571f6 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -327,8 +327,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
c->wbuf_ofs = ofs + towrite;
memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len);
/* Don't muck about with c->wbuf_inodes. False positives are harmless. */
- if (buf)
- kfree(buf);
+ kfree(buf);
} else {
/* OK, now we're left with the dregs in whichever buffer we're using */
if (buf) {
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 87332f30141b..c5a33648e9fd 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -112,8 +112,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_
}
}
spin_unlock(&host->h_lock);
- if (new != NULL)
- kfree(new);
+ kfree(new);
return res;
}
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 298997f17475..0f1e4530670f 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -301,8 +301,7 @@ fail:
if (cache) {
while (--m >= 0)
kfree(cache->c_indexes_hash[m]);
- if (cache->c_block_hash)
- kfree(cache->c_block_hash);
+ kfree(cache->c_block_hash);
kfree(cache);
}
return NULL;
diff --git a/fs/namei.c b/fs/namei.c
index c5769c4fcab1..b3f8a1966c9c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1459,7 +1459,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (!error) {
DQUOT_INIT(inode);
- error = do_truncate(dentry, 0);
+ error = do_truncate(dentry, 0, NULL);
}
put_write_access(inode);
if (error)
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 3976c177a7d0..618a327027b3 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -149,8 +149,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
}
}
spin_unlock(&clp->cl_lock);
- if (delegation != NULL)
- kfree(delegation);
+ kfree(delegation);
return status;
}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 24d2fbf549bd..6391d8964214 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1688,8 +1688,7 @@ static void nfs_kill_super(struct super_block *s)
rpciod_down(); /* release rpciod */
- if (server->hostname != NULL)
- kfree(server->hostname);
+ kfree(server->hostname);
kfree(server);
}
@@ -1908,8 +1907,7 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
return ERR_PTR(-ENOMEM);
}
if (copy_from_user(dst, src->data, maxlen)) {
- if (p != NULL)
- kfree(p);
+ kfree(p);
return ERR_PTR(-EFAULT);
}
dst[maxlen] = '\0';
@@ -2000,10 +1998,8 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
out_err:
s = (struct super_block *)p;
out_free:
- if (server->mnt_path)
- kfree(server->mnt_path);
- if (server->hostname)
- kfree(server->hostname);
+ kfree(server->mnt_path);
+ kfree(server->hostname);
kfree(server);
return s;
}
@@ -2023,8 +2019,7 @@ static void nfs4_kill_super(struct super_block *sb)
destroy_nfsv4_state(server);
- if (server->hostname != NULL)
- kfree(server->hostname);
+ kfree(server->hostname);
kfree(server);
}
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 52a26baa114c..0675f3215e0a 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -69,10 +69,8 @@ init_nfsv4_state(struct nfs_server *server)
void
destroy_nfsv4_state(struct nfs_server *server)
{
- if (server->mnt_path) {
- kfree(server->mnt_path);
- server->mnt_path = NULL;
- }
+ kfree(server->mnt_path);
+ server->mnt_path = NULL;
if (server->nfs4_state) {
nfs4_put_client(server->nfs4_state);
server->nfs4_state = NULL;
@@ -311,8 +309,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
new = NULL;
}
spin_unlock(&clp->cl_lock);
- if (new)
- kfree(new);
+ kfree(new);
if (sp != NULL)
return sp;
put_rpccred(cred);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index f732541a3332..d639d172d568 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -52,8 +52,7 @@ nfs_put_unlinkdata(struct nfs_unlinkdata *data)
{
if (--data->count == 0) {
nfs_detach_unlinkdata(data);
- if (data->name.name != NULL)
- kfree(data->name.name);
+ kfree(data->name.name);
kfree(data);
}
}
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 057aff745506..417ec02df44f 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -190,8 +190,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
out:
if (dom)
auth_domain_put(dom);
- if (buf)
- kfree(buf);
+ kfree(buf);
return err;
}
@@ -428,8 +427,7 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
path_release(&nd);
if (dom)
auth_domain_put(dom);
- if (buf)
- kfree(buf);
+ kfree(buf);
return err;
}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index e0e134d6baba..9147b8524d05 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -366,7 +366,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
len = args->len = ntohl(*p++);
hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
- if (rqstp->rq_arg.len < len + hdr)
+ if (rqstp->rq_arg.len < hdr ||
+ rqstp->rq_arg.len - hdr < len)
return 0;
args->vec[0].iov_base = (void*)p;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 4c4146350236..dcd673186944 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -151,8 +151,7 @@ static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
if (nbytes <= sizeof(argp->tmp))
p = argp->tmp;
else {
- if (argp->tmpp)
- kfree(argp->tmpp);
+ kfree(argp->tmpp);
p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
if (!p)
return NULL;
@@ -2476,10 +2475,8 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
kfree(args->ops);
args->ops = args->iops;
}
- if (args->tmpp) {
- kfree(args->tmpp);
- args->tmpp = NULL;
- }
+ kfree(args->tmpp);
+ args->tmpp = NULL;
while (args->to_free) {
struct tmpbuf *tb = args->to_free;
args->to_free = tb->next;
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 119e4d4495b8..d852ebb538e3 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -93,8 +93,7 @@ nfsd_cache_shutdown(void)
cache_disabled = 1;
- if (hash_list)
- kfree (hash_list);
+ kfree (hash_list);
hash_list = NULL;
}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 841c562991e8..a0871b3efeb7 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -23,6 +23,7 @@
#include <linux/seq_file.h>
#include <linux/pagemap.h>
#include <linux/init.h>
+#include <linux/string.h>
#include <linux/nfs.h>
#include <linux/nfsd_idmap.h>
@@ -35,6 +36,8 @@
#include <asm/uaccess.h>
+unsigned int nfsd_versbits = ~0;
+
/*
* We have a single directory with 9 nodes in it.
*/
@@ -50,8 +53,15 @@ enum {
NFSD_List,
NFSD_Fh,
NFSD_Threads,
+ NFSD_Versions,
+ /*
+ * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
+ * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
+ */
+#ifdef CONFIG_NFSD_V4
NFSD_Leasetime,
NFSD_RecoveryDir,
+#endif
};
/*
@@ -66,8 +76,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size);
static ssize_t write_getfs(struct file *file, char *buf, size_t size);
static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
static ssize_t write_threads(struct file *file, char *buf, size_t size);
+static ssize_t write_versions(struct file *file, char *buf, size_t size);
+#ifdef CONFIG_NFSD_V4
static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
+#endif
static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Svc] = write_svc,
@@ -79,8 +92,11 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Getfs] = write_getfs,
[NFSD_Fh] = write_filehandle,
[NFSD_Threads] = write_threads,
+ [NFSD_Versions] = write_versions,
+#ifdef CONFIG_NFSD_V4
[NFSD_Leasetime] = write_leasetime,
[NFSD_RecoveryDir] = write_recoverydir,
+#endif
};
static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -104,9 +120,23 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
return rv;
}
+static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
+{
+ if (! file->private_data) {
+ /* An attempt to read a transaction file without writing
+ * causes a 0-byte write so that the file can return
+ * state information
+ */
+ ssize_t rv = nfsctl_transaction_write(file, buf, 0, pos);
+ if (rv < 0)
+ return rv;
+ }
+ return simple_transaction_read(file, buf, size, pos);
+}
+
static struct file_operations transaction_ops = {
.write = nfsctl_transaction_write,
- .read = simple_transaction_read,
+ .read = nfsctl_transaction_read,
.release = simple_transaction_release,
};
@@ -329,6 +359,70 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
return strlen(buf);
}
+static ssize_t write_versions(struct file *file, char *buf, size_t size)
+{
+ /*
+ * Format:
+ * [-/+]vers [-/+]vers ...
+ */
+ char *mesg = buf;
+ char *vers, sign;
+ int len, num;
+ ssize_t tlen = 0;
+ char *sep;
+
+ if (size>0) {
+ if (nfsd_serv)
+ return -EBUSY;
+ if (buf[size-1] != '\n')
+ return -EINVAL;
+ buf[size-1] = 0;
+
+ vers = mesg;
+ len = qword_get(&mesg, vers, size);
+ if (len <= 0) return -EINVAL;
+ do {
+ sign = *vers;
+ if (sign == '+' || sign == '-')
+ num = simple_strtol((vers+1), NULL, 0);
+ else
+ num = simple_strtol(vers, NULL, 0);
+ switch(num) {
+ case 2:
+ case 3:
+ case 4:
+ if (sign != '-')
+ NFSCTL_VERSET(nfsd_versbits, num);
+ else
+ NFSCTL_VERUNSET(nfsd_versbits, num);
+ break;
+ default:
+ return -EINVAL;
+ }
+ vers += len + 1;
+ tlen += len;
+ } while ((len = qword_get(&mesg, vers, size)) > 0);
+ /* If all get turned off, turn them back on, as
+ * having no versions is BAD
+ */
+ if ((nfsd_versbits & NFSCTL_VERALL)==0)
+ nfsd_versbits = NFSCTL_VERALL;
+ }
+ /* Now write current state into reply buffer */
+ len = 0;
+ sep = "";
+ for (num=2 ; num <= 4 ; num++)
+ if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) {
+ len += sprintf(buf+len, "%s%c%d", sep,
+ NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-',
+ num);
+ sep = " ";
+ }
+ len += sprintf(buf+len, "\n");
+ return len;
+}
+
+#ifdef CONFIG_NFSD_V4
extern time_t nfs4_leasetime(void);
static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
@@ -370,6 +464,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
status = nfs4_reset_recoverydir(recdir);
return strlen(buf);
}
+#endif
/*----------------------------------------------------------------------------*/
/*
@@ -389,6 +484,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
[NFSD_List] = {"exports", &exports_operations, S_IRUGO},
[NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
#ifdef CONFIG_NFSD_V4
[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 1697539a7171..89ed04696865 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -30,6 +30,7 @@
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/stats.h>
#include <linux/nfsd/cache.h>
+#include <linux/nfsd/syscall.h>
#include <linux/lockd/bind.h>
#include <linux/nfsacl.h>
@@ -52,7 +53,7 @@
extern struct svc_program nfsd_program;
static void nfsd(struct svc_rqst *rqstp);
struct timeval nfssvc_boot;
-static struct svc_serv *nfsd_serv;
+ struct svc_serv *nfsd_serv;
static atomic_t nfsd_busy;
static unsigned long nfsd_last_call;
static DEFINE_SPINLOCK(nfsd_call_lock);
@@ -63,6 +64,31 @@ struct nfsd_list {
};
static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
+static struct svc_version * nfsd_version[] = {
+ [2] = &nfsd_version2,
+#if defined(CONFIG_NFSD_V3)
+ [3] = &nfsd_version3,
+#endif
+#if defined(CONFIG_NFSD_V4)
+ [4] = &nfsd_version4,
+#endif
+};
+
+#define NFSD_MINVERS 2
+#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0]))
+static struct svc_version *nfsd_versions[NFSD_NRVERS];
+
+struct svc_program nfsd_program = {
+ .pg_prog = NFS_PROGRAM, /* program number */
+ .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
+ .pg_vers = nfsd_versions, /* version table */
+ .pg_name = "nfsd", /* program name */
+ .pg_class = "nfsd", /* authentication class */
+ .pg_stats = &nfsd_svcstats, /* version table */
+ .pg_authenticate = &svc_set_client, /* export authentication */
+
+};
+
/*
* Maximum number of nfsd processes
*/
@@ -80,11 +106,12 @@ int
nfsd_svc(unsigned short port, int nrservs)
{
int error;
- int none_left;
+ int none_left, found_one, i;
struct list_head *victim;
lock_kernel();
- dprintk("nfsd: creating service\n");
+ dprintk("nfsd: creating service: vers 0x%x\n",
+ nfsd_versbits);
error = -EINVAL;
if (nrservs <= 0)
nrservs = 0;
@@ -99,6 +126,27 @@ nfsd_svc(unsigned short port, int nrservs)
if (error<0)
goto out;
if (!nfsd_serv) {
+ /*
+ * Use the nfsd_ctlbits to define which
+ * versions that will be advertised.
+ * If nfsd_ctlbits doesn't list any version,
+ * export them all.
+ */
+ found_one = 0;
+
+ for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
+ if (NFSCTL_VERISSET(nfsd_versbits, i)) {
+ nfsd_program.pg_vers[i] = nfsd_version[i];
+ found_one = 1;
+ } else
+ nfsd_program.pg_vers[i] = NULL;
+ }
+
+ if (!found_one) {
+ for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++)
+ nfsd_program.pg_vers[i] = nfsd_version[i];
+ }
+
atomic_set(&nfsd_busy, 0);
error = -ENOMEM;
nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE);
@@ -379,6 +427,7 @@ static struct svc_program nfsd_acl_program = {
.pg_name = "nfsd",
.pg_class = "nfsd",
.pg_stats = &nfsd_acl_svcstats,
+ .pg_authenticate = &svc_set_client,
};
static struct svc_stat nfsd_acl_svcstats = {
@@ -389,28 +438,3 @@ static struct svc_stat nfsd_acl_svcstats = {
#else
#define nfsd_acl_program_p NULL
#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
-
-extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
-
-static struct svc_version * nfsd_version[] = {
- [2] = &nfsd_version2,
-#if defined(CONFIG_NFSD_V3)
- [3] = &nfsd_version3,
-#endif
-#if defined(CONFIG_NFSD_V4)
- [4] = &nfsd_version4,
-#endif
-};
-
-#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0]))
-struct svc_program nfsd_program = {
- .pg_next = nfsd_acl_program_p,
- .pg_prog = NFS_PROGRAM, /* program number */
- .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
- .pg_vers = nfsd_version, /* version table */
- .pg_name = "nfsd", /* program name */
- .pg_class = "nfsd", /* authentication class */
- .pg_stats = &nfsd_svcstats, /* version table */
- .pg_authenticate = &svc_set_client, /* export authentication */
-
-};
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 4f2cd3d27566..af7c3c3074b0 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -254,12 +254,19 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
/* Get inode */
err = fh_verify(rqstp, fhp, ftype, accmode);
- if (err || !iap->ia_valid)
+ if (err)
goto out;
dentry = fhp->fh_dentry;
inode = dentry->d_inode;
+ /* Ignore any mode updates on symlinks */
+ if (S_ISLNK(inode->i_mode))
+ iap->ia_valid &= ~ATTR_MODE;
+
+ if (!iap->ia_valid)
+ goto out;
+
/* NFSv2 does not differentiate between "set-[ac]time-to-now"
* which only requires access, and "set-[ac]time-to-X" which
* requires ownership.
diff --git a/fs/open.c b/fs/open.c
index 8d06ec911fd9..6e8136751e9a 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -194,7 +194,7 @@ out:
return error;
}
-int do_truncate(struct dentry *dentry, loff_t length)
+int do_truncate(struct dentry *dentry, loff_t length, struct file *filp)
{
int err;
struct iattr newattrs;
@@ -205,6 +205,10 @@ int do_truncate(struct dentry *dentry, loff_t length)
newattrs.ia_size = length;
newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+ if (filp) {
+ newattrs.ia_file = filp;
+ newattrs.ia_valid |= ATTR_FILE;
+ }
down(&dentry->d_inode->i_sem);
err = notify_change(dentry, &newattrs);
@@ -262,7 +266,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length)
error = locks_verify_truncate(inode, NULL, length);
if (!error) {
DQUOT_INIT(inode);
- error = do_truncate(nd.dentry, length);
+ error = do_truncate(nd.dentry, length, NULL);
}
put_write_access(inode);
@@ -314,7 +318,7 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
error = locks_verify_truncate(inode, file, length);
if (!error)
- error = do_truncate(dentry, length);
+ error = do_truncate(dentry, length, file);
out_putf:
fput(file);
out:
@@ -887,6 +891,10 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
return filp;
}
+/*
+ * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
+ * error.
+ */
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
{
int error;
@@ -894,8 +902,11 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
error = -ENFILE;
f = get_empty_filp();
- if (f == NULL)
+ if (f == NULL) {
+ dput(dentry);
+ mntput(mnt);
return ERR_PTR(error);
+ }
return __dentry_open(dentry, mnt, flags, f, NULL);
}
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 1be11ce96b0f..aeb0106890e4 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -1088,8 +1088,7 @@ static void __exit exit_openprom_fs(void)
unregister_filesystem(&openprom_fs_type);
free_pages ((unsigned long)nodes, alloced);
for (i = 0; i < aliases_nodes; i++)
- if (alias_names [i])
- kfree (alias_names [i]);
+ kfree (alias_names [i]);
nodes = NULL;
}
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index d59dcbf2bd4a..6327bcb2d73d 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -29,7 +29,7 @@
* cyl-cyl-head-head structure
*/
static inline int
-cchh2blk (cchh_t *ptr, struct hd_geometry *geo) {
+cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) {
return ptr->cc * geo->heads * geo->sectors +
ptr->hh * geo->sectors;
}
@@ -40,7 +40,7 @@ cchh2blk (cchh_t *ptr, struct hd_geometry *geo) {
* cyl-cyl-head-head-block structure
*/
static inline int
-cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
+cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
return ptr->cc * geo->heads * geo->sectors +
ptr->hh * geo->sectors +
ptr->b;
@@ -56,7 +56,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
struct hd_geometry *geo;
char type[5] = {0,};
char name[7] = {0,};
- volume_label_t *vlabel;
+ struct vtoc_volume_label *vlabel;
unsigned char *data;
Sector sect;
@@ -64,7 +64,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
goto out_noinfo;
if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
goto out_nogeo;
- if ((vlabel = kmalloc(sizeof(volume_label_t), GFP_KERNEL)) == NULL)
+ if ((vlabel = kmalloc(sizeof(struct vtoc_volume_label),
+ GFP_KERNEL)) == NULL)
goto out_novlab;
if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
@@ -86,7 +87,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
strncpy(name, data + 8, 6);
else
strncpy(name, data + 4, 6);
- memcpy (vlabel, data, sizeof(volume_label_t));
+ memcpy (vlabel, data, sizeof(struct vtoc_volume_label));
put_dev_sector(sect);
EBCASC(type, 4);
@@ -129,9 +130,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
counter = 0;
while ((data = read_dev_sector(bdev, blk*(blocksize/512),
&sect)) != NULL) {
- format1_label_t f1;
+ struct vtoc_format1_label f1;
- memcpy(&f1, data, sizeof(format1_label_t));
+ memcpy(&f1, data, sizeof(struct vtoc_format1_label));
put_dev_sector(sect);
/* skip FMT4 / FMT5 / FMT7 labels */
diff --git a/fs/quota.c b/fs/quota.c
index 1df7832b4e08..612e04db4b93 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -15,6 +15,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/buffer_head.h>
+#include <linux/quotaops.h>
/* Check validity of generic quotactl commands */
static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index 2d85dd7415bb..a0f296d9928a 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -786,8 +786,7 @@ int smb_request_recv(struct smb_sb_info *server)
/* We should never be called with any of these states */
case SMB_RECV_END:
case SMB_RECV_REQUEST:
- server->rstate = SMB_RECV_END;
- break;
+ BUG();
}
if (result < 0) {
diff --git a/fs/smbfs/symlink.c b/fs/smbfs/symlink.c
index 0c64bc3a0127..cdc53c4fb381 100644
--- a/fs/smbfs/symlink.c
+++ b/fs/smbfs/symlink.c
@@ -45,7 +45,7 @@ static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd)
int len = smb_proc_read_link(server_from_dentry(dentry),
dentry, link, PATH_MAX - 1);
if (len < 0) {
- putname(link);
+ __putname(link);
link = ERR_PTR(len);
} else {
link[len] = 0;
@@ -59,7 +59,7 @@ static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
{
char *s = nd_get_link(nd);
if (!IS_ERR(s))
- putname(s);
+ __putname(s);
}
struct inode_operations smb_link_inode_operations =
diff --git a/fs/super.c b/fs/super.c
index f60155ec7780..eed6c3132905 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -474,8 +474,6 @@ rescan:
return NULL;
}
-EXPORT_SYMBOL(user_get_super);
-
asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf)
{
struct super_block *s;
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 0e54922daa09..663669810be6 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -39,8 +39,7 @@ static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
{\
if (UDF_SB(X))\
{\
- if (UDF_SB_PARTMAPS(X))\
- kfree(UDF_SB_PARTMAPS(X));\
+ kfree(UDF_SB_PARTMAPS(X));\
UDF_SB_PARTMAPS(X) = NULL;\
}\
}
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index f036d694ba5a..54828ebcf1ba 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -472,13 +472,14 @@ static int ufs_read_cylinder_structures (struct super_block *sb) {
return 1;
failed:
- if (base) kfree (base);
+ kfree (base);
if (sbi->s_ucg) {
for (i = 0; i < uspi->s_ncg; i++)
- if (sbi->s_ucg[i]) brelse (sbi->s_ucg[i]);
+ if (sbi->s_ucg[i])
+ brelse (sbi->s_ucg[i]);
kfree (sbi->s_ucg);
for (i = 0; i < UFS_MAX_GROUP_LOADED; i++)
- if (sbi->s_ucpi[i]) kfree (sbi->s_ucpi[i]);
+ kfree (sbi->s_ucpi[i]);
}
UFSD(("EXIT (FAILED)\n"))
return 0;
@@ -981,9 +982,10 @@ magic_found:
dalloc_failed:
iput(inode);
failed:
- if (ubh) ubh_brelse_uspi (uspi);
- if (uspi) kfree (uspi);
- if (sbi) kfree(sbi);
+ if (ubh)
+ ubh_brelse_uspi (uspi);
+ kfree (uspi);
+ kfree(sbi);
sb->s_fs_info = NULL;
UFSD(("EXIT (FAILED)\n"))
return -EINVAL;
diff --git a/fs/xattr.c b/fs/xattr.c
index f6e00c0e114f..a9db22557998 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -74,8 +74,7 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
}
out:
up(&d->d_inode->i_sem);
- if (kvalue)
- kfree(kvalue);
+ kfree(kvalue);
return error;
}
@@ -173,8 +172,7 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
error = -E2BIG;
}
out:
- if (kvalue)
- kfree(kvalue);
+ kfree(kvalue);
return error;
}
@@ -259,8 +257,7 @@ listxattr(struct dentry *d, char __user *list, size_t size)
error = -E2BIG;
}
out:
- if (klist)
- kfree(klist);
+ kfree(klist);
return error;
}
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 8f82c1a20dc5..c64a29cdfff3 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -30,8 +30,8 @@
#define KM_NOFS 0x0004u
#define KM_MAYFAIL 0x0008u
-#define kmem_zone kmem_cache_s
-#define kmem_zone_t kmem_cache_t
+#define kmem_zone kmem_cache
+#define kmem_zone_t struct kmem_cache
typedef unsigned long xfs_pflags_t;
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 8393bf374b2b..a985cd29b6db 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -17,6 +17,9 @@
#include <asm/processor.h> /* For TASK_SIZE */
#include <asm/machvec.h>
+struct mm_struct;
+struct vm_area_struct;
+
/* Certain architectures need to do special things when PTEs
* within a page table are directly modified. Thus, the following
* hook is made available.
diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h
index d462c5e14c13..072375c135b4 100644
--- a/include/asm-alpha/ptrace.h
+++ b/include/asm-alpha/ptrace.h
@@ -67,6 +67,9 @@ struct switch_stack {
};
#ifdef __KERNEL__
+
+#define __ARCH_SYS_PTRACE 1
+
#define user_mode(regs) (((regs)->ps & 8) != 0)
#define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs)
diff --git a/include/asm-cris/arch-v10/byteorder.h b/include/asm-cris/arch-v10/byteorder.h
index e24465d1f40d..255b646b7fa8 100644
--- a/include/asm-cris/arch-v10/byteorder.h
+++ b/include/asm-cris/arch-v10/byteorder.h
@@ -9,14 +9,14 @@
* them together into ntohl etc.
*/
-extern __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
{
__asm__ ("swapwb %0" : "=r" (x) : "0" (x));
return(x);
}
-extern __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
+static inline __attribute_const__ __u16 ___arch__swab16(__u16 x)
{
__asm__ ("swapb %0" : "=r" (x) : "0" (x));
diff --git a/include/asm-cris/arch-v10/checksum.h b/include/asm-cris/arch-v10/checksum.h
index fde1d00aaa90..633f234f336b 100644
--- a/include/asm-cris/arch-v10/checksum.h
+++ b/include/asm-cris/arch-v10/checksum.h
@@ -8,7 +8,7 @@
* to split all of those into 16-bit components, then add.
*/
-extern inline unsigned int
+static inline unsigned int
csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
unsigned short proto, unsigned int sum)
{
diff --git a/include/asm-cris/arch-v10/delay.h b/include/asm-cris/arch-v10/delay.h
index cfedae0d2f53..39481f6e0c30 100644
--- a/include/asm-cris/arch-v10/delay.h
+++ b/include/asm-cris/arch-v10/delay.h
@@ -1,7 +1,7 @@
#ifndef _CRIS_ARCH_DELAY_H
#define _CRIS_ARCH_DELAY_H
-extern __inline__ void __delay(int loops)
+static inline void __delay(int loops)
{
__asm__ __volatile__ (
"move.d %0,$r9\n\t"
diff --git a/include/asm-cris/arch-v10/ide.h b/include/asm-cris/arch-v10/ide.h
index 8cf2d7cb22ac..78b301ed7b12 100644
--- a/include/asm-cris/arch-v10/ide.h
+++ b/include/asm-cris/arch-v10/ide.h
@@ -25,7 +25,7 @@
#define MAX_HWIFS 4
-extern __inline__ int ide_default_irq(unsigned long base)
+static inline int ide_default_irq(unsigned long base)
{
/* all IDE busses share the same IRQ, number 4.
* this has the side-effect that ide-probe.c will cluster our 4 interfaces
@@ -35,7 +35,7 @@ extern __inline__ int ide_default_irq(unsigned long base)
return 4;
}
-extern __inline__ unsigned long ide_default_io_base(int index)
+static inline unsigned long ide_default_io_base(int index)
{
/* we have no real I/O base address per interface, since all go through the
* same register. but in a bitfield in that register, we have the i/f number.
@@ -54,7 +54,7 @@ extern __inline__ unsigned long ide_default_io_base(int index)
* of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us.
*/
-extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq)
+static inline void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq)
{
int i;
@@ -77,7 +77,7 @@ extern __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_por
hw->io_ports[IDE_IRQ_OFFSET] = 0;
}
-extern __inline__ void ide_init_default_hwifs(void)
+static inline void ide_init_default_hwifs(void)
{
hw_regs_t hw;
int index;
diff --git a/include/asm-cris/arch-v10/system.h b/include/asm-cris/arch-v10/system.h
index 6cc35642b8ab..1ac7b639b1b0 100644
--- a/include/asm-cris/arch-v10/system.h
+++ b/include/asm-cris/arch-v10/system.h
@@ -5,7 +5,7 @@
/* read the CPU version register */
-extern inline unsigned long rdvr(void) {
+static inline unsigned long rdvr(void) {
unsigned char vr;
__asm__ volatile ("move $vr,%0" : "=rm" (vr));
return vr;
@@ -15,7 +15,7 @@ extern inline unsigned long rdvr(void) {
/* read/write the user-mode stackpointer */
-extern inline unsigned long rdusp(void) {
+static inline unsigned long rdusp(void) {
unsigned long usp;
__asm__ __volatile__("move $usp,%0" : "=rm" (usp));
return usp;
@@ -26,13 +26,13 @@ extern inline unsigned long rdusp(void) {
/* read the current stackpointer */
-extern inline unsigned long rdsp(void) {
+static inline unsigned long rdsp(void) {
unsigned long sp;
__asm__ __volatile__("move.d $sp,%0" : "=rm" (sp));
return sp;
}
-extern inline unsigned long _get_base(char * addr)
+static inline unsigned long _get_base(char * addr)
{
return 0;
}
diff --git a/include/asm-cris/arch-v10/thread_info.h b/include/asm-cris/arch-v10/thread_info.h
index 357f5df0c907..218f4152d3e5 100644
--- a/include/asm-cris/arch-v10/thread_info.h
+++ b/include/asm-cris/arch-v10/thread_info.h
@@ -2,7 +2,7 @@
#define _ASM_ARCH_THREAD_INFO_H
/* how to get the thread information struct from C */
-extern inline struct thread_info *current_thread_info(void)
+static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
__asm__("and.d $sp,%0; ":"=r" (ti) : "0" (~8191UL));
diff --git a/include/asm-cris/arch-v10/timex.h b/include/asm-cris/arch-v10/timex.h
index ecfc553c06a5..e48447d94faf 100644
--- a/include/asm-cris/arch-v10/timex.h
+++ b/include/asm-cris/arch-v10/timex.h
@@ -22,7 +22,7 @@
unsigned long get_ns_in_jiffie(void);
-extern inline unsigned long get_us_in_jiffie_highres(void)
+static inline unsigned long get_us_in_jiffie_highres(void)
{
return get_ns_in_jiffie()/1000;
}
diff --git a/include/asm-cris/arch-v10/uaccess.h b/include/asm-cris/arch-v10/uaccess.h
index 787d2e60c83c..65b02d9b605a 100644
--- a/include/asm-cris/arch-v10/uaccess.h
+++ b/include/asm-cris/arch-v10/uaccess.h
@@ -87,7 +87,7 @@
* bytes copied if we hit a null byte
* (without the null byte)
*/
-extern inline long
+static inline long
__do_strncpy_from_user(char *dst, const char *src, long count)
{
long res;
@@ -602,7 +602,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count)
* or 0 for error. Return a value greater than N if too long.
*/
-extern inline long
+static inline long
strnlen_user(const char *s, long n)
{
long res, tmp1;
diff --git a/include/asm-cris/arch-v32/bitops.h b/include/asm-cris/arch-v32/bitops.h
index e40a58d3b862..147689d6b624 100644
--- a/include/asm-cris/arch-v32/bitops.h
+++ b/include/asm-cris/arch-v32/bitops.h
@@ -8,7 +8,7 @@
* inverts all bits in the input.
*/
-extern inline unsigned long
+static inline unsigned long
cris_swapnwbrlz(unsigned long w)
{
unsigned long res;
@@ -20,7 +20,7 @@ cris_swapnwbrlz(unsigned long w)
return res;
}
-extern inline unsigned long
+static inline unsigned long
cris_swapwbrlz(unsigned long w)
{
unsigned long res;
@@ -36,7 +36,7 @@ cris_swapwbrlz(unsigned long w)
* Find First Zero in word. Undefined if no zero exist, so the caller should
* check against ~0 first.
*/
-extern inline unsigned long
+static inline unsigned long
ffz(unsigned long w)
{
return cris_swapnwbrlz(w);
@@ -46,7 +46,7 @@ ffz(unsigned long w)
* Find First Set bit in word. Undefined if no 1 exist, so the caller
* should check against 0 first.
*/
-extern inline unsigned long
+static inline unsigned long
__ffs(unsigned long w)
{
return cris_swapnwbrlz(~w);
@@ -55,7 +55,7 @@ __ffs(unsigned long w)
/*
* Find First Bit that is set.
*/
-extern inline unsigned long
+static inline unsigned long
kernel_ffs(unsigned long w)
{
return w ? cris_swapwbrlz (w) + 1 : 0;
diff --git a/include/asm-cris/arch-v32/byteorder.h b/include/asm-cris/arch-v32/byteorder.h
index 74846ee6cf99..6ef8fb4a35f2 100644
--- a/include/asm-cris/arch-v32/byteorder.h
+++ b/include/asm-cris/arch-v32/byteorder.h
@@ -3,14 +3,14 @@
#include <asm/types.h>
-extern __inline__ __const__ __u32
+static inline __const__ __u32
___arch__swab32(__u32 x)
{
__asm__ __volatile__ ("swapwb %0" : "=r" (x) : "0" (x));
return (x);
}
-extern __inline__ __const__ __u16
+static inline __const__ __u16
___arch__swab16(__u16 x)
{
__asm__ __volatile__ ("swapb %0" : "=r" (x) : "0" (x));
diff --git a/include/asm-cris/arch-v32/checksum.h b/include/asm-cris/arch-v32/checksum.h
index a1d6b2a6cc44..97ef89efea62 100644
--- a/include/asm-cris/arch-v32/checksum.h
+++ b/include/asm-cris/arch-v32/checksum.h
@@ -9,7 +9,7 @@
* checksum. Which means it would be necessary to split all those into
* 16-bit components and then add.
*/
-extern inline unsigned int
+static inline unsigned int
csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
unsigned short len, unsigned short proto, unsigned int sum)
{
diff --git a/include/asm-cris/arch-v32/delay.h b/include/asm-cris/arch-v32/delay.h
index f36f7f760e89..b6e941e637de 100644
--- a/include/asm-cris/arch-v32/delay.h
+++ b/include/asm-cris/arch-v32/delay.h
@@ -1,7 +1,7 @@
#ifndef _ASM_CRIS_ARCH_DELAY_H
#define _ASM_CRIS_ARCH_DELAY_H
-extern __inline__ void
+static inline void
__delay(int loops)
{
__asm__ __volatile__ (
diff --git a/include/asm-cris/arch-v32/ide.h b/include/asm-cris/arch-v32/ide.h
index 24f5604f566a..6590f657500d 100644
--- a/include/asm-cris/arch-v32/ide.h
+++ b/include/asm-cris/arch-v32/ide.h
@@ -26,7 +26,7 @@
#define MAX_HWIFS 4
-extern __inline__ int ide_default_irq(unsigned long base)
+static inline int ide_default_irq(unsigned long base)
{
/* all IDE busses share the same IRQ,
* this has the side-effect that ide-probe.c will cluster our 4 interfaces
@@ -36,7 +36,7 @@ extern __inline__ int ide_default_irq(unsigned long base)
return ATA_INTR_VECT;
}
-extern __inline__ unsigned long ide_default_io_base(int index)
+static inline unsigned long ide_default_io_base(int index)
{
reg_ata_rw_ctrl2 ctrl2 = {.sel = index};
/* we have no real I/O base address per interface, since all go through the
diff --git a/include/asm-cris/arch-v32/io.h b/include/asm-cris/arch-v32/io.h
index 4c80263ec634..043c9ce5294e 100644
--- a/include/asm-cris/arch-v32/io.h
+++ b/include/asm-cris/arch-v32/io.h
@@ -35,7 +35,7 @@ extern struct crisv32_iopin crisv32_led2_red;
extern struct crisv32_iopin crisv32_led3_green;
extern struct crisv32_iopin crisv32_led3_red;
-extern inline void crisv32_io_set(struct crisv32_iopin* iopin,
+static inline void crisv32_io_set(struct crisv32_iopin* iopin,
int val)
{
if (val)
@@ -44,7 +44,7 @@ extern inline void crisv32_io_set(struct crisv32_iopin* iopin,
*iopin->port->data &= ~iopin->bit;
}
-extern inline void crisv32_io_set_dir(struct crisv32_iopin* iopin,
+static inline void crisv32_io_set_dir(struct crisv32_iopin* iopin,
enum crisv32_io_dir dir)
{
if (dir == crisv32_io_dir_in)
@@ -53,7 +53,7 @@ extern inline void crisv32_io_set_dir(struct crisv32_iopin* iopin,
*iopin->port->oe |= iopin->bit;
}
-extern inline int crisv32_io_rd(struct crisv32_iopin* iopin)
+static inline int crisv32_io_rd(struct crisv32_iopin* iopin)
{
return ((*iopin->port->data_in & iopin->bit) ? 1 : 0);
}
diff --git a/include/asm-cris/arch-v32/system.h b/include/asm-cris/arch-v32/system.h
index b9afbb95e0bb..a3d75d581e2f 100644
--- a/include/asm-cris/arch-v32/system.h
+++ b/include/asm-cris/arch-v32/system.h
@@ -4,7 +4,7 @@
#include <linux/config.h>
/* Read the CPU version register. */
-extern inline unsigned long rdvr(void)
+static inline unsigned long rdvr(void)
{
unsigned char vr;
@@ -15,7 +15,7 @@ extern inline unsigned long rdvr(void)
#define cris_machine_name "crisv32"
/* Read the user-mode stack pointer. */
-extern inline unsigned long rdusp(void)
+static inline unsigned long rdusp(void)
{
unsigned long usp;
@@ -24,7 +24,7 @@ extern inline unsigned long rdusp(void)
}
/* Read the current stack pointer. */
-extern inline unsigned long rdsp(void)
+static inline unsigned long rdsp(void)
{
unsigned long sp;
diff --git a/include/asm-cris/arch-v32/thread_info.h b/include/asm-cris/arch-v32/thread_info.h
index a7a182307da0..d6936956a3c6 100644
--- a/include/asm-cris/arch-v32/thread_info.h
+++ b/include/asm-cris/arch-v32/thread_info.h
@@ -2,7 +2,7 @@
#define _ASM_CRIS_ARCH_THREAD_INFO_H
/* Return a thread_info struct. */
-extern inline struct thread_info *current_thread_info(void)
+static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
diff --git a/include/asm-cris/arch-v32/timex.h b/include/asm-cris/arch-v32/timex.h
index 4d0fd23b21e9..5a4aa285d5fd 100644
--- a/include/asm-cris/arch-v32/timex.h
+++ b/include/asm-cris/arch-v32/timex.h
@@ -22,7 +22,7 @@
extern unsigned long get_ns_in_jiffie(void);
-extern inline unsigned long get_us_in_jiffie_highres(void)
+static inline unsigned long get_us_in_jiffie_highres(void)
{
return get_ns_in_jiffie() / 1000;
}
diff --git a/include/asm-cris/arch-v32/uaccess.h b/include/asm-cris/arch-v32/uaccess.h
index 055a0bdbe835..6b207f1b6622 100644
--- a/include/asm-cris/arch-v32/uaccess.h
+++ b/include/asm-cris/arch-v32/uaccess.h
@@ -93,7 +93,7 @@
* bytes copied if we hit a null byte
* (without the null byte)
*/
-extern inline long
+static inline long
__do_strncpy_from_user(char *dst, const char *src, long count)
{
long res;
@@ -695,7 +695,7 @@ __do_strncpy_from_user(char *dst, const char *src, long count)
* or 0 for error. Return a value greater than N if too long.
*/
-extern inline long
+static inline long
strnlen_user(const char *s, long n)
{
long res, tmp1;
diff --git a/include/asm-cris/atomic.h b/include/asm-cris/atomic.h
index 70605b09e8b7..8c2e78304523 100644
--- a/include/asm-cris/atomic.h
+++ b/include/asm-cris/atomic.h
@@ -20,7 +20,7 @@ typedef struct { volatile int counter; } atomic_t;
/* These should be written in asm but we do it in C for now. */
-extern __inline__ void atomic_add(int i, volatile atomic_t *v)
+static inline void atomic_add(int i, volatile atomic_t *v)
{
unsigned long flags;
cris_atomic_save(v, flags);
@@ -28,7 +28,7 @@ extern __inline__ void atomic_add(int i, volatile atomic_t *v)
cris_atomic_restore(v, flags);
}
-extern __inline__ void atomic_sub(int i, volatile atomic_t *v)
+static inline void atomic_sub(int i, volatile atomic_t *v)
{
unsigned long flags;
cris_atomic_save(v, flags);
@@ -36,7 +36,7 @@ extern __inline__ void atomic_sub(int i, volatile atomic_t *v)
cris_atomic_restore(v, flags);
}
-extern __inline__ int atomic_add_return(int i, volatile atomic_t *v)
+static inline int atomic_add_return(int i, volatile atomic_t *v)
{
unsigned long flags;
int retval;
@@ -48,7 +48,7 @@ extern __inline__ int atomic_add_return(int i, volatile atomic_t *v)
#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
-extern __inline__ int atomic_sub_return(int i, volatile atomic_t *v)
+static inline int atomic_sub_return(int i, volatile atomic_t *v)
{
unsigned long flags;
int retval;
@@ -58,7 +58,7 @@ extern __inline__ int atomic_sub_return(int i, volatile atomic_t *v)
return retval;
}
-extern __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v)
+static inline int atomic_sub_and_test(int i, volatile atomic_t *v)
{
int retval;
unsigned long flags;
@@ -68,7 +68,7 @@ extern __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v)
return retval;
}
-extern __inline__ void atomic_inc(volatile atomic_t *v)
+static inline void atomic_inc(volatile atomic_t *v)
{
unsigned long flags;
cris_atomic_save(v, flags);
@@ -76,7 +76,7 @@ extern __inline__ void atomic_inc(volatile atomic_t *v)
cris_atomic_restore(v, flags);
}
-extern __inline__ void atomic_dec(volatile atomic_t *v)
+static inline void atomic_dec(volatile atomic_t *v)
{
unsigned long flags;
cris_atomic_save(v, flags);
@@ -84,7 +84,7 @@ extern __inline__ void atomic_dec(volatile atomic_t *v)
cris_atomic_restore(v, flags);
}
-extern __inline__ int atomic_inc_return(volatile atomic_t *v)
+static inline int atomic_inc_return(volatile atomic_t *v)
{
unsigned long flags;
int retval;
@@ -94,7 +94,7 @@ extern __inline__ int atomic_inc_return(volatile atomic_t *v)
return retval;
}
-extern __inline__ int atomic_dec_return(volatile atomic_t *v)
+static inline int atomic_dec_return(volatile atomic_t *v)
{
unsigned long flags;
int retval;
@@ -103,7 +103,7 @@ extern __inline__ int atomic_dec_return(volatile atomic_t *v)
cris_atomic_restore(v, flags);
return retval;
}
-extern __inline__ int atomic_dec_and_test(volatile atomic_t *v)
+static inline int atomic_dec_and_test(volatile atomic_t *v)
{
int retval;
unsigned long flags;
@@ -113,7 +113,7 @@ extern __inline__ int atomic_dec_and_test(volatile atomic_t *v)
return retval;
}
-extern __inline__ int atomic_inc_and_test(volatile atomic_t *v)
+static inline int atomic_inc_and_test(volatile atomic_t *v)
{
int retval;
unsigned long flags;
diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h
index e3da57f97964..1bddb3f3a289 100644
--- a/include/asm-cris/bitops.h
+++ b/include/asm-cris/bitops.h
@@ -89,7 +89,7 @@ struct __dummy { unsigned long a[100]; };
* It also implies a memory barrier.
*/
-extern inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
{
unsigned int mask, retval;
unsigned long flags;
@@ -105,7 +105,7 @@ extern inline int test_and_set_bit(int nr, volatile unsigned long *addr)
return retval;
}
-extern inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
{
unsigned int mask, retval;
unsigned int *adr = (unsigned int *)addr;
@@ -132,7 +132,7 @@ extern inline int __test_and_set_bit(int nr, volatile unsigned long *addr)
* It also implies a memory barrier.
*/
-extern inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
{
unsigned int mask, retval;
unsigned long flags;
@@ -157,7 +157,7 @@ extern inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
* but actually fail. You must protect multiple accesses with a lock.
*/
-extern inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
{
unsigned int mask, retval;
unsigned int *adr = (unsigned int *)addr;
@@ -177,7 +177,7 @@ extern inline int __test_and_clear_bit(int nr, volatile unsigned long *addr)
* It also implies a memory barrier.
*/
-extern inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
{
unsigned int mask, retval;
unsigned long flags;
@@ -193,7 +193,7 @@ extern inline int test_and_change_bit(int nr, volatile unsigned long *addr)
/* WARNING: non atomic and it can be reordered! */
-extern inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
+static inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
{
unsigned int mask, retval;
unsigned int *adr = (unsigned int *)addr;
@@ -214,7 +214,7 @@ extern inline int __test_and_change_bit(int nr, volatile unsigned long *addr)
* This routine doesn't need to be atomic.
*/
-extern inline int test_bit(int nr, const volatile unsigned long *addr)
+static inline int test_bit(int nr, const volatile unsigned long *addr)
{
unsigned int mask;
unsigned int *adr = (unsigned int *)addr;
@@ -258,7 +258,7 @@ extern inline int test_bit(int nr, const volatile unsigned long *addr)
* @offset: The bitnumber to start searching at
* @size: The maximum size to search
*/
-extern inline int find_next_zero_bit (const unsigned long * addr, int size, int offset)
+static inline int find_next_zero_bit (const unsigned long * addr, int size, int offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
unsigned long result = offset & ~31UL;
@@ -366,7 +366,7 @@ found_middle:
#define minix_test_bit(nr,addr) test_bit(nr,addr)
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
-extern inline int sched_find_first_bit(const unsigned long *b)
+static inline int sched_find_first_bit(const unsigned long *b)
{
if (unlikely(b[0]))
return __ffs(b[0]);
diff --git a/include/asm-cris/checksum.h b/include/asm-cris/checksum.h
index 15ca8aec5c63..26a7719bbb84 100644
--- a/include/asm-cris/checksum.h
+++ b/include/asm-cris/checksum.h
@@ -34,7 +34,7 @@ unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
* Fold a partial checksum into a word
*/
-extern inline unsigned int csum_fold(unsigned int sum)
+static inline unsigned int csum_fold(unsigned int sum)
{
/* the while loop is unnecessary really, it's always enough with two
iterations */
@@ -55,7 +55,7 @@ extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
*
*/
-extern inline unsigned short ip_fast_csum(unsigned char * iph,
+static inline unsigned short ip_fast_csum(unsigned char * iph,
unsigned int ihl)
{
return csum_fold(csum_partial(iph, ihl * 4, 0));
@@ -66,7 +66,7 @@ extern inline unsigned short ip_fast_csum(unsigned char * iph,
* returns a 16-bit checksum, already complemented
*/
-extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
unsigned long daddr,
unsigned short len,
unsigned short proto,
@@ -80,7 +80,7 @@ extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
* in icmp.c
*/
-extern inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
return csum_fold (csum_partial(buff, len, 0));
}
diff --git a/include/asm-cris/current.h b/include/asm-cris/current.h
index dce69c99da39..5f5c0efd00be 100644
--- a/include/asm-cris/current.h
+++ b/include/asm-cris/current.h
@@ -5,7 +5,7 @@
struct task_struct;
-extern inline struct task_struct * get_current(void)
+static inline struct task_struct * get_current(void)
{
return current_thread_info()->task;
}
diff --git a/include/asm-cris/delay.h b/include/asm-cris/delay.h
index efc41aad4845..d3a397803719 100644
--- a/include/asm-cris/delay.h
+++ b/include/asm-cris/delay.h
@@ -13,7 +13,7 @@
extern unsigned long loops_per_usec; /* arch/cris/mm/init.c */
-extern __inline__ void udelay(unsigned long usecs)
+static inline void udelay(unsigned long usecs)
{
__delay(usecs * loops_per_usec);
}
diff --git a/include/asm-cris/io.h b/include/asm-cris/io.h
index 16e791b3c721..716c69bc58f8 100644
--- a/include/asm-cris/io.h
+++ b/include/asm-cris/io.h
@@ -23,12 +23,12 @@ extern struct cris_io_operations *cris_iops;
* Change virtual addresses to physical addresses and vv.
*/
-extern inline unsigned long virt_to_phys(volatile void * address)
+static inline unsigned long virt_to_phys(volatile void * address)
{
return __pa(address);
}
-extern inline void * phys_to_virt(unsigned long address)
+static inline void * phys_to_virt(unsigned long address)
{
return __va(address);
}
@@ -36,7 +36,7 @@ extern inline void * phys_to_virt(unsigned long address)
extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
extern void __iomem * __ioremap_prot(unsigned long phys_addr, unsigned long size, pgprot_t prot);
-extern inline void __iomem * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap (unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, 0);
}
diff --git a/include/asm-cris/irq.h b/include/asm-cris/irq.h
index 4fab5c3b2e15..4b338792218b 100644
--- a/include/asm-cris/irq.h
+++ b/include/asm-cris/irq.h
@@ -8,7 +8,7 @@
#include <asm/arch/irq.h>
-extern __inline__ int irq_canonicalize(int irq)
+static inline int irq_canonicalize(int irq)
{
return irq;
}
diff --git a/include/asm-cris/pgalloc.h b/include/asm-cris/pgalloc.h
index a131776edf41..deaddfe79bbc 100644
--- a/include/asm-cris/pgalloc.h
+++ b/include/asm-cris/pgalloc.h
@@ -11,35 +11,35 @@
* Allocate and free page tables.
*/
-extern inline pgd_t *pgd_alloc (struct mm_struct *mm)
+static inline pgd_t *pgd_alloc (struct mm_struct *mm)
{
return (pgd_t *)get_zeroed_page(GFP_KERNEL);
}
-extern inline void pgd_free (pgd_t *pgd)
+static inline void pgd_free (pgd_t *pgd)
{
free_page((unsigned long)pgd);
}
-extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
return pte;
}
-extern inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
return pte;
}
-extern inline void pte_free_kernel(pte_t *pte)
+static inline void pte_free_kernel(pte_t *pte)
{
free_page((unsigned long)pte);
}
-extern inline void pte_free(struct page *pte)
+static inline void pte_free(struct page *pte)
{
__free_page(pte);
}
diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
index a9143bed99db..70a832514f62 100644
--- a/include/asm-cris/pgtable.h
+++ b/include/asm-cris/pgtable.h
@@ -112,44 +112,44 @@ extern unsigned long empty_zero_page;
* Undefined behaviour if not..
*/
-extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
-extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
-extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
-extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
-
-extern inline pte_t pte_wrprotect(pte_t pte)
+static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_READ; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+
+static inline pte_t pte_wrprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
return pte;
}
-extern inline pte_t pte_rdprotect(pte_t pte)
+static inline pte_t pte_rdprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
return pte;
}
-extern inline pte_t pte_exprotect(pte_t pte)
+static inline pte_t pte_exprotect(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
return pte;
}
-extern inline pte_t pte_mkclean(pte_t pte)
+static inline pte_t pte_mkclean(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE);
return pte;
}
-extern inline pte_t pte_mkold(pte_t pte)
+static inline pte_t pte_mkold(pte_t pte)
{
pte_val(pte) &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ);
return pte;
}
-extern inline pte_t pte_mkwrite(pte_t pte)
+static inline pte_t pte_mkwrite(pte_t pte)
{
pte_val(pte) |= _PAGE_WRITE;
if (pte_val(pte) & _PAGE_MODIFIED)
@@ -157,7 +157,7 @@ extern inline pte_t pte_mkwrite(pte_t pte)
return pte;
}
-extern inline pte_t pte_mkread(pte_t pte)
+static inline pte_t pte_mkread(pte_t pte)
{
pte_val(pte) |= _PAGE_READ;
if (pte_val(pte) & _PAGE_ACCESSED)
@@ -165,7 +165,7 @@ extern inline pte_t pte_mkread(pte_t pte)
return pte;
}
-extern inline pte_t pte_mkexec(pte_t pte)
+static inline pte_t pte_mkexec(pte_t pte)
{
pte_val(pte) |= _PAGE_READ;
if (pte_val(pte) & _PAGE_ACCESSED)
@@ -173,7 +173,7 @@ extern inline pte_t pte_mkexec(pte_t pte)
return pte;
}
-extern inline pte_t pte_mkdirty(pte_t pte)
+static inline pte_t pte_mkdirty(pte_t pte)
{
pte_val(pte) |= _PAGE_MODIFIED;
if (pte_val(pte) & _PAGE_WRITE)
@@ -181,7 +181,7 @@ extern inline pte_t pte_mkdirty(pte_t pte)
return pte;
}
-extern inline pte_t pte_mkyoung(pte_t pte)
+static inline pte_t pte_mkyoung(pte_t pte)
{
pte_val(pte) |= _PAGE_ACCESSED;
if (pte_val(pte) & _PAGE_READ)
@@ -205,7 +205,7 @@ extern inline pte_t pte_mkyoung(pte_t pte)
* addresses (the 0xc0xxxxxx's) goes as void *'s.
*/
-extern inline pte_t __mk_pte(void * page, pgprot_t pgprot)
+static inline pte_t __mk_pte(void * page, pgprot_t pgprot)
{
pte_t pte;
/* the PTE needs a physical address */
@@ -223,7 +223,7 @@ extern inline pte_t __mk_pte(void * page, pgprot_t pgprot)
__pte; \
})
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
@@ -232,7 +232,7 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* pte_pagenr refers to the page-number counted starting from the virtual DRAM start
*/
-extern inline unsigned long __pte_page(pte_t pte)
+static inline unsigned long __pte_page(pte_t pte)
{
/* the PTE contains a physical address */
return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
@@ -250,7 +250,7 @@ extern inline unsigned long __pte_page(pte_t pte)
* don't need the __pa and __va transformations.
*/
-extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
{ pmd_val(*pmdp) = _PAGE_TABLE | (unsigned long) ptep; }
#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
@@ -260,7 +260,7 @@ extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
/* to find an entry in a page-table-directory */
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
{
return mm->pgd + pgd_index(address);
}
@@ -296,7 +296,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
*
* Actually I am not sure on what this could be used for.
*/
-extern inline void update_mmu_cache(struct vm_area_struct * vma,
+static inline void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t pte)
{
}
diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h
index 0dc218117bd8..dce41009eeb0 100644
--- a/include/asm-cris/processor.h
+++ b/include/asm-cris/processor.h
@@ -16,6 +16,8 @@
#include <asm/ptrace.h>
#include <asm/arch/processor.h>
+struct task_struct;
+
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
@@ -45,7 +47,7 @@
#define current_regs() user_regs(current->thread_info)
-extern inline void prepare_to_copy(struct task_struct *tsk)
+static inline void prepare_to_copy(struct task_struct *tsk)
{
}
@@ -58,7 +60,7 @@ unsigned long get_wchan(struct task_struct *p);
extern unsigned long thread_saved_pc(struct task_struct *tsk);
/* Free all resources held by a thread. */
-extern inline void release_thread(struct task_struct *dead_task)
+static inline void release_thread(struct task_struct *dead_task)
{
/* Nothing needs to be done. */
}
diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
index 39faf69bcf76..53f548b791c1 100644
--- a/include/asm-cris/semaphore.h
+++ b/include/asm-cris/semaphore.h
@@ -18,8 +18,6 @@
* CRIS semaphores, implemented in C-only so far.
*/
-int printk(const char *fmt, ...);
-
struct semaphore {
atomic_t count;
atomic_t waking;
@@ -39,17 +37,17 @@ struct semaphore {
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
-extern inline void sema_init(struct semaphore *sem, int val)
+static inline void sema_init(struct semaphore *sem, int val)
{
*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}
-extern inline void init_MUTEX (struct semaphore *sem)
+static inline void init_MUTEX (struct semaphore *sem)
{
sema_init(sem, 1);
}
-extern inline void init_MUTEX_LOCKED (struct semaphore *sem)
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
{
sema_init(sem, 0);
}
@@ -61,7 +59,7 @@ extern void __up(struct semaphore * sem);
/* notice - we probably can do cli/sti here instead of saving */
-extern inline void down(struct semaphore * sem)
+static inline void down(struct semaphore * sem)
{
unsigned long flags;
int failed;
@@ -83,7 +81,7 @@ extern inline void down(struct semaphore * sem)
* returns negative for signalled and zero for semaphore acquired.
*/
-extern inline int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
{
unsigned long flags;
int failed;
@@ -99,7 +97,7 @@ extern inline int down_interruptible(struct semaphore * sem)
return(failed);
}
-extern inline int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
{
unsigned long flags;
int failed;
@@ -119,7 +117,7 @@ extern inline int down_trylock(struct semaphore * sem)
* The default case (no contention) will result in NO
* jumps for both down() and up().
*/
-extern inline void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
{
unsigned long flags;
int wakeup;
diff --git a/include/asm-cris/system.h b/include/asm-cris/system.h
index e06739806d4e..d48670107a85 100644
--- a/include/asm-cris/system.h
+++ b/include/asm-cris/system.h
@@ -41,7 +41,7 @@ extern struct task_struct *resume(struct task_struct *prev, struct task_struct *
void disable_hlt(void);
void enable_hlt(void);
-extern inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
{
/* since Etrax doesn't have any atomic xchg instructions, we need to disable
irq's (if enabled) and do it with move.d's */
diff --git a/include/asm-cris/timex.h b/include/asm-cris/timex.h
index 3fb069a37717..b92e0e80fe86 100644
--- a/include/asm-cris/timex.h
+++ b/include/asm-cris/timex.h
@@ -16,7 +16,7 @@
typedef unsigned long long cycles_t;
-extern inline cycles_t get_cycles(void)
+static inline cycles_t get_cycles(void)
{
return 0;
}
diff --git a/include/asm-cris/tlbflush.h b/include/asm-cris/tlbflush.h
index 6ed7d9ae90db..c52238005b55 100644
--- a/include/asm-cris/tlbflush.h
+++ b/include/asm-cris/tlbflush.h
@@ -39,14 +39,14 @@ static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long st
flush_tlb_mm(vma->vm_mm);
}
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
/* CRIS does not keep any page table caches in TLB */
}
-extern inline void flush_tlb(void)
+static inline void flush_tlb(void)
{
flush_tlb_mm(current->mm);
}
diff --git a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h
index 7d50086eb5ea..69d48a2dc8e1 100644
--- a/include/asm-cris/uaccess.h
+++ b/include/asm-cris/uaccess.h
@@ -213,7 +213,7 @@ extern unsigned long __copy_user(void *to, const void *from, unsigned long n);
extern unsigned long __copy_user_zeroing(void *to, const void *from, unsigned long n);
extern unsigned long __do_clear_user(void *to, unsigned long n);
-extern inline unsigned long
+static inline unsigned long
__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
@@ -221,7 +221,7 @@ __generic_copy_to_user(void __user *to, const void *from, unsigned long n)
return n;
}
-extern inline unsigned long
+static inline unsigned long
__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
@@ -229,7 +229,7 @@ __generic_copy_from_user(void *to, const void __user *from, unsigned long n)
return n;
}
-extern inline unsigned long
+static inline unsigned long
__generic_clear_user(void __user *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
@@ -237,13 +237,13 @@ __generic_clear_user(void __user *to, unsigned long n)
return n;
}
-extern inline long
+static inline long
__strncpy_from_user(char *dst, const char __user *src, long count)
{
return __do_strncpy_from_user(dst, src, count);
}
-extern inline long
+static inline long
strncpy_from_user(char *dst, const char __user *src, long count)
{
long res = -EFAULT;
@@ -256,7 +256,7 @@ strncpy_from_user(char *dst, const char __user *src, long count)
/* Note that if these expand awfully if made into switch constructs, so
don't do that. */
-extern inline unsigned long
+static inline unsigned long
__constant_copy_from_user(void *to, const void __user *from, unsigned long n)
{
unsigned long ret = 0;
@@ -306,7 +306,7 @@ __constant_copy_from_user(void *to, const void __user *from, unsigned long n)
/* Ditto, don't make a switch out of this. */
-extern inline unsigned long
+static inline unsigned long
__constant_copy_to_user(void __user *to, const void *from, unsigned long n)
{
unsigned long ret = 0;
@@ -356,7 +356,7 @@ __constant_copy_to_user(void __user *to, const void *from, unsigned long n)
/* No switch, please. */
-extern inline unsigned long
+static inline unsigned long
__constant_clear_user(void __user *to, unsigned long n)
{
unsigned long ret = 0;
@@ -406,19 +406,19 @@ __constant_clear_user(void __user *to, unsigned long n)
* used in fast paths and have only a small space overhead.
*/
-extern inline unsigned long
+static inline unsigned long
__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
{
return __copy_user_zeroing(to,from,n);
}
-extern inline unsigned long
+static inline unsigned long
__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
{
return __copy_user(to,from,n);
}
-extern inline unsigned long
+static inline unsigned long
__generic_clear_user_nocheck(void *to, unsigned long n)
{
return __do_clear_user(to,n);
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index 156a34bfc583..2627bbdf8a11 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -343,14 +343,14 @@
* some others too.
*/
#define __NR__exit __NR_exit
-extern inline _syscall0(pid_t,setsid)
-extern inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
-extern inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
-extern inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
-extern inline _syscall1(int,dup,int,fd)
-extern inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-extern inline _syscall3(int,open,const char *,file,int,flag,int,mode)
-extern inline _syscall1(int,close,int,fd)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
struct pt_regs;
asmlinkage long sys_mmap2(
@@ -382,8 +382,8 @@ asmlinkage long sys_rt_sigaction(int sig,
#ifdef __KERNEL__
#define _exit kernel_syscall_exit
#endif
-extern inline _syscall1(int,_exit,int,exitcode)
-extern inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
#endif
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index b247e99dff49..844666377dcb 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -26,6 +26,8 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/spinlock.h>
+struct mm_struct;
+struct vm_area_struct;
#endif
#ifndef __ASSEMBLY__
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 7dca30a26c53..358e4d309ceb 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -128,6 +128,7 @@ do { \
#endif
#ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
+struct mm_struct;
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep)
{
pte_t old_pte = *ptep;
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index a9c55490fb82..094d4917c1a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -35,6 +35,13 @@
VMLINUX_SYMBOL(__end_pci_fixups_enable) = .; \
} \
\
+ /* RapidIO route ops */ \
+ .rio_route : AT(ADDR(.rio_route) - LOAD_OFFSET) { \
+ VMLINUX_SYMBOL(__start_rio_route_ops) = .; \
+ *(.rio_route_ops) \
+ VMLINUX_SYMBOL(__end_rio_route_ops) = .; \
+ } \
+ \
/* Kernel symbol table: Normal symbols */ \
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___ksymtab) = .; \
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index fa11117d3cfa..4153d80e4d2b 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -119,6 +119,8 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
*/
#define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X)
+struct task_struct;
+
extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct *);
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 8b6d3a90cd78..ca916a892877 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -49,6 +49,23 @@ struct arch_specific_insn {
kprobe_opcode_t insn[MAX_INSN_SIZE];
};
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned long status;
+ unsigned long old_eflags;
+ unsigned long saved_eflags;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ unsigned long kprobe_old_eflags;
+ unsigned long kprobe_saved_eflags;
+ long *jprobe_saved_esp;
+ struct pt_regs jprobe_saved_regs;
+ kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
+ struct prev_kprobe prev_kprobe;
+};
/* trap3/1 are intr gates for kprobes. So, restore the status of IF,
* if necessary, before executing the original int3/1 (trap) handler.
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 03f3c8ac6383..088a945bf26b 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -25,6 +25,9 @@
#include <linux/list.h>
#include <linux/spinlock.h>
+struct mm_struct;
+struct vm_area_struct;
+
/*
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 0a4ec764377c..8c02b0318703 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -718,4 +718,10 @@ extern void mtrr_bp_init(void);
#define mtrr_bp_init() do {} while (0)
#endif
+#ifdef CONFIG_X86_MCE
+extern void mcheck_init(struct cpuinfo_x86 *c);
+#else
+#define mcheck_init(c) do {} while(0)
+#endif
+
#endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h
index 6347c9845642..df67d40801de 100644
--- a/include/asm-ia64/dma-mapping.h
+++ b/include/asm-ia64/dma-mapping.h
@@ -48,12 +48,7 @@ dma_set_mask (struct device *dev, u64 mask)
return 0;
}
-static inline int
-dma_get_cache_alignment (void)
-{
- extern int ia64_max_cacheline_size;
- return ia64_max_cacheline_size;
-}
+extern int dma_get_cache_alignment(void);
static inline void
dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir)
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 573a3574a24f..592abb000e29 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -26,6 +26,7 @@
*/
#include <linux/types.h>
#include <linux/ptrace.h>
+#include <linux/percpu.h>
#include <asm/break.h>
#define MAX_INSN_SIZE 16
@@ -62,6 +63,18 @@ typedef struct _bundle {
} quad1;
} __attribute__((__aligned__(16))) bundle_t;
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned long status;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ struct pt_regs jprobe_saved_regs;
+ struct prev_kprobe prev_kprobe;
+};
+
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
#define ARCH_SUPPORTS_KRETPROBES
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 21e32a06bc82..c34ba80c1c31 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -127,6 +127,7 @@
# ifndef __ASSEMBLY__
+#include <linux/sched.h> /* for mm_struct */
#include <asm/bitops.h>
#include <asm/cacheflush.h>
#include <asm/mmu_context.h>
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
index a79d1a7ecc77..2c703d6e0c86 100644
--- a/include/asm-ia64/ptrace.h
+++ b/include/asm-ia64/ptrace.h
@@ -229,6 +229,9 @@ struct switch_stack {
};
#ifdef __KERNEL__
+
+#define __ARCH_SYS_PTRACE 1
+
/*
* We use the ia64_psr(regs)->ri to determine which of the three
* instructions in bundle (16 bytes) took the sample. Generate
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 1cd5fd4a5b2c..75740debcd01 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -27,6 +27,9 @@
#include <asm/bitops.h>
#include <asm/page.h>
+struct mm_struct;
+struct vm_area_struct;
+
extern pgd_t swapper_pg_dir[1024];
extern void paging_init(void);
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 976417126b2d..55cd7ecfde43 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -145,6 +145,9 @@ struct pt_regs {
#define PTRACE_O_TRACESYSGOOD 0x00000001
#ifdef __KERNEL__
+
+#define __ARCH_SYS_PTRACE 1
+
#if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2)
#define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0)
#elif defined(CONFIG_ISA_M32R)
diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
index 026bbc9565b4..49925e91e89c 100644
--- a/include/asm-m68knommu/cacheflush.h
+++ b/include/asm-m68knommu/cacheflush.h
@@ -25,7 +25,7 @@
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
memcpy(dst, src, len)
-extern inline void __flush_cache_all(void)
+static inline void __flush_cache_all(void)
{
#ifdef CONFIG_M5407
/*
@@ -64,7 +64,7 @@ extern inline void __flush_cache_all(void)
"nop\n\t"
: : : "d0" );
#endif /* CONFIG_M5272 */
-#if CONFIG_M5249
+#ifdef CONFIG_M5249
__asm__ __volatile__ (
"movel #0xa1000200, %%d0\n\t"
"movec %%d0, %%CACR\n\t"
diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h
index 208ccd969e4b..a08fa9b958da 100644
--- a/include/asm-m68knommu/irq.h
+++ b/include/asm-m68knommu/irq.h
@@ -2,7 +2,6 @@
#define _M68K_IRQ_H_
#include <linux/config.h>
-#include <linux/interrupt.h>
#include <asm/ptrace.h>
#ifdef CONFIG_COLDFIRE
@@ -83,36 +82,6 @@ extern void (*mach_disable_irq)(unsigned int);
#endif /* CONFIG_M68360 */
/*
- * This structure is used to chain together the ISRs for a particular
- * interrupt source (if it supports chaining).
- */
-typedef struct irq_node {
- irqreturn_t (*handler)(int, void *, struct pt_regs *);
- unsigned long flags;
- void *dev_id;
- const char *devname;
- struct irq_node *next;
-} irq_node_t;
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-typedef struct irq_handler {
- irqreturn_t (*handler)(int, void *, struct pt_regs *);
- unsigned long flags;
- void *dev_id;
- const char *devname;
-} irq_handler_t;
-
-/* count of spurious interrupts */
-extern volatile unsigned int num_spurious;
-
-/*
- * This function returns a new irq_node_t
- */
-extern irq_node_t *new_irq_node(void);
-
-/*
* Some drivers want these entry points
*/
#define enable_irq(x) (mach_enable_irq ? (*mach_enable_irq)(x) : 0)
diff --git a/include/asm-m68knommu/irqnode.h b/include/asm-m68knommu/irqnode.h
new file mode 100644
index 000000000000..a2503dfc554c
--- /dev/null
+++ b/include/asm-m68knommu/irqnode.h
@@ -0,0 +1,36 @@
+#ifndef _M68K_IRQNODE_H_
+#define _M68K_IRQNODE_H_
+
+#include <linux/interrupt.h>
+
+/*
+ * This structure is used to chain together the ISRs for a particular
+ * interrupt source (if it supports chaining).
+ */
+typedef struct irq_node {
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ void *dev_id;
+ const char *devname;
+ struct irq_node *next;
+} irq_node_t;
+
+/*
+ * This structure has only 4 elements for speed reasons
+ */
+typedef struct irq_handler {
+ irqreturn_t (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ void *dev_id;
+ const char *devname;
+} irq_handler_t;
+
+/* count of spurious interrupts */
+extern volatile unsigned int num_spurious;
+
+/*
+ * This function returns a new irq_node_t
+ */
+extern irq_node_t *new_irq_node(void);
+
+#endif /* _M68K_IRQNODE_H_ */
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index 7420f12742bb..d2c9a25f8459 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -275,6 +275,8 @@ do { \
#endif /* CONFIG_64BIT */
+struct task_struct;
+
extern void dump_regs(elf_greg_t *, struct pt_regs *regs);
extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 34facd996503..702a28fa7a34 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -19,6 +19,9 @@
#include <asm/io.h>
#include <asm/pgtable-bits.h>
+struct mm_struct;
+struct vm_area_struct;
+
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
PAGE_CACHABLE_DEFAULT)
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index c28fb6f48c6c..b4554711c3e7 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -12,6 +12,7 @@
*/
#include <linux/spinlock.h>
+#include <linux/mm.h> /* for vm_area_struct */
#include <asm/processor.h>
#include <asm/cache.h>
#include <asm/bitops.h>
@@ -418,7 +419,6 @@ extern void paging_init (void);
#define PG_dcache_dirty PG_arch_1
-struct vm_area_struct; /* forward declaration (include/linux/mm.h) */
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
/* Encode and de-code a swap entry */
@@ -464,6 +464,7 @@ static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned
extern spinlock_t pa_dbit_lock;
+struct mm_struct;
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t old_pte;
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index d140577d0a05..feac3458d71f 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -1,11 +1,13 @@
#ifndef _ASM_POWERPC_ELF_H
#define _ASM_POWERPC_ELF_H
+#include <linux/sched.h> /* for task_struct */
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/cputable.h>
#include <asm/auxvec.h>
#include <asm/page.h>
+#include <asm/string.h>
/* PowerPC relocations defined by the ABIs */
#define R_PPC_NONE 0
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index b2f09f17fbe0..6cd0a3bfa280 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -27,6 +27,7 @@
*/
#include <linux/types.h>
#include <linux/ptrace.h>
+#include <linux/percpu.h>
struct pt_regs;
@@ -53,6 +54,20 @@ struct arch_specific_insn {
kprobe_opcode_t *insn;
};
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned long status;
+ unsigned long saved_msr;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ unsigned long kprobe_saved_msr;
+ struct pt_regs jprobe_saved_regs;
+ struct prev_kprobe prev_kprobe;
+};
+
#ifdef CONFIG_KPROBES
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h
index e5374be86aef..f835066fb3ca 100644
--- a/include/asm-ppc/ibm44x.h
+++ b/include/asm-ppc/ibm44x.h
@@ -34,12 +34,20 @@
/* Lowest TLB slot consumed by the default pinned TLBs */
#define PPC44x_LOW_SLOT 63
-/* LS 32-bits of UART0 physical address location for early serial text debug */
+/*
+ * Least significant 32-bits and extended real page number (ERPN) of
+ * UART0 physical address location for early serial text debug
+ */
#if defined(CONFIG_440SP)
+#define UART0_PHYS_ERPN 1
+#define UART0_PHYS_IO_BASE 0xf0000200
+#elif defined(CONFIG_440SPE)
+#define UART0_PHYS_ERPN 4
#define UART0_PHYS_IO_BASE 0xf0000200
#elif defined(CONFIG_440EP)
#define UART0_PHYS_IO_BASE 0xe0000000
#else
+#define UART0_PHYS_ERPN 1
#define UART0_PHYS_IO_BASE 0x40000200
#endif
@@ -56,6 +64,11 @@
#define PPC44x_PCICFG_PAGE 0x0000000900000000ULL
#define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE
#define PPC44x_PCIMEM_PAGE 0x0000000a00000000ULL
+#elif defined(CONFIG_440SPE)
+#define PPC44x_IO_PAGE 0x0000000400000000ULL
+#define PPC44x_PCICFG_PAGE 0x0000000c00000000ULL
+#define PPC44x_PCIIO_PAGE PPC44x_PCICFG_PAGE
+#define PPC44x_PCIMEM_PAGE 0x0000000d00000000ULL
#elif defined(CONFIG_440EP)
#define PPC44x_IO_PAGE 0x0000000000000000ULL
#define PPC44x_PCICFG_PAGE 0x0000000000000000ULL
@@ -71,7 +84,7 @@
/*
* 36-bit trap ranges
*/
-#if defined(CONFIG_440SP)
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
#define PPC44x_IO_LO 0xf0000000UL
#define PPC44x_IO_HI 0xf0000fffUL
#define PPC44x_PCI0CFG_LO 0x0ec00000UL
@@ -109,7 +122,7 @@
*/
-/* CPRs (440GX and 440SP) */
+/* CPRs (440GX and 440SP/440SPe) */
#define DCRN_CPR_CONFIG_ADDR 0xc
#define DCRN_CPR_CONFIG_DATA 0xd
@@ -130,7 +143,7 @@
mtdcr(DCRN_CPR_CONFIG_ADDR, offset); \
mtdcr(DCRN_CPR_CONFIG_DATA, data);})
-/* SDRs (440GX and 440SP) */
+/* SDRs (440GX and 440SP/440SPe) */
#define DCRN_SDR_CONFIG_ADDR 0xe
#define DCRN_SDR_CONFIG_DATA 0xf
#define DCRN_SDR_PFC0 0x4100
@@ -180,7 +193,7 @@
mtdcr(DCRN_SDR_CONFIG_ADDR, offset); \
mtdcr(DCRN_SDR_CONFIG_DATA,data);})
-/* DMA (excluding 440SP) */
+/* DMA (excluding 440SP/440SPe) */
#define DCRN_DMA0_BASE 0x100
#define DCRN_DMA1_BASE 0x108
#define DCRN_DMA2_BASE 0x110
@@ -200,12 +213,20 @@
/* UIC */
#define DCRN_UIC0_BASE 0xc0
#define DCRN_UIC1_BASE 0xd0
-#define DCRN_UIC2_BASE 0x210
-#define DCRN_UICB_BASE 0x200
#define UIC0 DCRN_UIC0_BASE
#define UIC1 DCRN_UIC1_BASE
+
+#ifdef CONFIG_440SPE
+#define DCRN_UIC2_BASE 0xe0
+#define DCRN_UIC3_BASE 0xf0
+#define UIC2 DCRN_UIC2_BASE
+#define UIC3 DCRN_UIC3_BASE
+#else
+#define DCRN_UIC2_BASE 0x210
+#define DCRN_UICB_BASE 0x200
#define UIC2 DCRN_UIC2_BASE
#define UICB DCRN_UICB_BASE
+#endif
#define DCRN_UIC_SR(base) (base + 0x0)
#define DCRN_UIC_ER(base) (base + 0x2)
@@ -218,6 +239,12 @@
#define UIC0_UIC1NC 0x00000002
+#ifdef CONFIG_440SPE
+#define UIC0_UIC1NC 0x00000002
+#define UIC0_UIC2NC 0x00200000
+#define UIC0_UIC3NC 0x00008000
+#endif
+
#define UICB_UIC0NC 0x40000000
#define UICB_UIC1NC 0x10000000
#define UICB_UIC2NC 0x04000000
@@ -297,6 +324,23 @@
#define MALOBISR_CH0 0x80000000 /* EOB channel 1 bit */
#define MALOBISR_CH2 0x40000000 /* EOB channel 2 bit */
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+/* 440SP/440SPe PLB Arbiter DCRs */
+#define DCRN_PLB_REVID 0x080 /* PLB Revision ID */
+#define DCRN_PLB_CCR 0x088 /* PLB Crossbar Control */
+
+#define DCRN_PLB0_ACR 0x081 /* PLB Arbiter Control */
+#define DCRN_PLB0_BESRL 0x082 /* PLB Error Status */
+#define DCRN_PLB0_BESRH 0x083 /* PLB Error Status */
+#define DCRN_PLB0_BEARL 0x084 /* PLB Error Address Low */
+#define DCRN_PLB0_BEARH 0x085 /* PLB Error Address High */
+
+#define DCRN_PLB1_ACR 0x089 /* PLB Arbiter Control */
+#define DCRN_PLB1_BESRL 0x08a /* PLB Error Status */
+#define DCRN_PLB1_BESRH 0x08b /* PLB Error Status */
+#define DCRN_PLB1_BEARL 0x08c /* PLB Error Address Low */
+#define DCRN_PLB1_BEARH 0x08d /* PLB Error Address High */
+#else
/* 440GP/GX PLB Arbiter DCRs */
#define DCRN_PLB0_REVID 0x082 /* PLB Arbiter Revision ID */
#define DCRN_PLB0_ACR 0x083 /* PLB Arbiter Control */
@@ -304,6 +348,7 @@
#define DCRN_PLB0_BEARL 0x086 /* PLB Error Address Low */
#define DCRN_PLB0_BEAR DCRN_PLB0_BEARL /* 40x compatibility */
#define DCRN_PLB0_BEARH 0x087 /* PLB Error Address High */
+#endif
/* 440GP/GX PLB to OPB bridge DCRs */
#define DCRN_POB0_BESR0 0x090
@@ -407,9 +452,13 @@
#define PPC44x_MEM_SIZE_1G 0x40000000
#define PPC44x_MEM_SIZE_2G 0x80000000
-/* 440SP memory controller DCRs */
+/* 440SP/440SPe memory controller DCRs */
#define DCRN_MQ0_BS0BAS 0x40
-#define DCRN_MQ0_BS1BAS 0x41
+#if defined(CONFIG_440SP)
+#define MQ0_NUM_BANKS 2
+#elif defined(CONFIG_440SPE)
+#define MQ0_NUM_BANKS 4
+#endif
#define MQ0_CONFIG_SIZE_MASK 0x0000fff0
#define MQ0_CONFIG_SIZE_8M 0x0000ffc0
@@ -421,8 +470,9 @@
#define MQ0_CONFIG_SIZE_512M 0x0000f000
#define MQ0_CONFIG_SIZE_1G 0x0000e000
#define MQ0_CONFIG_SIZE_2G 0x0000c000
+#define MQ0_CONFIG_SIZE_4G 0x00008000
-/* Internal SRAM Controller 440GX/440SP */
+/* Internal SRAM Controller 440GX/440SP/440SPe */
#define DCRN_SRAM0_BASE 0x000
#define DCRN_SRAM0_SB0CR (DCRN_SRAM0_BASE + 0x020)
@@ -446,7 +496,7 @@
#define DCRN_SRAM0_DPC (DCRN_SRAM0_BASE + 0x02a)
#define SRAM_DPC_ENABLE 0x80000000
-/* L2 Cache Controller 440GX/440SP */
+/* L2 Cache Controller 440GX/440SP/440SPe */
#define DCRN_L2C0_CFG 0x030
#define L2C_CFG_L2M 0x80000000
#define L2C_CFG_ICU 0x40000000
@@ -610,8 +660,10 @@
#define IIC_CLOCK 50
#undef NR_UICS
-#ifdef CONFIG_440GX
+#if defined(CONFIG_440GX)
#define NR_UICS 3
+#elif defined(CONFIG_440SPE)
+#define NR_UICS 4
#else
#define NR_UICS 2
#endif
diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h
index e992369cb8e9..6c28ae7807f4 100644
--- a/include/asm-ppc/ibm4xx.h
+++ b/include/asm-ppc/ibm4xx.h
@@ -97,6 +97,10 @@ void ppc4xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
#include <platforms/4xx/luan.h>
#endif
+#if defined(CONFIG_YUCCA)
+#include <platforms/4xx/yucca.h>
+#endif
+
#if defined(CONFIG_OCOTEA)
#include <platforms/4xx/ocotea.h>
#endif
diff --git a/include/asm-ppc/ibm_ocp.h b/include/asm-ppc/ibm_ocp.h
index 6f10a25bd628..9c21de1ff4ed 100644
--- a/include/asm-ppc/ibm_ocp.h
+++ b/include/asm-ppc/ibm_ocp.h
@@ -131,9 +131,22 @@ static inline void ibm_ocp_set_emac(int start, int end)
/* Copy MAC addresses to EMAC additions */
for (i=start; i<=end; i++) {
def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
- memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr,
- &__res.bi_enetaddr[i],
- 6);
+ if (i == 0)
+ memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr,
+ __res.bi_enetaddr, 6);
+#if defined(CONFIG_405EP) || defined(CONFIG_44x)
+ else if (i == 1)
+ memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr,
+ __res.bi_enet1addr, 6);
+#endif
+#if defined(CONFIG_440GX)
+ else if (i == 2)
+ memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr,
+ __res.bi_enet2addr, 6);
+ else if (i == 3)
+ memcpy(((struct ocp_func_emac_data *)def->additions)->mac_addr,
+ __res.bi_enet3addr, 6);
+#endif
}
}
#endif
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index b28a713ba862..6d1c39e8a6af 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -12,6 +12,7 @@
#include <asm/processor.h> /* For TASK_SIZE */
#include <asm/mmu.h>
#include <asm/page.h>
+struct mm_struct;
extern unsigned long va_to_phys(unsigned long address);
extern pte_t *va_to_pte(unsigned long address);
diff --git a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h
index fe24e4520208..6b7b63f71daa 100644
--- a/include/asm-ppc/ppcboot.h
+++ b/include/asm-ppc/ppcboot.h
@@ -73,8 +73,8 @@ typedef struct bd_info {
#if defined(CONFIG_HYMOD)
hymod_conf_t bi_hymod_conf; /* hymod configuration information */
#endif
-#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx) ||\
- defined(CONFIG_83xx)
+#if defined(CONFIG_EVB64260) || defined(CONFIG_405EP) || defined(CONFIG_44x) || \
+ defined(CONFIG_85xx) || defined(CONFIG_83xx)
/* second onboard ethernet port */
unsigned char bi_enet1addr[6];
#endif
@@ -96,5 +96,7 @@ typedef struct bd_info {
#endif
} bd_t;
+#define bi_tbfreq bi_intfreq
+
#endif /* __ASSEMBLY__ */
#endif /* __ASM_PPCBOOT_H__ */
diff --git a/include/asm-ppc/rio.h b/include/asm-ppc/rio.h
new file mode 100644
index 000000000000..0018bf80cb25
--- /dev/null
+++ b/include/asm-ppc/rio.h
@@ -0,0 +1,18 @@
+/*
+ * RapidIO architecture support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#ifndef ASM_PPC_RIO_H
+#define ASM_PPC_RIO_H
+
+extern void platform_rio_init(void);
+
+#endif /* ASM_PPC_RIO_H */
diff --git a/include/asm-ppc64/pgtable-4k.h b/include/asm-ppc64/pgtable-4k.h
index c883a2748558..e9590c06ad92 100644
--- a/include/asm-ppc64/pgtable-4k.h
+++ b/include/asm-ppc64/pgtable-4k.h
@@ -23,6 +23,9 @@
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
+/* With 4k base page size, hugepage PTEs go at the PMD level */
+#define MIN_HUGEPTE_SHIFT PMD_SHIFT
+
/* PUD_SHIFT determines what a third-level page table entry can map */
#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE)
#define PUD_SIZE (1UL << PUD_SHIFT)
diff --git a/include/asm-ppc64/pgtable-64k.h b/include/asm-ppc64/pgtable-64k.h
index c5f437c86b3c..154f1840ece4 100644
--- a/include/asm-ppc64/pgtable-64k.h
+++ b/include/asm-ppc64/pgtable-64k.h
@@ -14,6 +14,9 @@
#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE)
+/* With 4k base page size, hugepage PTEs go at the PMD level */
+#define MIN_HUGEPTE_SHIFT PAGE_SHIFT
+
/* PMD_SHIFT determines what a second-level page table entry can map */
#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE)
#define PMD_SIZE (1UL << PMD_SHIFT)
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index fde93ec36abc..a9783ba7fe98 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -13,6 +13,7 @@
#include <asm/mmu.h>
#include <asm/page.h>
#include <asm/tlbflush.h>
+struct mm_struct;
#endif /* __ASSEMBLY__ */
#ifdef CONFIG_PPC_64K_PAGES
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index 8651524217fd..b07c578b22ea 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -518,8 +518,8 @@ static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr
static inline int
__constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
- return (((volatile char *) addr)
- [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7)));
+ return ((((volatile char *) addr)
+ [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7)))) != 0;
}
#define test_bit(nr,addr) \
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index 3b8bd46832a1..372d51cccd53 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -96,6 +96,7 @@
* ELF register definitions..
*/
+#include <linux/sched.h> /* for task_struct */
#include <asm/ptrace.h>
#include <asm/user.h>
#include <asm/system.h> /* for save_access_regs */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index df94f89038cc..9be741bb1496 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -36,6 +36,7 @@
#include <linux/threads.h>
struct vm_area_struct; /* forward declaration (include/linux/mm.h) */
+struct mm_struct;
extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
extern void paging_init(void);
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index fc7c96edc697..a949cc077cc7 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -468,6 +468,8 @@ struct user_regs_struct
};
#ifdef __KERNEL__
+#define __ARCH_SYS_PTRACE 1
+
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
#define profile_pc(regs) instruction_pointer(regs)
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index 38a5cf8ab9e3..10a619da4761 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -200,21 +200,37 @@ extern int __put_user_bad(void) __attribute__((noreturn));
#define __get_user(x, ptr) \
({ \
- __typeof__(*(ptr)) __x; \
int __gu_err; \
__chk_user_ptr(ptr); \
switch (sizeof(*(ptr))) { \
- case 1: \
- case 2: \
- case 4: \
- case 8: \
+ case 1: { \
+ unsigned char __x; \
+ __get_user_asm(__x, ptr, __gu_err); \
+ (x) = (__typeof__(*(ptr))) __x; \
+ break; \
+ }; \
+ case 2: { \
+ unsigned short __x; \
+ __get_user_asm(__x, ptr, __gu_err); \
+ (x) = (__typeof__(*(ptr))) __x; \
+ break; \
+ }; \
+ case 4: { \
+ unsigned int __x; \
+ __get_user_asm(__x, ptr, __gu_err); \
+ (x) = (__typeof__(*(ptr))) __x; \
+ break; \
+ }; \
+ case 8: { \
+ unsigned long long __x; \
__get_user_asm(__x, ptr, __gu_err); \
+ (x) = (__typeof__(*(ptr))) __x; \
break; \
+ }; \
default: \
__get_user_bad(); \
break; \
} \
- (x) = __x; \
__gu_err; \
})
diff --git a/include/asm-s390/vtoc.h b/include/asm-s390/vtoc.h
index a14e34e80b88..41d369f38b0e 100644
--- a/include/asm-s390/vtoc.h
+++ b/include/asm-s390/vtoc.h
@@ -1,372 +1,179 @@
-#ifndef __KERNEL__
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <fcntl.h>
-#include <unistd.h>
+/*
+ * include/asm-s390/vtoc.h
+ *
+ * This file contains volume label definitions for DASD devices.
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Volker Sameske <sameske@de.ibm.com>
+ *
+ */
+
+#ifndef _ASM_S390_VTOC_H
+#define _ASM_S390_VTOC_H
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-
-#include <linux/fs.h>
#include <linux/types.h>
-#include <linux/hdreg.h>
-#include <asm/dasd.h>
-#endif
-
-
-#define LINE_LENGTH 80
-#define VTOC_START_CC 0x0
-#define VTOC_START_HH 0x1
-#define FIRST_USABLE_CYL 1
-#define FIRST_USABLE_TRK 2
-
-#define DASD_3380_TYPE 13148
-#define DASD_3390_TYPE 13200
-#define DASD_9345_TYPE 37701
-
-#define DASD_3380_VALUE 0xbb60
-#define DASD_3390_VALUE 0xe5a2
-#define DASD_9345_VALUE 0xbc98
-
-#define VOLSER_LENGTH 6
-#define BIG_DISK_SIZE 0x10000
-
-#define VTOC_ERROR "VTOC error:"
-
-typedef struct ttr
+struct vtoc_ttr
{
- __u16 tt;
- __u8 r;
-} __attribute__ ((packed)) ttr_t;
+ __u16 tt;
+ __u8 r;
+} __attribute__ ((packed));
-typedef struct cchhb
+struct vtoc_cchhb
{
- __u16 cc;
- __u16 hh;
- __u8 b;
-} __attribute__ ((packed)) cchhb_t;
+ __u16 cc;
+ __u16 hh;
+ __u8 b;
+} __attribute__ ((packed));
-typedef struct cchh
+struct vtoc_cchh
{
- __u16 cc;
- __u16 hh;
-} __attribute__ ((packed)) cchh_t;
+ __u16 cc;
+ __u16 hh;
+} __attribute__ ((packed));
-typedef struct labeldate
+struct vtoc_labeldate
{
- __u8 year;
- __u16 day;
-} __attribute__ ((packed)) labeldate_t;
+ __u8 year;
+ __u16 day;
+} __attribute__ ((packed));
-
-typedef struct volume_label
+struct vtoc_volume_label
{
- char volkey[4]; /* volume key = volume label */
- char vollbl[4]; /* volume label */
- char volid[6]; /* volume identifier */
- __u8 security; /* security byte */
- cchhb_t vtoc; /* VTOC address */
- char res1[5]; /* reserved */
- char cisize[4]; /* CI-size for FBA,... */
- /* ...blanks for CKD */
- char blkperci[4]; /* no of blocks per CI (FBA), blanks for CKD */
- char labperci[4]; /* no of labels per CI (FBA), blanks for CKD */
- char res2[4]; /* reserved */
- char lvtoc[14]; /* owner code for LVTOC */
- char res3[29]; /* reserved */
-} __attribute__ ((packed)) volume_label_t;
-
-
-typedef struct extent
+ char volkey[4]; /* volume key = volume label */
+ char vollbl[4]; /* volume label */
+ char volid[6]; /* volume identifier */
+ __u8 security; /* security byte */
+ struct vtoc_cchhb vtoc; /* VTOC address */
+ char res1[5]; /* reserved */
+ char cisize[4]; /* CI-size for FBA,... */
+ /* ...blanks for CKD */
+ char blkperci[4]; /* no of blocks per CI (FBA), blanks for CKD */
+ char labperci[4]; /* no of labels per CI (FBA), blanks for CKD */
+ char res2[4]; /* reserved */
+ char lvtoc[14]; /* owner code for LVTOC */
+ char res3[29]; /* reserved */
+} __attribute__ ((packed));
+
+struct vtoc_extent
{
- __u8 typeind; /* extent type indicator */
- __u8 seqno; /* extent sequence number */
- cchh_t llimit; /* starting point of this extent */
- cchh_t ulimit; /* ending point of this extent */
-} __attribute__ ((packed)) extent_t;
-
+ __u8 typeind; /* extent type indicator */
+ __u8 seqno; /* extent sequence number */
+ struct vtoc_cchh llimit; /* starting point of this extent */
+ struct vtoc_cchh ulimit; /* ending point of this extent */
+} __attribute__ ((packed));
-typedef struct dev_const
+struct vtoc_dev_const
{
- __u16 DS4DSCYL; /* number of logical cyls */
- __u16 DS4DSTRK; /* number of tracks in a logical cylinder */
- __u16 DS4DEVTK; /* device track length */
- __u8 DS4DEVI; /* non-last keyed record overhead */
- __u8 DS4DEVL; /* last keyed record overhead */
- __u8 DS4DEVK; /* non-keyed record overhead differential */
- __u8 DS4DEVFG; /* flag byte */
- __u16 DS4DEVTL; /* device tolerance */
- __u8 DS4DEVDT; /* number of DSCB's per track */
- __u8 DS4DEVDB; /* number of directory blocks per track */
-} __attribute__ ((packed)) dev_const_t;
-
-
-typedef struct format1_label
+ __u16 DS4DSCYL; /* number of logical cyls */
+ __u16 DS4DSTRK; /* number of tracks in a logical cylinder */
+ __u16 DS4DEVTK; /* device track length */
+ __u8 DS4DEVI; /* non-last keyed record overhead */
+ __u8 DS4DEVL; /* last keyed record overhead */
+ __u8 DS4DEVK; /* non-keyed record overhead differential */
+ __u8 DS4DEVFG; /* flag byte */
+ __u16 DS4DEVTL; /* device tolerance */
+ __u8 DS4DEVDT; /* number of DSCB's per track */
+ __u8 DS4DEVDB; /* number of directory blocks per track */
+} __attribute__ ((packed));
+
+struct vtoc_format1_label
{
- char DS1DSNAM[44]; /* data set name */
- __u8 DS1FMTID; /* format identifier */
- char DS1DSSN[6]; /* data set serial number */
- __u16 DS1VOLSQ; /* volume sequence number */
- labeldate_t DS1CREDT; /* creation date: ydd */
- labeldate_t DS1EXPDT; /* expiration date */
- __u8 DS1NOEPV; /* number of extents on volume */
- __u8 DS1NOBDB; /* no. of bytes used in last direction blk */
- __u8 DS1FLAG1; /* flag 1 */
- char DS1SYSCD[13]; /* system code */
- labeldate_t DS1REFD; /* date last referenced */
- __u8 DS1SMSFG; /* system managed storage indicators */
- __u8 DS1SCXTF; /* sec. space extension flag byte */
- __u16 DS1SCXTV; /* secondary space extension value */
- __u8 DS1DSRG1; /* data set organisation byte 1 */
- __u8 DS1DSRG2; /* data set organisation byte 2 */
- __u8 DS1RECFM; /* record format */
- __u8 DS1OPTCD; /* option code */
- __u16 DS1BLKL; /* block length */
- __u16 DS1LRECL; /* record length */
- __u8 DS1KEYL; /* key length */
- __u16 DS1RKP; /* relative key position */
- __u8 DS1DSIND; /* data set indicators */
- __u8 DS1SCAL1; /* secondary allocation flag byte */
- char DS1SCAL3[3]; /* secondary allocation quantity */
- ttr_t DS1LSTAR; /* last used track and block on track */
- __u16 DS1TRBAL; /* space remaining on last used track */
- __u16 res1; /* reserved */
- extent_t DS1EXT1; /* first extent description */
- extent_t DS1EXT2; /* second extent description */
- extent_t DS1EXT3; /* third extent description */
- cchhb_t DS1PTRDS; /* possible pointer to f2 or f3 DSCB */
-} __attribute__ ((packed)) format1_label_t;
-
-
-typedef struct format4_label
+ char DS1DSNAM[44]; /* data set name */
+ __u8 DS1FMTID; /* format identifier */
+ char DS1DSSN[6]; /* data set serial number */
+ __u16 DS1VOLSQ; /* volume sequence number */
+ struct vtoc_labeldate DS1CREDT; /* creation date: ydd */
+ struct vtoc_labeldate DS1EXPDT; /* expiration date */
+ __u8 DS1NOEPV; /* number of extents on volume */
+ __u8 DS1NOBDB; /* no. of bytes used in last direction blk */
+ __u8 DS1FLAG1; /* flag 1 */
+ char DS1SYSCD[13]; /* system code */
+ struct vtoc_labeldate DS1REFD; /* date last referenced */
+ __u8 DS1SMSFG; /* system managed storage indicators */
+ __u8 DS1SCXTF; /* sec. space extension flag byte */
+ __u16 DS1SCXTV; /* secondary space extension value */
+ __u8 DS1DSRG1; /* data set organisation byte 1 */
+ __u8 DS1DSRG2; /* data set organisation byte 2 */
+ __u8 DS1RECFM; /* record format */
+ __u8 DS1OPTCD; /* option code */
+ __u16 DS1BLKL; /* block length */
+ __u16 DS1LRECL; /* record length */
+ __u8 DS1KEYL; /* key length */
+ __u16 DS1RKP; /* relative key position */
+ __u8 DS1DSIND; /* data set indicators */
+ __u8 DS1SCAL1; /* secondary allocation flag byte */
+ char DS1SCAL3[3]; /* secondary allocation quantity */
+ struct vtoc_ttr DS1LSTAR; /* last used track and block on track */
+ __u16 DS1TRBAL; /* space remaining on last used track */
+ __u16 res1; /* reserved */
+ struct vtoc_extent DS1EXT1; /* first extent description */
+ struct vtoc_extent DS1EXT2; /* second extent description */
+ struct vtoc_extent DS1EXT3; /* third extent description */
+ struct vtoc_cchhb DS1PTRDS; /* possible pointer to f2 or f3 DSCB */
+} __attribute__ ((packed));
+
+struct vtoc_format4_label
{
- char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */
- __u8 DS4IDFMT; /* format identifier */
- cchhb_t DS4HPCHR; /* highest address of a format 1 DSCB */
- __u16 DS4DSREC; /* number of available DSCB's */
- cchh_t DS4HCCHH; /* CCHH of next available alternate track */
- __u16 DS4NOATK; /* number of remaining alternate tracks */
- __u8 DS4VTOCI; /* VTOC indicators */
- __u8 DS4NOEXT; /* number of extents in VTOC */
- __u8 DS4SMSFG; /* system managed storage indicators */
- __u8 DS4DEVAC; /* number of alternate cylinders.
- Subtract from first two bytes of
- DS4DEVSZ to get number of usable
- cylinders. can be zero. valid
- only if DS4DEVAV on. */
- dev_const_t DS4DEVCT; /* device constants */
- char DS4AMTIM[8]; /* VSAM time stamp */
- char DS4AMCAT[3]; /* VSAM catalog indicator */
- char DS4R2TIM[8]; /* VSAM volume/catalog match time stamp */
- char res1[5]; /* reserved */
- char DS4F6PTR[5]; /* pointer to first format 6 DSCB */
- extent_t DS4VTOCE; /* VTOC extent description */
- char res2[10]; /* reserved */
- __u8 DS4EFLVL; /* extended free-space management level */
- cchhb_t DS4EFPTR; /* pointer to extended free-space info */
- char res3[9]; /* reserved */
-} __attribute__ ((packed)) format4_label_t;
-
-
-typedef struct ds5ext
+ char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */
+ __u8 DS4IDFMT; /* format identifier */
+ struct vtoc_cchhb DS4HPCHR; /* highest address of a format 1 DSCB */
+ __u16 DS4DSREC; /* number of available DSCB's */
+ struct vtoc_cchh DS4HCCHH; /* CCHH of next available alternate track */
+ __u16 DS4NOATK; /* number of remaining alternate tracks */
+ __u8 DS4VTOCI; /* VTOC indicators */
+ __u8 DS4NOEXT; /* number of extents in VTOC */
+ __u8 DS4SMSFG; /* system managed storage indicators */
+ __u8 DS4DEVAC; /* number of alternate cylinders.
+ * Subtract from first two bytes of
+ * DS4DEVSZ to get number of usable
+ * cylinders. can be zero. valid
+ * only if DS4DEVAV on. */
+ struct vtoc_dev_const DS4DEVCT; /* device constants */
+ char DS4AMTIM[8]; /* VSAM time stamp */
+ char DS4AMCAT[3]; /* VSAM catalog indicator */
+ char DS4R2TIM[8]; /* VSAM volume/catalog match time stamp */
+ char res1[5]; /* reserved */
+ char DS4F6PTR[5]; /* pointer to first format 6 DSCB */
+ struct vtoc_extent DS4VTOCE; /* VTOC extent description */
+ char res2[10]; /* reserved */
+ __u8 DS4EFLVL; /* extended free-space management level */
+ struct vtoc_cchhb DS4EFPTR; /* pointer to extended free-space info */
+ char res3[9]; /* reserved */
+} __attribute__ ((packed));
+
+struct vtoc_ds5ext
{
- __u16 t; /* RTA of the first track of free extent */
- __u16 fc; /* number of whole cylinders in free ext. */
- __u8 ft; /* number of remaining free tracks */
-} __attribute__ ((packed)) ds5ext_t;
-
+ __u16 t; /* RTA of the first track of free extent */
+ __u16 fc; /* number of whole cylinders in free ext. */
+ __u8 ft; /* number of remaining free tracks */
+} __attribute__ ((packed));
-typedef struct format5_label
+struct vtoc_format5_label
{
- char DS5KEYID[4]; /* key identifier */
- ds5ext_t DS5AVEXT; /* first available (free-space) extent. */
- ds5ext_t DS5EXTAV[7]; /* seven available extents */
- __u8 DS5FMTID; /* format identifier */
- ds5ext_t DS5MAVET[18]; /* eighteen available extents */
- cchhb_t DS5PTRDS; /* pointer to next format5 DSCB */
-} __attribute__ ((packed)) format5_label_t;
-
-
-typedef struct ds7ext
+ char DS5KEYID[4]; /* key identifier */
+ struct vtoc_ds5ext DS5AVEXT; /* first available (free-space) extent. */
+ struct vtoc_ds5ext DS5EXTAV[7]; /* seven available extents */
+ __u8 DS5FMTID; /* format identifier */
+ struct vtoc_ds5ext DS5MAVET[18]; /* eighteen available extents */
+ struct vtoc_cchhb DS5PTRDS; /* pointer to next format5 DSCB */
+} __attribute__ ((packed));
+
+struct vtoc_ds7ext
{
- __u32 a; /* starting RTA value */
- __u32 b; /* ending RTA value + 1 */
-} __attribute__ ((packed)) ds7ext_t;
+ __u32 a; /* starting RTA value */
+ __u32 b; /* ending RTA value + 1 */
+} __attribute__ ((packed));
-
-typedef struct format7_label
+struct vtoc_format7_label
{
- char DS7KEYID[4]; /* key identifier */
- ds7ext_t DS7EXTNT[5]; /* space for 5 extent descriptions */
- __u8 DS7FMTID; /* format identifier */
- ds7ext_t DS7ADEXT[11]; /* space for 11 extent descriptions */
- char res1[2]; /* reserved */
- cchhb_t DS7PTRDS; /* pointer to next FMT7 DSCB */
-} __attribute__ ((packed)) format7_label_t;
-
-
-char * vtoc_ebcdic_enc (
- unsigned char source[LINE_LENGTH],
- unsigned char target[LINE_LENGTH],
- int l);
-char * vtoc_ebcdic_dec (
- unsigned char source[LINE_LENGTH],
- unsigned char target[LINE_LENGTH],
- int l);
-void vtoc_set_extent (
- extent_t * ext,
- __u8 typeind,
- __u8 seqno,
- cchh_t * lower,
- cchh_t * upper);
-void vtoc_set_cchh (
- cchh_t * addr,
- __u16 cc,
- __u16 hh);
-void vtoc_set_cchhb (
- cchhb_t * addr,
- __u16 cc,
- __u16 hh,
- __u8 b);
-void vtoc_set_date (
- labeldate_t * d,
- __u8 year,
- __u16 day);
-
-void vtoc_volume_label_init (
- volume_label_t *vlabel);
-
-int vtoc_read_volume_label (
- char * device,
- unsigned long vlabel_start,
- volume_label_t * vlabel);
-
-int vtoc_write_volume_label (
- char *device,
- unsigned long vlabel_start,
- volume_label_t *vlabel);
-
-void vtoc_volume_label_set_volser (
- volume_label_t *vlabel,
- char *volser);
-
-char *vtoc_volume_label_get_volser (
- volume_label_t *vlabel,
- char *volser);
-
-void vtoc_volume_label_set_key (
- volume_label_t *vlabel,
- char *key);
-
-void vtoc_volume_label_set_label (
- volume_label_t *vlabel,
- char *lbl);
-
-char *vtoc_volume_label_get_label (
- volume_label_t *vlabel,
- char *lbl);
-
-void vtoc_read_label (
- char *device,
- unsigned long position,
- format1_label_t *f1,
- format4_label_t *f4,
- format5_label_t *f5,
- format7_label_t *f7);
-
-void vtoc_write_label (
- char *device,
- unsigned long position,
- format1_label_t *f1,
- format4_label_t *f4,
- format5_label_t *f5,
- format7_label_t *f7);
-
-
-void vtoc_init_format1_label (
- char *volid,
- unsigned int blksize,
- extent_t *part_extent,
- format1_label_t *f1);
-
-
-void vtoc_init_format4_label (
- format4_label_t *f4lbl,
- unsigned int usable_partitions,
- unsigned int cylinders,
- unsigned int tracks,
- unsigned int blocks,
- unsigned int blksize,
- __u16 dev_type);
-
-void vtoc_update_format4_label (
- format4_label_t *f4,
- cchhb_t *highest_f1,
- __u16 unused_update);
-
-
-void vtoc_init_format5_label (
- format5_label_t *f5);
-
-void vtoc_update_format5_label_add (
- format5_label_t *f5,
- int verbose,
- int cyl,
- int trk,
- __u16 a,
- __u16 b,
- __u8 c);
-
-void vtoc_update_format5_label_del (
- format5_label_t *f5,
- int verbose,
- int cyl,
- int trk,
- __u16 a,
- __u16 b,
- __u8 c);
-
-
-void vtoc_init_format7_label (
- format7_label_t *f7);
-
-void vtoc_update_format7_label_add (
- format7_label_t *f7,
- int verbose,
- __u32 a,
- __u32 b);
-
-void vtoc_update_format7_label_del (
- format7_label_t *f7,
- int verbose,
- __u32 a,
- __u32 b);
-
-
-void vtoc_set_freespace(
- format4_label_t *f4,
- format5_label_t *f5,
- format7_label_t *f7,
- char ch,
- int verbose,
- __u32 start,
- __u32 stop,
- int cyl,
- int trk);
-
-
-
-
-
-
-
-
-
-
-
-
+ char DS7KEYID[4]; /* key identifier */
+ struct vtoc_ds7ext DS7EXTNT[5]; /* space for 5 extent descriptions */
+ __u8 DS7FMTID; /* format identifier */
+ struct vtoc_ds7ext DS7ADEXT[11]; /* space for 11 extent descriptions */
+ char res1[2]; /* reserved */
+ struct vtoc_cchhb DS7PTRDS; /* pointer to next FMT7 DSCB */
+} __attribute__ ((packed));
+
+#endif /* _ASM_S390_VTOC_H */
diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h
index 8fe00a1981ce..1b63dfeea4f2 100644
--- a/include/asm-sh/elf.h
+++ b/include/asm-sh/elf.h
@@ -111,6 +111,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
#ifdef __KERNEL__
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+struct task_struct;
extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
diff --git a/include/asm-sh/mmzone.h b/include/asm-sh/mmzone.h
deleted file mode 100644
index 0e7406601fdf..000000000000
--- a/include/asm-sh/mmzone.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * linux/include/asm-sh/mmzone.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_SH_MMZONE_H
-#define __ASM_SH_MMZONE_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_DISCONTIGMEM
-
-/* Currently, just for HP690 */
-#define PHYSADDR_TO_NID(phys) ((((phys) - __MEMORY_START) >= 0x01000000)?1:0)
-
-extern pg_data_t discontig_page_data[MAX_NUMNODES];
-extern bootmem_data_t discontig_node_bdata[MAX_NUMNODES];
-
-/*
- * Following are macros that each numa implmentation must define.
- */
-
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define KVADDR_TO_NID(kaddr) PHYSADDR_TO_NID(__pa(kaddr))
-
-/*
- * Return a pointer to the node data for node n.
- */
-#define NODE_DATA(nid) (&discontig_page_data[nid])
-
-/*
- * NODE_MEM_MAP gives the kaddr for the mem_map of the node.
- */
-#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map)
-
-#define phys_to_page(phys) \
-({ unsigned int node = PHYSADDR_TO_NID(phys); \
- NODE_MEM_MAP(node) \
- + (((phys) - NODE_DATA(node)->node_start_paddr) >> PAGE_SHIFT); })
-
-static inline int is_valid_page(struct page *page)
-{
- unsigned int i;
-
- for (i = 0; i < MAX_NUMNODES; i++) {
- if (page >= NODE_MEM_MAP(i) &&
- page < NODE_MEM_MAP(i) + NODE_DATA(i)->node_size)
- return 1;
- }
- return 0;
-}
-
-#define VALID_PAGE(page) is_valid_page(page)
-#define page_to_phys(page) PHYSADDR(page_address(page))
-
-#endif /* CONFIG_DISCONTIGMEM */
-#endif
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 324e6cc5ecf7..972c3f655b2a 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -93,11 +93,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __MEMORY_START CONFIG_MEMORY_START
#define __MEMORY_SIZE CONFIG_MEMORY_SIZE
-#ifdef CONFIG_DISCONTIGMEM
-/* Just for HP690, for now.. */
-#define __MEMORY_START_2ND (__MEMORY_START+0x02000000)
-#define __MEMORY_SIZE_2ND 0x001000000 /* 16MB */
-#endif
#define PAGE_OFFSET (0x80000000UL)
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
@@ -105,10 +100,8 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define MAP_NR(addr) (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)
-#ifndef CONFIG_DISCONTIGMEM
#define phys_to_page(phys) (mem_map + (((phys)-__MEMORY_START) >> PAGE_SHIFT))
#define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + __MEMORY_START)
-#endif
/* PFN start number, because of __MEMORY_START */
#define PFN_START (__MEMORY_START >> PAGE_SHIFT)
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index aef8ae43de13..bb0efb31a8cb 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -196,7 +196,9 @@ static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _
static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+#ifdef CONFIG_HUGETLB_PAGE
static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+#endif
/*
* Macro and implementation to make a page protection as uncachable.
@@ -282,6 +284,8 @@ typedef pte_t *pte_addr_t;
#define GET_IOSPACE(pfn) 0
#define GET_PFN(pfn) (pfn)
+struct mm_struct;
+
/*
* No page table caches to initialise
*/
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 51b05818e4eb..a1906a772df9 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -24,6 +24,8 @@
#include <linux/threads.h>
#include <linux/config.h>
+struct vm_area_struct;
+
extern void paging_init(void);
/* We provide our own get_unmapped_area to avoid cache synonym issue */
diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h
index a8ecb2d6977a..714497099a42 100644
--- a/include/asm-sparc/ptrace.h
+++ b/include/asm-sparc/ptrace.h
@@ -60,6 +60,9 @@ struct sparc_stackf {
#define STACKFRAME_SZ sizeof(struct sparc_stackf)
#ifdef __KERNEL__
+
+#define __ARCH_SYS_PTRACE 1
+
#define user_mode(regs) (!((regs)->psr & PSR_PS))
#define instruction_pointer(regs) ((regs)->pc)
unsigned long profile_pc(struct pt_regs *);
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index a8d326a598f0..7ba845320f5c 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -3,6 +3,7 @@
#include <linux/config.h>
#include <linux/types.h>
+#include <linux/percpu.h>
typedef u32 kprobe_opcode_t;
@@ -18,6 +19,25 @@ struct arch_specific_insn {
kprobe_opcode_t insn[MAX_INSN_SIZE];
};
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned int status;
+ unsigned long orig_tnpc;
+ unsigned long orig_tstate_pil;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ unsigned long kprobe_orig_tnpc;
+ unsigned long kprobe_orig_tstate_pil;
+ long *jprobe_saved_esp;
+ struct pt_regs jprobe_saved_regs;
+ struct pt_regs *jprobe_saved_regs_location;
+ struct sparc_stackf jprobe_saved_stack;
+ struct prev_kprobe prev_kprobe;
+};
+
#ifdef CONFIG_KPROBES
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
index 6194f771e9fc..7eba90c6c753 100644
--- a/include/asm-sparc64/ptrace.h
+++ b/include/asm-sparc64/ptrace.h
@@ -94,6 +94,9 @@ struct sparc_trapf {
#define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
#ifdef __KERNEL__
+
+#define __ARCH_SYS_PTRACE 1
+
#define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \
} while (0)
diff --git a/include/asm-um/ldt-i386.h b/include/asm-um/ldt-i386.h
new file mode 100644
index 000000000000..b42662929b6c
--- /dev/null
+++ b/include/asm-um/ldt-i386.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_I386_H
+#define __ASM_LDT_I386_H
+
+#include "asm/semaphore.h"
+#include "asm/arch/ldt.h"
+
+struct mmu_context_skas;
+extern void ldt_host_info(void);
+extern long init_new_ldt(struct mmu_context_skas * to_mm,
+ struct mmu_context_skas * from_mm);
+extern void free_ldt(struct mmu_context_skas * mm);
+
+#define LDT_PAGES_MAX \
+ ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+ (PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+ ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+ __u32 a;
+ __u32 b;
+};
+
+typedef struct uml_ldt {
+ int entry_count;
+ struct semaphore semaphore;
+ union {
+ struct ldt_entry * pages[LDT_PAGES_MAX];
+ struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+ };
+} uml_ldt_t;
+
+/*
+ * macros stolen from include/asm-i386/desc.h
+ */
+#define LDT_entry_a(info) \
+ ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+ (((info)->base_addr & 0xff000000) | \
+ (((info)->base_addr & 0x00ff0000) >> 16) | \
+ ((info)->limit & 0xf0000) | \
+ (((info)->read_exec_only ^ 1) << 9) | \
+ ((info)->contents << 10) | \
+ (((info)->seg_not_present ^ 1) << 15) | \
+ ((info)->seg_32bit << 22) | \
+ ((info)->limit_in_pages << 23) | \
+ ((info)->useable << 20) | \
+ 0x7000)
+
+#define LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0 )
+
+#endif
diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt.h
index e908439d338a..4466ff6de0fd 100644
--- a/include/asm-um/ldt.h
+++ b/include/asm-um/ldt.h
@@ -1,3 +1,72 @@
+/*
+ * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
+ * Licensed under the GPL
+ *
+ * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
+ */
+
+#ifndef __ASM_LDT_I386_H
+#define __ASM_LDT_I386_H
+
+#include "asm/semaphore.h"
+#include "asm/arch/ldt.h"
+
+struct mmu_context_skas;
+extern void ldt_host_info(void);
+extern long init_new_ldt(struct mmu_context_skas * to_mm,
+ struct mmu_context_skas * from_mm);
+extern void free_ldt(struct mmu_context_skas * mm);
+
+#define LDT_PAGES_MAX \
+ ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE)
+#define LDT_ENTRIES_PER_PAGE \
+ (PAGE_SIZE/LDT_ENTRY_SIZE)
+#define LDT_DIRECT_ENTRIES \
+ ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE)
+
+struct ldt_entry {
+ __u32 a;
+ __u32 b;
+};
+
+typedef struct uml_ldt {
+ int entry_count;
+ struct semaphore semaphore;
+ union {
+ struct ldt_entry * pages[LDT_PAGES_MAX];
+ struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+ };
+} uml_ldt_t;
+
+/*
+ * macros stolen from include/asm-i386/desc.h
+ */
+#define LDT_entry_a(info) \
+ ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
+
+#define LDT_entry_b(info) \
+ (((info)->base_addr & 0xff000000) | \
+ (((info)->base_addr & 0x00ff0000) >> 16) | \
+ ((info)->limit & 0xf0000) | \
+ (((info)->read_exec_only ^ 1) << 9) | \
+ ((info)->contents << 10) | \
+ (((info)->seg_not_present ^ 1) << 15) | \
+ ((info)->seg_32bit << 22) | \
+ ((info)->limit_in_pages << 23) | \
+ ((info)->useable << 20) | \
+ 0x7000)
+
+#define LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0 )
+
+#endif
#ifndef __UM_LDT_H
#define __UM_LDT_H
diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
index 2edb4f1f789c..9a0e48eb542e 100644
--- a/include/asm-um/mmu_context.h
+++ b/include/asm-um/mmu_context.h
@@ -29,7 +29,8 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
* possible.
*/
if (old != new && (current->flags & PF_BORROWED_MM))
- force_flush_all();
+ CHOOSE_MODE(force_flush_all(),
+ switch_mm_skas(&new->context.skas.id));
}
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h
index 8284aa7363f2..395268a8c0de 100644
--- a/include/asm-v850/atomic.h
+++ b/include/asm-v850/atomic.h
@@ -31,7 +31,7 @@ typedef struct { int counter; } atomic_t;
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
-extern __inline__ int atomic_add_return (int i, volatile atomic_t *v)
+static inline int atomic_add_return (int i, volatile atomic_t *v)
{
unsigned long flags;
int res;
diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h
index 0e5c2f210872..b91e799763fd 100644
--- a/include/asm-v850/bitops.h
+++ b/include/asm-v850/bitops.h
@@ -30,7 +30,7 @@
* ffz = Find First Zero in word. Undefined if no zero exists,
* so code should check against ~0UL first..
*/
-extern __inline__ unsigned long ffz (unsigned long word)
+static inline unsigned long ffz (unsigned long word)
{
unsigned long result = 0;
@@ -135,7 +135,7 @@ extern __inline__ unsigned long ffz (unsigned long word)
"m" (*((const char *)(addr) + ((nr) >> 3)))); \
__test_bit_res; \
})
-extern __inline__ int __test_bit (int nr, const void *addr)
+static inline int __test_bit (int nr, const void *addr)
{
int res;
__asm__ __volatile__ ("tst1 %1, [%2]; setf nz, %0"
@@ -157,7 +157,7 @@ extern __inline__ int __test_bit (int nr, const void *addr)
#define find_first_zero_bit(addr, size) \
find_next_zero_bit ((addr), (size), 0)
-extern __inline__ int find_next_zero_bit(const void *addr, int size, int offset)
+static inline int find_next_zero_bit(const void *addr, int size, int offset)
{
unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
unsigned long result = offset & ~31UL;
diff --git a/include/asm-v850/delay.h b/include/asm-v850/delay.h
index 1ce65d48a7c5..6d028e6b2354 100644
--- a/include/asm-v850/delay.h
+++ b/include/asm-v850/delay.h
@@ -16,7 +16,7 @@
#include <asm/param.h>
-extern __inline__ void __delay(unsigned long loops)
+static inline void __delay(unsigned long loops)
{
if (loops)
__asm__ __volatile__ ("1: add -1, %0; bnz 1b"
@@ -33,7 +33,7 @@ extern __inline__ void __delay(unsigned long loops)
extern unsigned long loops_per_jiffy;
-extern __inline__ void udelay(unsigned long usecs)
+static inline void udelay(unsigned long usecs)
{
register unsigned long full_loops, part_loops;
diff --git a/include/asm-v850/hw_irq.h b/include/asm-v850/hw_irq.h
index 4bdc98edb9f8..a8aab4342712 100644
--- a/include/asm-v850/hw_irq.h
+++ b/include/asm-v850/hw_irq.h
@@ -1,7 +1,7 @@
#ifndef __V850_HW_IRQ_H__
#define __V850_HW_IRQ_H__
-extern inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i)
+static inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i)
{
}
diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h
index d41f925f5182..98f929427d3d 100644
--- a/include/asm-v850/processor.h
+++ b/include/asm-v850/processor.h
@@ -59,7 +59,7 @@ struct thread_struct {
/* Do necessary setup to start up a newly executed thread. */
-extern inline void start_thread (struct pt_regs *regs,
+static inline void start_thread (struct pt_regs *regs,
unsigned long pc, unsigned long usp)
{
regs->pc = pc;
@@ -68,7 +68,7 @@ extern inline void start_thread (struct pt_regs *regs,
}
/* Free all resources held by a thread. */
-extern inline void release_thread (struct task_struct *dead_task)
+static inline void release_thread (struct task_struct *dead_task)
{
}
diff --git a/include/asm-v850/semaphore.h b/include/asm-v850/semaphore.h
index df6cdecf6c1f..735baaf3a16e 100644
--- a/include/asm-v850/semaphore.h
+++ b/include/asm-v850/semaphore.h
@@ -24,7 +24,7 @@ struct semaphore {
#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC (name,1)
#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC (name,0)
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
{
*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
}
@@ -52,14 +52,14 @@ extern int __down_interruptible (struct semaphore * sem);
extern int __down_trylock (struct semaphore * sem);
extern void __up (struct semaphore * sem);
-extern inline void down (struct semaphore * sem)
+static inline void down (struct semaphore * sem)
{
might_sleep();
if (atomic_dec_return (&sem->count) < 0)
__down (sem);
}
-extern inline int down_interruptible (struct semaphore * sem)
+static inline int down_interruptible (struct semaphore * sem)
{
int ret = 0;
might_sleep();
@@ -68,7 +68,7 @@ extern inline int down_interruptible (struct semaphore * sem)
return ret;
}
-extern inline int down_trylock (struct semaphore *sem)
+static inline int down_trylock (struct semaphore *sem)
{
int ret = 0;
if (atomic_dec_return (&sem->count) < 0)
@@ -76,7 +76,7 @@ extern inline int down_trylock (struct semaphore *sem)
return ret;
}
-extern inline void up (struct semaphore * sem)
+static inline void up (struct semaphore * sem)
{
if (atomic_inc_return (&sem->count) <= 0)
__up (sem);
diff --git a/include/asm-v850/system.h b/include/asm-v850/system.h
index 20f4c738c04e..107decbd6e6c 100644
--- a/include/asm-v850/system.h
+++ b/include/asm-v850/system.h
@@ -81,7 +81,7 @@ static inline int irqs_disabled (void)
((__typeof__ (*(ptr)))__xchg ((unsigned long)(with), (ptr), sizeof (*(ptr))))
#define tas(ptr) (xchg ((ptr), 1))
-extern inline unsigned long __xchg (unsigned long with,
+static inline unsigned long __xchg (unsigned long with,
__volatile__ void *ptr, int size)
{
unsigned long tmp, flags;
diff --git a/include/asm-v850/tlbflush.h b/include/asm-v850/tlbflush.h
index 501e4498172c..5f2f85f636ea 100644
--- a/include/asm-v850/tlbflush.h
+++ b/include/asm-v850/tlbflush.h
@@ -56,12 +56,12 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
BUG ();
}
-extern inline void flush_tlb_kernel_page(unsigned long addr)
+static inline void flush_tlb_kernel_page(unsigned long addr)
{
BUG ();
}
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
unsigned long start, unsigned long end)
{
BUG ();
diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h
index 188b28597cf1..64563c409bb2 100644
--- a/include/asm-v850/uaccess.h
+++ b/include/asm-v850/uaccess.h
@@ -14,7 +14,7 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-extern inline int access_ok (int type, const void *addr, unsigned long size)
+static inline int access_ok (int type, const void *addr, unsigned long size)
{
/* XXX I guess we should check against real ram bounds at least, and
possibly make sure ADDR is not within the kernel.
diff --git a/include/asm-v850/unaligned.h b/include/asm-v850/unaligned.h
index 65e38362142b..e30b18653a94 100644
--- a/include/asm-v850/unaligned.h
+++ b/include/asm-v850/unaligned.h
@@ -82,19 +82,19 @@ extern int __bug_unaligned_x(void *ptr);
})
-extern inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
+static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
{
*__p++ = __v;
*__p++ = __v >> 8;
}
-extern inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
+static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
{
__put_unaligned_2(__v >> 16, __p + 2);
__put_unaligned_2(__v, __p);
}
-extern inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
+static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
{
/*
* tradeoff: 8 bytes of stack for all unaligned puts (2
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
index a60a35e79222..43862cd6a569 100644
--- a/include/asm-x86_64/elf.h
+++ b/include/asm-x86_64/elf.h
@@ -149,6 +149,8 @@ extern void set_personality_64bit(void);
*/
#define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X)
+struct task_struct;
+
extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index 6d6d883fdf6d..4dd7a7e148d4 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -25,6 +25,7 @@
*/
#include <linux/types.h>
#include <linux/ptrace.h>
+#include <linux/percpu.h>
struct pt_regs;
@@ -48,6 +49,24 @@ struct arch_specific_insn {
kprobe_opcode_t *insn;
};
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned long status;
+ unsigned long old_rflags;
+ unsigned long saved_rflags;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ unsigned long kprobe_old_rflags;
+ unsigned long kprobe_saved_rflags;
+ long *jprobe_saved_rsp;
+ struct pt_regs jprobe_saved_regs;
+ kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
+ struct prev_kprobe prev_kprobe;
+};
+
/* trap3/1 are intr gates for kprobes. So, restore the status of IF,
* if necessary, before executing the original int3/1 (trap) handler.
*/
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 7a07196a7202..7309fffeec9a 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -105,6 +105,8 @@ static inline void pgd_clear (pgd_t * pgd)
#define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte, 0))
+struct mm_struct;
+
static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
{
pte_t pte;
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index 64f1f53874fe..de0667453b2e 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -209,6 +209,8 @@ extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *);
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+struct task_struct;
+
extern void do_copy_regs (xtensa_gregset_t*, struct pt_regs*,
struct task_struct*);
extern void do_restore_regs (xtensa_gregset_t*, struct pt_regs*,
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
index 987e3b802313..7b15afb70c56 100644
--- a/include/asm-xtensa/pgtable.h
+++ b/include/asm-xtensa/pgtable.h
@@ -278,6 +278,8 @@ static inline void update_pte(pte_t *ptep, pte_t pteval)
#endif
}
+struct mm_struct;
+
static inline void
set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
{
@@ -294,6 +296,7 @@ set_pmd(pmd_t *pmdp, pmd_t pmdval)
#endif
}
+struct vm_area_struct;
static inline int
ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
index 2a10e193b929..f10c3487cd4c 100644
--- a/include/asm-xtensa/semaphore.h
+++ b/include/asm-xtensa/semaphore.h
@@ -38,6 +38,7 @@ struct semaphore {
static inline void sema_init (struct semaphore *sem, int val)
{
atomic_set(&sem->count, val);
+ sem->sleepers = 0;
init_waitqueue_head(&sem->wait);
}
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 0decf66117c1..403d71dcb7c8 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -183,6 +183,7 @@ struct kioctx {
struct list_head active_reqs; /* used for cancellation */
struct list_head run_list; /* used for kicked reqs */
+ /* sys_io_setup currently limits this to an unsigned int */
unsigned max_reqs;
struct aio_ring_info ring_info;
@@ -234,7 +235,7 @@ static inline struct kiocb *list_kiocb(struct list_head *h)
}
/* for sysctl: */
-extern atomic_t aio_nr;
-extern unsigned aio_max_nr;
+extern unsigned long aio_nr;
+extern unsigned long aio_max_nr;
#endif /* __LINUX__AIO_H */
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
new file mode 100644
index 000000000000..70ab56317380
--- /dev/null
+++ b/include/linux/cn_proc.h
@@ -0,0 +1,127 @@
+/*
+ * cn_proc.h - process events connector
+ *
+ * Copyright (C) Matt Helsley, IBM Corp. 2005
+ * Based on cn_fork.h by Nguyen Anh Quynh and Guillaume Thouvenin
+ * Original copyright notice follows:
+ * Copyright (C) 2005 Nguyen Anh Quynh <aquynh@gmail.com>
+ * Copyright (C) 2005 Guillaume Thouvenin <guillaume.thouvenin@bull.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef CN_PROC_H
+#define CN_PROC_H
+
+#include <linux/types.h>
+#include <linux/connector.h>
+
+/*
+ * Userspace sends this enum to register with the kernel that it is listening
+ * for events on the connector.
+ */
+enum proc_cn_mcast_op {
+ PROC_CN_MCAST_LISTEN = 1,
+ PROC_CN_MCAST_IGNORE = 2
+};
+
+/*
+ * From the user's point of view, the process
+ * ID is the thread group ID and thread ID is the internal
+ * kernel "pid". So, fields are assigned as follow:
+ *
+ * In user space - In kernel space
+ *
+ * parent process ID = parent->tgid
+ * parent thread ID = parent->pid
+ * child process ID = child->tgid
+ * child thread ID = child->pid
+ */
+
+struct proc_event {
+ enum what {
+ /* Use successive bits so the enums can be used to record
+ * sets of events as well
+ */
+ PROC_EVENT_NONE = 0x00000000,
+ PROC_EVENT_FORK = 0x00000001,
+ PROC_EVENT_EXEC = 0x00000002,
+ PROC_EVENT_UID = 0x00000004,
+ PROC_EVENT_GID = 0x00000040,
+ /* "next" should be 0x00000400 */
+ /* "last" is the last process event: exit */
+ PROC_EVENT_EXIT = 0x80000000
+ } what;
+ __u32 cpu;
+ union { /* must be last field of proc_event struct */
+ struct {
+ __u32 err;
+ } ack;
+
+ struct fork_proc_event {
+ pid_t parent_pid;
+ pid_t parent_tgid;
+ pid_t child_pid;
+ pid_t child_tgid;
+ } fork;
+
+ struct exec_proc_event {
+ pid_t process_pid;
+ pid_t process_tgid;
+ } exec;
+
+ struct id_proc_event {
+ pid_t process_pid;
+ pid_t process_tgid;
+ union {
+ uid_t ruid; /* current->uid */
+ gid_t rgid; /* current->gid */
+ } r;
+ union {
+ uid_t euid;
+ gid_t egid;
+ } e;
+ } id;
+
+ struct exit_proc_event {
+ pid_t process_pid;
+ pid_t process_tgid;
+ __u32 exit_code, exit_signal;
+ } exit;
+ } event_data;
+};
+
+#ifdef __KERNEL__
+#ifdef CONFIG_PROC_EVENTS
+void proc_fork_connector(struct task_struct *task);
+void proc_exec_connector(struct task_struct *task);
+void proc_id_connector(struct task_struct *task, int which_id);
+void proc_exit_connector(struct task_struct *task);
+#else
+static inline void proc_fork_connector(struct task_struct *task)
+{}
+
+static inline void proc_exec_connector(struct task_struct *task)
+{}
+
+static inline void proc_id_connector(struct task_struct *task,
+ int which_id)
+{}
+
+static inline void proc_exit_connector(struct task_struct *task)
+{}
+#endif /* CONFIG_PROC_EVENTS */
+#endif /* __KERNEL__ */
+#endif /* CN_PROC_H */
diff --git a/include/linux/connector.h b/include/linux/connector.h
index 95952cc1f525..c5769c6585f4 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -27,6 +27,12 @@
#define CN_IDX_CONNECTOR 0xffffffff
#define CN_VAL_CONNECTOR 0xffffffff
+/*
+ * Process Events connector unique ids -- used for message routing
+ */
+#define CN_IDX_PROC 0x1
+#define CN_VAL_PROC 0x1
+
#define CN_NETLINK_USERS 1
/*
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index 725be90ef55e..f8e5587a0f92 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -9,6 +9,8 @@
* to achieve effects such as fast scrolling by changing the origin.
*/
+#include <linux/vt.h>
+
struct vt_struct;
#define NPAR 16
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c698055266d0..e7ff98e395f6 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -810,7 +810,6 @@ struct fb_info {
extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_blank(struct fb_info *info, int blank);
-extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image);
@@ -898,11 +897,13 @@ extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
struct list_head *head);
extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
struct list_head *head);
-extern struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var,
+extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode,
struct list_head *head);
extern void fb_destroy_modelist(struct list_head *head);
extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
struct list_head *head);
+extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs,
+ struct list_head *head);
/* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
diff --git a/include/linux/file.h b/include/linux/file.h
index f5bbd4c508b3..d3b1a15d5f21 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -59,9 +59,9 @@ extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag));
extern void put_filp(struct file *);
extern int get_unused_fd(void);
extern void FASTCALL(put_unused_fd(unsigned int fd));
-struct kmem_cache_s;
-extern void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags);
-extern void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags);
+struct kmem_cache;
+extern void filp_ctor(void * objp, struct kmem_cache *cachep, unsigned long cflags);
+extern void filp_dtor(void * objp, struct kmem_cache *cachep, unsigned long dflags);
extern struct file ** alloc_fd_array(int);
extern void free_fd_array(struct file **, int);
diff --git a/include/linux/font.h b/include/linux/font.h
index 53b129f07f6f..8aac48c37f3d 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -31,6 +31,7 @@ struct font_desc {
#define SUN12x22_IDX 7
#define ACORN8x8_IDX 8
#define MINI4x6_IDX 9
+#define RL_IDX 10
extern const struct font_desc font_vga_8x8,
font_vga_8x16,
@@ -41,6 +42,7 @@ extern const struct font_desc font_vga_8x8,
font_sun_8x16,
font_sun_12x22,
font_acorn_8x8,
+ font_rl,
font_mini_4x6;
/* Find a font with a specific name */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6d6226732c93..9a593ef262ef 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -264,6 +264,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define ATTR_ATTR_FLAG 1024
#define ATTR_KILL_SUID 2048
#define ATTR_KILL_SGID 4096
+#define ATTR_FILE 8192
/*
* This is the Inode Attributes structure, used for notify_change(). It
@@ -283,6 +284,13 @@ struct iattr {
struct timespec ia_atime;
struct timespec ia_mtime;
struct timespec ia_ctime;
+
+ /*
+ * Not an attribute, but an auxilary info for filesystems wanting to
+ * implement an ftruncate() like method. NOTE: filesystem should
+ * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
+ */
+ struct file *ia_file;
};
/*
@@ -1088,6 +1096,8 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc);
* @get_name: find the name for a given inode in a given directory
* @get_parent: find the parent of a given directory
* @get_dentry: find a dentry for the inode given a file handle sub-fragment
+ * @find_exported_dentry:
+ * set by the exporting module to a standard helper function.
*
* Description:
* The export_operations structure provides a means for nfsd to communicate
@@ -1288,7 +1298,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
/* fs/open.c */
-extern int do_truncate(struct dentry *, loff_t start);
+extern int do_truncate(struct dentry *, loff_t start, struct file *filp);
extern long do_sys_open(const char __user *filename, int flags, int mode);
extern struct file *filp_open(const char *, int, int);
extern struct file * dentry_open(struct dentry *, struct vfsmount *, int);
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index f98854c2abd7..b76b558b03d4 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -14,7 +14,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 2
+#define FUSE_KERNEL_MINOR_VERSION 3
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -61,6 +61,7 @@ struct fuse_kstatfs {
#define FATTR_SIZE (1 << 3)
#define FATTR_ATIME (1 << 4)
#define FATTR_MTIME (1 << 5)
+#define FATTR_FH (1 << 6)
/**
* Flags returned by the OPEN request
@@ -99,7 +100,9 @@ enum fuse_opcode {
FUSE_OPENDIR = 27,
FUSE_READDIR = 28,
FUSE_RELEASEDIR = 29,
- FUSE_FSYNCDIR = 30
+ FUSE_FSYNCDIR = 30,
+ FUSE_ACCESS = 34,
+ FUSE_CREATE = 35
};
/* Conservative buffer size for the client */
@@ -152,12 +155,25 @@ struct fuse_link_in {
struct fuse_setattr_in {
__u32 valid;
__u32 padding;
- struct fuse_attr attr;
+ __u64 fh;
+ __u64 size;
+ __u64 unused1;
+ __u64 atime;
+ __u64 mtime;
+ __u64 unused2;
+ __u32 atimensec;
+ __u32 mtimensec;
+ __u32 unused3;
+ __u32 mode;
+ __u32 unused4;
+ __u32 uid;
+ __u32 gid;
+ __u32 unused5;
};
struct fuse_open_in {
__u32 flags;
- __u32 padding;
+ __u32 mode;
};
struct fuse_open_out {
@@ -222,6 +238,11 @@ struct fuse_getxattr_out {
__u32 padding;
};
+struct fuse_access_in {
+ __u32 mask;
+ __u32 padding;
+};
+
struct fuse_init_in_out {
__u32 major;
__u32 minor;
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 18d010bee635..cd6bd001ba4e 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -94,7 +94,7 @@ extern struct resource iomem_resource;
extern int request_resource(struct resource *root, struct resource *new);
extern struct resource * ____request_resource(struct resource *root, struct resource *new);
extern int release_resource(struct resource *new);
-extern int insert_resource(struct resource *parent, struct resource *new);
+extern __deprecated_for_modules int insert_resource(struct resource *parent, struct resource *new);
extern int allocate_resource(struct resource *root, struct resource *new,
unsigned long size,
unsigned long min, unsigned long max,
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 938d55b813a5..d6276e60b3bf 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -256,10 +256,7 @@ struct ipmi_recv_msg
};
/* Allocate and free the receive message. */
-static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
-{
- msg->done(msg);
-}
+void ipmi_free_recv_msg(struct ipmi_recv_msg *msg);
struct ipmi_user_hndl
{
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 69681c3b1f05..c516382fbec2 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -10,6 +10,7 @@
*/
#include <linux/config.h>
+#include <asm/smp.h> /* cpu_online_map */
#if !defined(CONFIG_ARCH_S390)
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index be197eb90077..aa56172c6fed 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -611,6 +611,9 @@ struct transaction_s
* @j_revoke: The revoke table - maintains the list of revoked blocks in the
* current transaction.
* @j_revoke_table: alternate revoke tables for j_revoke
+ * @j_wbuf: array of buffer_heads for journal_commit_transaction
+ * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the
+ * number that will fit in j_blocksize
* @j_private: An opaque pointer to fs-private information.
*/
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index f1925ccc9fe1..b1e407a4fbda 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -168,7 +168,7 @@ static inline void console_verbose(void)
extern void bust_spinlocks(int yes);
extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */
-extern int panic_timeout;
+extern __deprecated_for_modules int panic_timeout;
extern int panic_on_oops;
extern int tainted;
extern const char *print_tainted(void);
@@ -266,7 +266,6 @@ extern void dump_stack(void);
/**
* container_of - cast a member of a structure out to the containing structure
- *
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index dba27749b428..a484572c302e 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -6,6 +6,7 @@
#include <linux/smp.h>
#include <linux/threads.h>
#include <linux/percpu.h>
+#include <linux/cpumask.h>
#include <asm/cputime.h>
/*
@@ -43,11 +44,10 @@ extern unsigned long long nr_context_switches(void);
*/
static inline int kstat_irqs(int irq)
{
- int i, sum=0;
+ int cpu, sum = 0;
- for (i = 0; i < NR_CPUS; i++)
- if (cpu_possible(i))
- sum += kstat_cpu(i).irqs[irq];
+ for_each_cpu(cpu)
+ sum += kstat_cpu(cpu).irqs[irq];
return sum;
}
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index e30afdca7917..e373c4a9de53 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -33,6 +33,9 @@
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/smp.h>
+#include <linux/percpu.h>
+#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
#include <asm/kprobes.h>
@@ -106,6 +109,9 @@ struct jprobe {
kprobe_opcode_t *entry; /* probe handling code to jump to */
};
+DECLARE_PER_CPU(struct kprobe *, current_kprobe);
+DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
#ifdef ARCH_SUPPORTS_KRETPROBES
extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
#else /* ARCH_SUPPORTS_KRETPROBES */
@@ -142,17 +148,7 @@ struct kretprobe_instance {
};
#ifdef CONFIG_KPROBES
-/* Locks kprobe: irq must be disabled */
-void lock_kprobes(void);
-void unlock_kprobes(void);
-
-/* kprobe running now on this CPU? */
-static inline int kprobe_running(void)
-{
- extern unsigned int kprobe_cpu;
- return kprobe_cpu == smp_processor_id();
-}
-
+extern spinlock_t kretprobe_lock;
extern int arch_prepare_kprobe(struct kprobe *p);
extern void arch_copy_kprobe(struct kprobe *p);
extern void arch_arm_kprobe(struct kprobe *p);
@@ -163,10 +159,26 @@ extern void show_registers(struct pt_regs *regs);
extern kprobe_opcode_t *get_insn_slot(void);
extern void free_insn_slot(kprobe_opcode_t *slot);
-/* Get the kprobe at this addr (if any). Must have called lock_kprobes */
+/* Get the kprobe at this addr (if any) - called with preemption disabled */
struct kprobe *get_kprobe(void *addr);
struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
+/* kprobe_running() will just return the current_kprobe on this CPU */
+static inline struct kprobe *kprobe_running(void)
+{
+ return (__get_cpu_var(current_kprobe));
+}
+
+static inline void reset_current_kprobe(void)
+{
+ __get_cpu_var(current_kprobe) = NULL;
+}
+
+static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void)
+{
+ return (&__get_cpu_var(kprobe_ctlblk));
+}
+
int register_kprobe(struct kprobe *p);
void unregister_kprobe(struct kprobe *p);
int setjmp_pre_handler(struct kprobe *, struct pt_regs *);
@@ -183,9 +195,9 @@ void add_rp_inst(struct kretprobe_instance *ri);
void kprobe_flush_task(struct task_struct *tk);
void recycle_rp_inst(struct kretprobe_instance *ri);
#else /* CONFIG_KPROBES */
-static inline int kprobe_running(void)
+static inline struct kprobe *kprobe_running(void)
{
- return 0;
+ return NULL;
}
static inline int register_kprobe(struct kprobe *p)
{
diff --git a/include/linux/list.h b/include/linux/list.h
index 084971f333fe..fbfca73355a3 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -601,7 +601,7 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
* or hlist_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
- * hlist_for_each_rcu(), used to prevent memory-consistency
+ * hlist_for_each_entry_rcu(), used to prevent memory-consistency
* problems on Alpha CPUs. Regardless of the type of CPU, the
* list-traversal primitive must be guarded by rcu_read_lock().
*/
@@ -650,7 +650,7 @@ static inline void hlist_add_after(struct hlist_node *n,
* or hlist_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
- * hlist_for_each_rcu(), used to prevent memory-consistency
+ * hlist_for_each_entry_rcu(), used to prevent memory-consistency
* problems on Alpha CPUs.
*/
static inline void hlist_add_before_rcu(struct hlist_node *n,
@@ -675,7 +675,7 @@ static inline void hlist_add_before_rcu(struct hlist_node *n,
* or hlist_del_rcu(), running on this same list.
* However, it is perfectly legal to run concurrently with
* the _rcu list-traversal primitives, such as
- * hlist_for_each_rcu(), used to prevent memory-consistency
+ * hlist_for_each_entry_rcu(), used to prevent memory-consistency
* problems on Alpha CPUs.
*/
static inline void hlist_add_after_rcu(struct hlist_node *prev,
@@ -699,11 +699,6 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
-#define hlist_for_each_rcu(pos, head) \
- for ((pos) = (head)->first; \
- rcu_dereference((pos)) && ({ prefetch((pos)->next); 1; }); \
- (pos) = (pos)->next)
-
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop counter.
@@ -756,7 +751,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
/**
* hlist_for_each_entry_rcu - iterate over rcu list of given type
- * @pos: the type * to use as a loop counter.
+ * @tpos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 0def328ab5cf..9a424383e6c6 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -54,6 +54,9 @@ struct memory_block {
*/
#define MEM_MAPPING_INVALID (1<<3)
+struct notifier_block;
+struct mem_section;
+
#ifndef CONFIG_MEMORY_HOTPLUG
static inline int memory_dev_init(void)
{
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5c1fb0a2e806..7b115feca4df 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -932,13 +932,13 @@ int write_one_page(struct page *page, int wait);
* turning readahead off */
int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
- unsigned long offset, unsigned long nr_to_read);
+ pgoff_t offset, unsigned long nr_to_read);
int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
- unsigned long offset, unsigned long nr_to_read);
-unsigned long page_cache_readahead(struct address_space *mapping,
+ pgoff_t offset, unsigned long nr_to_read);
+unsigned long page_cache_readahead(struct address_space *mapping,
struct file_ra_state *ra,
struct file *filp,
- unsigned long offset,
+ pgoff_t offset,
unsigned long size);
void handle_ra_miss(struct address_space *mapping,
struct file_ra_state *ra, pgoff_t offset);
diff --git a/include/linux/net.h b/include/linux/net.h
index 4e981585a89a..d6a41e6577f6 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -71,6 +71,7 @@ typedef enum {
* @SOCK_RAW: raw socket
* @SOCK_RDM: reliably-delivered message
* @SOCK_SEQPACKET: sequential packet socket
+ * @SOCK_DCCP: Datagram Congestion Control Protocol socket
* @SOCK_PACKET: linux specific way of getting packets at the dev level.
* For writing rarp and other similar things on the user level.
*
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 6d5a24f3fc6d..51c231a1e5a6 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -60,7 +60,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int);
extern struct svc_program nfsd_program;
extern struct svc_version nfsd_version2, nfsd_version3,
nfsd_version4;
-
+extern struct svc_serv *nfsd_serv;
/*
* Function prototypes.
*/
diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h
index e65c9db6d13f..781efbf94ed3 100644
--- a/include/linux/nfsd/syscall.h
+++ b/include/linux/nfsd/syscall.h
@@ -39,6 +39,21 @@
#define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */
#define NFSCTL_GETFS 8 /* get an fh by path with max FH len */
+/*
+ * Macros used to set version
+ */
+#define NFSCTL_VERSET(_cltbits, _v) ((_cltbits) |= (1 << (_v)))
+#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
+#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
+
+#if defined(CONFIG_NFSD_V4)
+#define NFSCTL_VERALL (0x1c /* 0b011100 */)
+#elif defined(CONFIG_NFSD_V3)
+#define NFSCTL_VERALL (0x0c /* 0b001100 */)
+#else
+#define NFSCTL_VERALL (0x04 /* 0b000100 */)
+#endif
+
/* SVC */
struct nfsctl_svc {
unsigned short svc_port;
@@ -120,6 +135,8 @@ extern int exp_delclient(struct nfsctl_client *ncp);
extern int exp_export(struct nfsctl_export *nxp);
extern int exp_unexport(struct nfsctl_export *nxp);
+extern unsigned int nfsd_versbits;
+
#endif /* __KERNEL__ */
#endif /* NFSD_SYSCALL_H */
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 21e18ce7ca63..3c2a71b43bac 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -42,7 +42,7 @@ struct nfsd3_writeargs {
__u64 offset;
__u32 count;
int stable;
- int len;
+ __u32 len;
struct kvec vec[RPCSVC_MAXPAGES];
int vlen;
};
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 8cadfdeef674..9a96f0588393 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -519,6 +519,7 @@
#define PCI_DEVICE_ID_MATROX_MIL 0x0519
#define PCI_DEVICE_ID_MATROX_MYS 0x051A
#define PCI_DEVICE_ID_MATROX_MIL_2 0x051b
+#define PCI_DEVICE_ID_MATROX_MYS_AGP 0x051e
#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f
#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10
#define PCI_DEVICE_ID_MATROX_G100_MM 0x1000
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index aadbac29103c..584d57cb393a 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -353,7 +353,6 @@ struct pnp_protocol {
int pnp_register_protocol(struct pnp_protocol *protocol);
void pnp_unregister_protocol(struct pnp_protocol *protocol);
int pnp_add_device(struct pnp_dev *dev);
-void pnp_remove_device(struct pnp_dev *dev);
int pnp_device_attach(struct pnp_dev *pnp_dev);
void pnp_device_detach(struct pnp_dev *pnp_dev);
extern struct list_head pnp_global;
@@ -399,7 +398,6 @@ static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return
static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { }
static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; }
static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; }
-static inline void pnp_remove_device(struct pnp_dev *dev) { }
static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index dc6f3647bfbc..b2b3dba1298d 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -78,6 +78,8 @@
#include <linux/compiler.h> /* For unlikely. */
#include <linux/sched.h> /* For struct task_struct. */
+
+extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
extern int ptrace_attach(struct task_struct *tsk);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index d211507ab246..4f34d3d60f2e 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -198,38 +198,38 @@ static __inline__ int DQUOT_OFF(struct super_block *sb)
#define DQUOT_SYNC(sb) do { } while(0)
#define DQUOT_OFF(sb) do { } while(0)
#define DQUOT_TRANSFER(inode, iattr) (0)
-extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
inode_add_bytes(inode, nr);
return 0;
}
-extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
{
DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr);
mark_inode_dirty(inode);
return 0;
}
-extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
inode_add_bytes(inode, nr);
return 0;
}
-extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
+static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
{
DQUOT_ALLOC_SPACE_NODIRTY(inode, nr);
mark_inode_dirty(inode);
return 0;
}
-extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
+static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
inode_sub_bytes(inode, nr);
}
-extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
+static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
{
DQUOT_FREE_SPACE_NODIRTY(inode, nr);
mark_inode_dirty(inode);
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 9f0f9281f42a..36e5d269612f 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -46,6 +46,7 @@ do { \
int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
+void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
void *radix_tree_delete(struct radix_tree_root *, unsigned long);
unsigned int
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
diff --git a/include/linux/rio.h b/include/linux/rio.h
new file mode 100644
index 000000000000..c7e907faae9c
--- /dev/null
+++ b/include/linux/rio.h
@@ -0,0 +1,325 @@
+/*
+ * RapidIO interconnect services
+ * (RapidIO Interconnect Specification, http://www.rapidio.org)
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#ifndef LINUX_RIO_H
+#define LINUX_RIO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/rio_regs.h>
+
+#define RIO_ANY_DESTID 0xff
+#define RIO_NO_HOPCOUNT -1
+
+#define RIO_MAX_MPORT_RESOURCES 16
+#define RIO_MAX_DEV_RESOURCES 16
+
+#define RIO_GLOBAL_TABLE 0xff /* Indicates access of a switch's
+ global routing table if it
+ has multiple (or per port)
+ tables */
+
+#define RIO_INVALID_ROUTE 0xff /* Indicates that a route table
+ entry is invalid (no route
+ exists for the device ID) */
+
+#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
+#define RIO_MAX_ROUTE_ENTRIES (1 << 8)
+#else
+#define RIO_MAX_ROUTE_ENTRIES (1 << 16)
+#endif
+
+#define RIO_MAX_MBOX 4
+#define RIO_MAX_MSG_SIZE 0x1000
+
+/*
+ * Error values that may be returned by RIO functions.
+ */
+#define RIO_SUCCESSFUL 0x00
+#define RIO_BAD_SIZE 0x81
+
+/*
+ * For RIO devices, the region numbers are assigned this way:
+ *
+ * 0 RapidIO outbound doorbells
+ * 1-15 RapidIO memory regions
+ *
+ * For RIO master ports, the region number are assigned this way:
+ *
+ * 0 RapidIO inbound doorbells
+ * 1 RapidIO inbound mailboxes
+ * 1 RapidIO outbound mailboxes
+ */
+#define RIO_DOORBELL_RESOURCE 0
+#define RIO_INB_MBOX_RESOURCE 1
+#define RIO_OUTB_MBOX_RESOURCE 2
+
+extern struct bus_type rio_bus_type;
+extern struct list_head rio_devices; /* list of all devices */
+
+struct rio_mport;
+
+/**
+ * struct rio_dev - RIO device info
+ * @global_list: Node in list of all RIO devices
+ * @net_list: Node in list of RIO devices in a network
+ * @net: Network this device is a part of
+ * @did: Device ID
+ * @vid: Vendor ID
+ * @device_rev: Device revision
+ * @asm_did: Assembly device ID
+ * @asm_vid: Assembly vendor ID
+ * @asm_rev: Assembly revision
+ * @efptr: Extended feature pointer
+ * @pef: Processing element features
+ * @swpinfo: Switch port info
+ * @src_ops: Source operation capabilities
+ * @dst_ops: Destination operation capabilities
+ * @dma_mask: Mask of bits of RIO address this device implements
+ * @rswitch: Pointer to &struct rio_switch if valid for this device
+ * @driver: Driver claiming this device
+ * @dev: Device model device
+ * @riores: RIO resources this device owns
+ * @destid: Network destination ID
+ */
+struct rio_dev {
+ struct list_head global_list; /* node in list of all RIO devices */
+ struct list_head net_list; /* node in per net list */
+ struct rio_net *net; /* RIO net this device resides in */
+ u16 did;
+ u16 vid;
+ u32 device_rev;
+ u16 asm_did;
+ u16 asm_vid;
+ u16 asm_rev;
+ u16 efptr;
+ u32 pef;
+ u32 swpinfo; /* Only used for switches */
+ u32 src_ops;
+ u32 dst_ops;
+ u64 dma_mask;
+ struct rio_switch *rswitch; /* RIO switch info */
+ struct rio_driver *driver; /* RIO driver claiming this device */
+ struct device dev; /* LDM device structure */
+ struct resource riores[RIO_MAX_DEV_RESOURCES];
+ u16 destid;
+};
+
+#define rio_dev_g(n) list_entry(n, struct rio_dev, global_list)
+#define rio_dev_f(n) list_entry(n, struct rio_dev, net_list)
+#define to_rio_dev(n) container_of(n, struct rio_dev, dev)
+
+/**
+ * struct rio_msg - RIO message event
+ * @res: Mailbox resource
+ * @mcback: Message event callback
+ */
+struct rio_msg {
+ struct resource *res;
+ void (*mcback) (struct rio_mport * mport, void *dev_id, int mbox, int slot);
+};
+
+/**
+ * struct rio_dbell - RIO doorbell event
+ * @node: Node in list of doorbell events
+ * @res: Doorbell resource
+ * @dinb: Doorbell event callback
+ * @dev_id: Device specific pointer to pass on event
+ */
+struct rio_dbell {
+ struct list_head node;
+ struct resource *res;
+ void (*dinb) (struct rio_mport *mport, void *dev_id, u16 src, u16 dst, u16 info);
+ void *dev_id;
+};
+
+/**
+ * struct rio_mport - RIO master port info
+ * @dbells: List of doorbell events
+ * @node: Node in global list of master ports
+ * @nnode: Node in network list of master ports
+ * @iores: I/O mem resource that this master port interface owns
+ * @riores: RIO resources that this master port interfaces owns
+ * @inb_msg: RIO inbound message event descriptors
+ * @outb_msg: RIO outbound message event descriptors
+ * @host_deviceid: Host device ID associated with this master port
+ * @ops: configuration space functions
+ * @id: Port ID, unique among all ports
+ * @index: Port index, unique among all port interfaces of the same type
+ * @name: Port name string
+ */
+struct rio_mport {
+ struct list_head dbells; /* list of doorbell events */
+ struct list_head node; /* node in global list of ports */
+ struct list_head nnode; /* node in net list of ports */
+ struct resource iores;
+ struct resource riores[RIO_MAX_MPORT_RESOURCES];
+ struct rio_msg inb_msg[RIO_MAX_MBOX];
+ struct rio_msg outb_msg[RIO_MAX_MBOX];
+ int host_deviceid; /* Host device ID */
+ struct rio_ops *ops; /* maintenance transaction functions */
+ unsigned char id; /* port ID, unique among all ports */
+ unsigned char index; /* port index, unique among all port
+ interfaces of the same type */
+ unsigned char name[40];
+};
+
+/**
+ * struct rio_net - RIO network info
+ * @node: Node in global list of RIO networks
+ * @devices: List of devices in this network
+ * @mports: List of master ports accessing this network
+ * @hport: Default port for accessing this network
+ * @id: RIO network ID
+ */
+struct rio_net {
+ struct list_head node; /* node in list of networks */
+ struct list_head devices; /* list of devices in this net */
+ struct list_head mports; /* list of ports accessing net */
+ struct rio_mport *hport; /* primary port for accessing net */
+ unsigned char id; /* RIO network ID */
+};
+
+/**
+ * struct rio_switch - RIO switch info
+ * @node: Node in global list of switches
+ * @switchid: Switch ID that is unique across a network
+ * @hopcount: Hopcount to this switch
+ * @destid: Associated destid in the path
+ * @route_table: Copy of switch routing table
+ * @add_entry: Callback for switch-specific route add function
+ * @get_entry: Callback for switch-specific route get function
+ */
+struct rio_switch {
+ struct list_head node;
+ u16 switchid;
+ u16 hopcount;
+ u16 destid;
+ u8 route_table[RIO_MAX_ROUTE_ENTRIES];
+ int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 route_port);
+ int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 * route_port);
+};
+
+/* Low-level architecture-dependent routines */
+
+/**
+ * struct rio_ops - Low-level RIO configuration space operations
+ * @lcread: Callback to perform local (master port) read of config space.
+ * @lcwrite: Callback to perform local (master port) write of config space.
+ * @cread: Callback to perform network read of config space.
+ * @cwrite: Callback to perform network write of config space.
+ * @dsend: Callback to send a doorbell message.
+ */
+struct rio_ops {
+ int (*lcread) (int index, u32 offset, int len, u32 * data);
+ int (*lcwrite) (int index, u32 offset, int len, u32 data);
+ int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len,
+ u32 * data);
+ int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len,
+ u32 data);
+ int (*dsend) (int index, u16 destid, u16 data);
+};
+
+#define RIO_RESOURCE_MEM 0x00000100
+#define RIO_RESOURCE_DOORBELL 0x00000200
+#define RIO_RESOURCE_MAILBOX 0x00000400
+
+#define RIO_RESOURCE_CACHEABLE 0x00010000
+#define RIO_RESOURCE_PCI 0x00020000
+
+#define RIO_RESOURCE_BUSY 0x80000000
+
+/**
+ * struct rio_driver - RIO driver info
+ * @node: Node in list of drivers
+ * @name: RIO driver name
+ * @id_table: RIO device ids to be associated with this driver
+ * @probe: RIO device inserted
+ * @remove: RIO device removed
+ * @suspend: RIO device suspended
+ * @resume: RIO device awakened
+ * @enable_wake: RIO device enable wake event
+ * @driver: LDM driver struct
+ *
+ * Provides info on a RIO device driver for insertion/removal and
+ * power management purposes.
+ */
+struct rio_driver {
+ struct list_head node;
+ char *name;
+ const struct rio_device_id *id_table;
+ int (*probe) (struct rio_dev * dev, const struct rio_device_id * id);
+ void (*remove) (struct rio_dev * dev);
+ int (*suspend) (struct rio_dev * dev, u32 state);
+ int (*resume) (struct rio_dev * dev);
+ int (*enable_wake) (struct rio_dev * dev, u32 state, int enable);
+ struct device_driver driver;
+};
+
+#define to_rio_driver(drv) container_of(drv,struct rio_driver, driver)
+
+/**
+ * struct rio_device_id - RIO device identifier
+ * @did: RIO device ID
+ * @vid: RIO vendor ID
+ * @asm_did: RIO assembly device ID
+ * @asm_vid: RIO assembly vendor ID
+ *
+ * Identifies a RIO device based on both the device/vendor IDs and
+ * the assembly device/vendor IDs.
+ */
+struct rio_device_id {
+ u16 did, vid;
+ u16 asm_did, asm_vid;
+};
+
+/**
+ * struct rio_route_ops - Per-switch route operations
+ * @vid: RIO vendor ID
+ * @did: RIO device ID
+ * @add_hook: Callback that adds a route entry
+ * @get_hook: Callback that gets a route entry
+ *
+ * Defines the operations that are necessary to manipulate the route
+ * tables for a particular RIO switch device.
+ */
+struct rio_route_ops {
+ u16 vid, did;
+ int (*add_hook) (struct rio_mport * mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 route_port);
+ int (*get_hook) (struct rio_mport * mport, u16 destid, u8 hopcount,
+ u16 table, u16 route_destid, u8 * route_port);
+};
+
+/* Architecture and hardware-specific functions */
+extern int rio_init_mports(void);
+extern void rio_register_mport(struct rio_mport *);
+extern int rio_hw_add_outb_message(struct rio_mport *, struct rio_dev *, int,
+ void *, size_t);
+extern int rio_hw_add_inb_buffer(struct rio_mport *, int, void *);
+extern void *rio_hw_get_inb_message(struct rio_mport *, int);
+extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int);
+extern void rio_close_inb_mbox(struct rio_mport *, int);
+extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int);
+extern void rio_close_outb_mbox(struct rio_mport *, int);
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_RIO_H */
diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h
new file mode 100644
index 000000000000..3bd7cce19e26
--- /dev/null
+++ b/include/linux/rio_drv.h
@@ -0,0 +1,469 @@
+/*
+ * RapidIO driver services
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#ifndef LINUX_RIO_DRV_H
+#define LINUX_RIO_DRV_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/rio.h>
+
+extern int __rio_local_read_config_32(struct rio_mport *port, u32 offset,
+ u32 * data);
+extern int __rio_local_write_config_32(struct rio_mport *port, u32 offset,
+ u32 data);
+extern int __rio_local_read_config_16(struct rio_mport *port, u32 offset,
+ u16 * data);
+extern int __rio_local_write_config_16(struct rio_mport *port, u32 offset,
+ u16 data);
+extern int __rio_local_read_config_8(struct rio_mport *port, u32 offset,
+ u8 * data);
+extern int __rio_local_write_config_8(struct rio_mport *port, u32 offset,
+ u8 data);
+
+extern int rio_mport_read_config_32(struct rio_mport *port, u16 destid,
+ u8 hopcount, u32 offset, u32 * data);
+extern int rio_mport_write_config_32(struct rio_mport *port, u16 destid,
+ u8 hopcount, u32 offset, u32 data);
+extern int rio_mport_read_config_16(struct rio_mport *port, u16 destid,
+ u8 hopcount, u32 offset, u16 * data);
+extern int rio_mport_write_config_16(struct rio_mport *port, u16 destid,
+ u8 hopcount, u32 offset, u16 data);
+extern int rio_mport_read_config_8(struct rio_mport *port, u16 destid,
+ u8 hopcount, u32 offset, u8 * data);
+extern int rio_mport_write_config_8(struct rio_mport *port, u16 destid,
+ u8 hopcount, u32 offset, u8 data);
+
+/**
+ * rio_local_read_config_32 - Read 32 bits from local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Pointer to read data into
+ *
+ * Reads 32 bits of data from the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_read_config_32(struct rio_mport *port, u32 offset,
+ u32 * data)
+{
+ return __rio_local_read_config_32(port, offset, data);
+}
+
+/**
+ * rio_local_write_config_32 - Write 32 bits to local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Data to be written
+ *
+ * Writes 32 bits of data to the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_write_config_32(struct rio_mport *port, u32 offset,
+ u32 data)
+{
+ return __rio_local_write_config_32(port, offset, data);
+}
+
+/**
+ * rio_local_read_config_16 - Read 16 bits from local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Pointer to read data into
+ *
+ * Reads 16 bits of data from the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_read_config_16(struct rio_mport *port, u32 offset,
+ u16 * data)
+{
+ return __rio_local_read_config_16(port, offset, data);
+}
+
+/**
+ * rio_local_write_config_16 - Write 16 bits to local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Data to be written
+ *
+ * Writes 16 bits of data to the specified offset within the local
+ * device's configuration space.
+ */
+
+static inline int rio_local_write_config_16(struct rio_mport *port, u32 offset,
+ u16 data)
+{
+ return __rio_local_write_config_16(port, offset, data);
+}
+
+/**
+ * rio_local_read_config_8 - Read 8 bits from local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Pointer to read data into
+ *
+ * Reads 8 bits of data from the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_read_config_8(struct rio_mport *port, u32 offset,
+ u8 * data)
+{
+ return __rio_local_read_config_8(port, offset, data);
+}
+
+/**
+ * rio_local_write_config_8 - Write 8 bits to local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Data to be written
+ *
+ * Writes 8 bits of data to the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_write_config_8(struct rio_mport *port, u32 offset,
+ u8 data)
+{
+ return __rio_local_write_config_8(port, offset, data);
+}
+
+/**
+ * rio_read_config_32 - Read 32 bits from configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Pointer to read data into
+ *
+ * Reads 32 bits of data from the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_read_config_32(struct rio_dev *rdev, u32 offset,
+ u32 * data)
+{
+ u8 hopcount = 0xff;
+ u16 destid = rdev->destid;
+
+ if (rdev->rswitch) {
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_read_config_32(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_write_config_32 - Write 32 bits to configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Data to be written
+ *
+ * Writes 32 bits of data to the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_write_config_32(struct rio_dev *rdev, u32 offset,
+ u32 data)
+{
+ u8 hopcount = 0xff;
+ u16 destid = rdev->destid;
+
+ if (rdev->rswitch) {
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_write_config_32(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_read_config_16 - Read 16 bits from configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Pointer to read data into
+ *
+ * Reads 16 bits of data from the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_read_config_16(struct rio_dev *rdev, u32 offset,
+ u16 * data)
+{
+ u8 hopcount = 0xff;
+ u16 destid = rdev->destid;
+
+ if (rdev->rswitch) {
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_read_config_16(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_write_config_16 - Write 16 bits to configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Data to be written
+ *
+ * Writes 16 bits of data to the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_write_config_16(struct rio_dev *rdev, u32 offset,
+ u16 data)
+{
+ u8 hopcount = 0xff;
+ u16 destid = rdev->destid;
+
+ if (rdev->rswitch) {
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_write_config_16(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_read_config_8 - Read 8 bits from configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Pointer to read data into
+ *
+ * Reads 8 bits of data from the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 * data)
+{
+ u8 hopcount = 0xff;
+ u16 destid = rdev->destid;
+
+ if (rdev->rswitch) {
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_read_config_8(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_write_config_8 - Write 8 bits to configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Data to be written
+ *
+ * Writes 8 bits of data to the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_write_config_8(struct rio_dev *rdev, u32 offset, u8 data)
+{
+ u8 hopcount = 0xff;
+ u16 destid = rdev->destid;
+
+ if (rdev->rswitch) {
+ destid = rdev->rswitch->destid;
+ hopcount = rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_write_config_8(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+extern int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid,
+ u16 data);
+
+/**
+ * rio_send_doorbell - Send a doorbell message to a device
+ * @rdev: RIO device
+ * @data: Doorbell message data
+ *
+ * Send a doorbell message to a RIO device. The doorbell message
+ * has a 16-bit info field provided by the @data argument.
+ */
+static inline int rio_send_doorbell(struct rio_dev *rdev, u16 data)
+{
+ return rio_mport_send_doorbell(rdev->net->hport, rdev->destid, data);
+};
+
+/**
+ * rio_init_mbox_res - Initialize a RIO mailbox resource
+ * @res: resource struct
+ * @start: start of mailbox range
+ * @end: end of mailbox range
+ *
+ * This function is used to initialize the fields of a resource
+ * for use as a mailbox resource. It initializes a range of
+ * mailboxes using the start and end arguments.
+ */
+static inline void rio_init_mbox_res(struct resource *res, int start, int end)
+{
+ memset(res, 0, sizeof(struct resource));
+ res->start = start;
+ res->end = end;
+ res->flags = RIO_RESOURCE_MAILBOX;
+}
+
+/**
+ * rio_init_dbell_res - Initialize a RIO doorbell resource
+ * @res: resource struct
+ * @start: start of doorbell range
+ * @end: end of doorbell range
+ *
+ * This function is used to initialize the fields of a resource
+ * for use as a doorbell resource. It initializes a range of
+ * doorbell messages using the start and end arguments.
+ */
+static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end)
+{
+ memset(res, 0, sizeof(struct resource));
+ res->start = start;
+ res->end = end;
+ res->flags = RIO_RESOURCE_DOORBELL;
+}
+
+/**
+ * RIO_DEVICE - macro used to describe a specific RIO device
+ * @vid: the 16 bit RIO vendor ID
+ * @did: the 16 bit RIO device ID
+ *
+ * This macro is used to create a struct rio_device_id that matches a
+ * specific device. The assembly vendor and assembly device fields
+ * will be set to %RIO_ANY_ID.
+ */
+#define RIO_DEVICE(dev,ven) \
+ .did = (dev), .vid = (ven), \
+ .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID
+
+/* Mailbox management */
+extern int rio_request_outb_mbox(struct rio_mport *, void *, int, int,
+ void (*)(struct rio_mport *, void *,int, int));
+extern int rio_release_outb_mbox(struct rio_mport *, int);
+
+/**
+ * rio_add_outb_message - Add RIO message to an outbound mailbox queue
+ * @mport: RIO master port containing the outbound queue
+ * @rdev: RIO device the message is be sent to
+ * @mbox: The outbound mailbox queue
+ * @buffer: Pointer to the message buffer
+ * @len: Length of the message buffer
+ *
+ * Adds a RIO message buffer to an outbound mailbox queue for
+ * transmission. Returns 0 on success.
+ */
+static inline int rio_add_outb_message(struct rio_mport *mport,
+ struct rio_dev *rdev, int mbox,
+ void *buffer, size_t len)
+{
+ return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len);
+}
+
+extern int rio_request_inb_mbox(struct rio_mport *, void *, int, int,
+ void (*)(struct rio_mport *, void *, int, int));
+extern int rio_release_inb_mbox(struct rio_mport *, int);
+
+/**
+ * rio_add_inb_buffer - Add buffer to an inbound mailbox queue
+ * @mport: Master port containing the inbound mailbox
+ * @mbox: The inbound mailbox number
+ * @buffer: Pointer to the message buffer
+ *
+ * Adds a buffer to an inbound mailbox queue for reception. Returns
+ * 0 on success.
+ */
+static inline int rio_add_inb_buffer(struct rio_mport *mport, int mbox,
+ void *buffer)
+{
+ return rio_hw_add_inb_buffer(mport, mbox, buffer);
+}
+
+/**
+ * rio_get_inb_message - Get A RIO message from an inbound mailbox queue
+ * @mport: Master port containing the inbound mailbox
+ * @mbox: The inbound mailbox number
+ * @buffer: Pointer to the message buffer
+ *
+ * Get a RIO message from an inbound mailbox queue. Returns 0 on success.
+ */
+static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox)
+{
+ return rio_hw_get_inb_message(mport, mbox);
+}
+
+/* Doorbell management */
+extern int rio_request_inb_dbell(struct rio_mport *, void *, u16, u16,
+ void (*)(struct rio_mport *, void *, u16, u16, u16));
+extern int rio_release_inb_dbell(struct rio_mport *, u16, u16);
+extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16);
+extern int rio_release_outb_dbell(struct rio_dev *, struct resource *);
+
+/* Memory region management */
+int rio_claim_resource(struct rio_dev *, int);
+int rio_request_regions(struct rio_dev *, char *);
+void rio_release_regions(struct rio_dev *);
+int rio_request_region(struct rio_dev *, int, char *);
+void rio_release_region(struct rio_dev *, int);
+
+/* LDM support */
+int rio_register_driver(struct rio_driver *);
+void rio_unregister_driver(struct rio_driver *);
+struct rio_dev *rio_dev_get(struct rio_dev *);
+void rio_dev_put(struct rio_dev *);
+
+/**
+ * rio_name - Get the unique RIO device identifier
+ * @rdev: RIO device
+ *
+ * Get the unique RIO device identifier. Returns the device
+ * identifier string.
+ */
+static inline char *rio_name(struct rio_dev *rdev)
+{
+ return rdev->dev.bus_id;
+}
+
+/**
+ * rio_get_drvdata - Get RIO driver specific data
+ * @rdev: RIO device
+ *
+ * Get RIO driver specific data. Returns a pointer to the
+ * driver specific data.
+ */
+static inline void *rio_get_drvdata(struct rio_dev *rdev)
+{
+ return dev_get_drvdata(&rdev->dev);
+}
+
+/**
+ * rio_set_drvdata - Set RIO driver specific data
+ * @rdev: RIO device
+ * @data: Pointer to driver specific data
+ *
+ * Set RIO driver specific data. device struct driver data pointer
+ * is set to the @data argument.
+ */
+static inline void rio_set_drvdata(struct rio_dev *rdev, void *data)
+{
+ dev_set_drvdata(&rdev->dev, data);
+}
+
+/* Misc driver helpers */
+extern u16 rio_local_get_device_id(struct rio_mport *port);
+extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from);
+extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did,
+ struct rio_dev *from);
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_RIO_DRV_H */
diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h
new file mode 100644
index 000000000000..919d4e07d54e
--- /dev/null
+++ b/include/linux/rio_ids.h
@@ -0,0 +1,24 @@
+/*
+ * RapidIO devices
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#ifndef LINUX_RIO_IDS_H
+#define LINUX_RIO_IDS_H
+
+#define RIO_ANY_ID 0xffff
+
+#define RIO_VID_FREESCALE 0x0002
+#define RIO_DID_MPC8560 0x0003
+
+#define RIO_VID_TUNDRA 0x000d
+#define RIO_DID_TSI500 0x0500
+
+#endif /* LINUX_RIO_IDS_H */
diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h
new file mode 100644
index 000000000000..326540f9b54e
--- /dev/null
+++ b/include/linux/rio_regs.h
@@ -0,0 +1,215 @@
+/*
+ * RapidIO register definitions
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * 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.
+ */
+
+#ifndef LINUX_RIO_REGS_H
+#define LINUX_RIO_REGS_H
+
+/*
+ * In RapidIO, each device has a 2MB configuration space that is
+ * accessed via maintenance transactions. Portions of configuration
+ * space are standardized and/or reserved.
+ */
+#define RIO_DEV_ID_CAR 0x00 /* [I] Device Identity CAR */
+#define RIO_DEV_INFO_CAR 0x04 /* [I] Device Information CAR */
+#define RIO_ASM_ID_CAR 0x08 /* [I] Assembly Identity CAR */
+#define RIO_ASM_ID_MASK 0xffff0000 /* [I] Asm ID Mask */
+#define RIO_ASM_VEN_ID_MASK 0x0000ffff /* [I] Asm Vend Mask */
+
+#define RIO_ASM_INFO_CAR 0x0c /* [I] Assembly Information CAR */
+#define RIO_ASM_REV_MASK 0xffff0000 /* [I] Asm Rev Mask */
+#define RIO_EXT_FTR_PTR_MASK 0x0000ffff /* [I] EF_PTR Mask */
+
+#define RIO_PEF_CAR 0x10 /* [I] Processing Element Features CAR */
+#define RIO_PEF_BRIDGE 0x80000000 /* [I] Bridge */
+#define RIO_PEF_MEMORY 0x40000000 /* [I] MMIO */
+#define RIO_PEF_PROCESSOR 0x20000000 /* [I] Processor */
+#define RIO_PEF_SWITCH 0x10000000 /* [I] Switch */
+#define RIO_PEF_INB_MBOX 0x00f00000 /* [II] Mailboxes */
+#define RIO_PEF_INB_MBOX0 0x00800000 /* [II] Mailbox 0 */
+#define RIO_PEF_INB_MBOX1 0x00400000 /* [II] Mailbox 1 */
+#define RIO_PEF_INB_MBOX2 0x00200000 /* [II] Mailbox 2 */
+#define RIO_PEF_INB_MBOX3 0x00100000 /* [II] Mailbox 3 */
+#define RIO_PEF_INB_DOORBELL 0x00080000 /* [II] Doorbells */
+#define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */
+#define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */
+#define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */
+#define RIO_PEF_ADDR_50 0x00000002 /* [I] 50 bits */
+#define RIO_PEF_ADDR_34 0x00000001 /* [I] 34 bits */
+
+#define RIO_SWP_INFO_CAR 0x14 /* [I] Switch Port Information CAR */
+#define RIO_SWP_INFO_PORT_TOTAL_MASK 0x0000ff00 /* [I] Total number of ports */
+#define RIO_SWP_INFO_PORT_NUM_MASK 0x000000ff /* [I] Maintenance transaction port number */
+#define RIO_GET_TOTAL_PORTS(x) ((x & RIO_SWP_INFO_PORT_TOTAL_MASK) >> 8)
+
+#define RIO_SRC_OPS_CAR 0x18 /* [I] Source Operations CAR */
+#define RIO_SRC_OPS_READ 0x00008000 /* [I] Read op */
+#define RIO_SRC_OPS_WRITE 0x00004000 /* [I] Write op */
+#define RIO_SRC_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */
+#define RIO_SRC_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */
+#define RIO_SRC_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */
+#define RIO_SRC_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */
+#define RIO_SRC_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */
+#define RIO_SRC_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */
+#define RIO_SRC_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */
+#define RIO_SRC_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */
+#define RIO_SRC_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */
+#define RIO_SRC_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */
+
+#define RIO_DST_OPS_CAR 0x1c /* Destination Operations CAR */
+#define RIO_DST_OPS_READ 0x00008000 /* [I] Read op */
+#define RIO_DST_OPS_WRITE 0x00004000 /* [I] Write op */
+#define RIO_DST_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */
+#define RIO_DST_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */
+#define RIO_DST_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */
+#define RIO_DST_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */
+#define RIO_DST_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */
+#define RIO_DST_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */
+#define RIO_DST_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */
+#define RIO_DST_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */
+#define RIO_DST_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */
+#define RIO_DST_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */
+
+#define RIO_OPS_READ 0x00008000 /* [I] Read op */
+#define RIO_OPS_WRITE 0x00004000 /* [I] Write op */
+#define RIO_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */
+#define RIO_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */
+#define RIO_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */
+#define RIO_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */
+#define RIO_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */
+#define RIO_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */
+#define RIO_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */
+#define RIO_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */
+#define RIO_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */
+#define RIO_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */
+
+ /* 0x20-0x3c *//* Reserved */
+
+#define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */
+#define RIO_MBOX0_AVAIL 0x80000000 /* [II] Mbox 0 avail */
+#define RIO_MBOX0_FULL 0x40000000 /* [II] Mbox 0 full */
+#define RIO_MBOX0_EMPTY 0x20000000 /* [II] Mbox 0 empty */
+#define RIO_MBOX0_BUSY 0x10000000 /* [II] Mbox 0 busy */
+#define RIO_MBOX0_FAIL 0x08000000 /* [II] Mbox 0 fail */
+#define RIO_MBOX0_ERROR 0x04000000 /* [II] Mbox 0 error */
+#define RIO_MBOX1_AVAIL 0x00800000 /* [II] Mbox 1 avail */
+#define RIO_MBOX1_FULL 0x00200000 /* [II] Mbox 1 full */
+#define RIO_MBOX1_EMPTY 0x00200000 /* [II] Mbox 1 empty */
+#define RIO_MBOX1_BUSY 0x00100000 /* [II] Mbox 1 busy */
+#define RIO_MBOX1_FAIL 0x00080000 /* [II] Mbox 1 fail */
+#define RIO_MBOX1_ERROR 0x00040000 /* [II] Mbox 1 error */
+#define RIO_MBOX2_AVAIL 0x00008000 /* [II] Mbox 2 avail */
+#define RIO_MBOX2_FULL 0x00004000 /* [II] Mbox 2 full */
+#define RIO_MBOX2_EMPTY 0x00002000 /* [II] Mbox 2 empty */
+#define RIO_MBOX2_BUSY 0x00001000 /* [II] Mbox 2 busy */
+#define RIO_MBOX2_FAIL 0x00000800 /* [II] Mbox 2 fail */
+#define RIO_MBOX2_ERROR 0x00000400 /* [II] Mbox 2 error */
+#define RIO_MBOX3_AVAIL 0x00000080 /* [II] Mbox 3 avail */
+#define RIO_MBOX3_FULL 0x00000040 /* [II] Mbox 3 full */
+#define RIO_MBOX3_EMPTY 0x00000020 /* [II] Mbox 3 empty */
+#define RIO_MBOX3_BUSY 0x00000010 /* [II] Mbox 3 busy */
+#define RIO_MBOX3_FAIL 0x00000008 /* [II] Mbox 3 fail */
+#define RIO_MBOX3_ERROR 0x00000004 /* [II] Mbox 3 error */
+
+#define RIO_WRITE_PORT_CSR 0x44 /* [I] Write Port CSR */
+#define RIO_DOORBELL_CSR 0x44 /* [II] Doorbell CSR */
+#define RIO_DOORBELL_AVAIL 0x80000000 /* [II] Doorbell avail */
+#define RIO_DOORBELL_FULL 0x40000000 /* [II] Doorbell full */
+#define RIO_DOORBELL_EMPTY 0x20000000 /* [II] Doorbell empty */
+#define RIO_DOORBELL_BUSY 0x10000000 /* [II] Doorbell busy */
+#define RIO_DOORBELL_FAILED 0x08000000 /* [II] Doorbell failed */
+#define RIO_DOORBELL_ERROR 0x04000000 /* [II] Doorbell error */
+#define RIO_WRITE_PORT_AVAILABLE 0x00000080 /* [I] Write Port Available */
+#define RIO_WRITE_PORT_FULL 0x00000040 /* [I] Write Port Full */
+#define RIO_WRITE_PORT_EMPTY 0x00000020 /* [I] Write Port Empty */
+#define RIO_WRITE_PORT_BUSY 0x00000010 /* [I] Write Port Busy */
+#define RIO_WRITE_PORT_FAILED 0x00000008 /* [I] Write Port Failed */
+#define RIO_WRITE_PORT_ERROR 0x00000004 /* [I] Write Port Error */
+
+ /* 0x48 *//* Reserved */
+
+#define RIO_PELL_CTRL_CSR 0x4c /* [I] PE Logical Layer Control CSR */
+#define RIO_PELL_ADDR_66 0x00000004 /* [I] 66-bit addr */
+#define RIO_PELL_ADDR_50 0x00000002 /* [I] 50-bit addr */
+#define RIO_PELL_ADDR_34 0x00000001 /* [I] 34-bit addr */
+
+ /* 0x50-0x54 *//* Reserved */
+
+#define RIO_LCSH_BA 0x58 /* [I] LCS High Base Address */
+#define RIO_LCSL_BA 0x5c /* [I] LCS Base Address */
+
+#define RIO_DID_CSR 0x60 /* [III] Base Device ID CSR */
+
+ /* 0x64 *//* Reserved */
+
+#define RIO_HOST_DID_LOCK_CSR 0x68 /* [III] Host Base Device ID Lock CSR */
+#define RIO_COMPONENT_TAG_CSR 0x6c /* [III] Component Tag CSR */
+
+ /* 0x70-0xf8 *//* Reserved */
+ /* 0x100-0xfff8 *//* [I] Extended Features Space */
+ /* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */
+
+/*
+ * Extended Features Space is a configuration space area where
+ * functionality is mapped into extended feature blocks via a
+ * singly linked list of extended feature pointers (EFT_PTR).
+ *
+ * Each extended feature block can be identified/located in
+ * Extended Features Space by walking the extended feature
+ * list starting with the Extended Feature Pointer located
+ * in the Assembly Information CAR.
+ *
+ * Extended Feature Blocks (EFBs) are identified with an assigned
+ * EFB ID. Extended feature block offsets in the definitions are
+ * relative to the offset of the EFB within the Extended Features
+ * Space.
+ */
+
+/* Helper macros to parse the Extended Feature Block header */
+#define RIO_EFB_PTR_MASK 0xffff0000
+#define RIO_EFB_ID_MASK 0x0000ffff
+#define RIO_GET_BLOCK_PTR(x) ((x & RIO_EFB_PTR_MASK) >> 16)
+#define RIO_GET_BLOCK_ID(x) (x & RIO_EFB_ID_MASK)
+
+/* Extended Feature Block IDs */
+#define RIO_EFB_PAR_EP_ID 0x0001 /* [IV] LP/LVDS EP Devices */
+#define RIO_EFB_PAR_EP_REC_ID 0x0002 /* [IV] LP/LVDS EP Recovery Devices */
+#define RIO_EFB_PAR_EP_FREE_ID 0x0003 /* [IV] LP/LVDS EP Free Devices */
+#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */
+#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */
+#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */
+
+/*
+ * Physical 8/16 LP-LVDS
+ * ID=0x0001, Generic End Point Devices
+ * ID=0x0002, Generic End Point Devices, software assisted recovery option
+ * ID=0x0003, Generic End Point Free Devices
+ *
+ * Physical LP-Serial
+ * ID=0x0004, Generic End Point Devices
+ * ID=0x0005, Generic End Point Devices, software assisted recovery option
+ * ID=0x0006, Generic End Point Free Devices
+ */
+#define RIO_PORT_MNT_HEADER 0x0000
+#define RIO_PORT_REQ_CTL_CSR 0x0020
+#define RIO_PORT_RSP_CTL_CSR 0x0024 /* 0x0001/0x0002 */
+#define RIO_PORT_GEN_CTL_CSR 0x003c
+#define RIO_PORT_GEN_HOST 0x80000000
+#define RIO_PORT_GEN_MASTER 0x40000000
+#define RIO_PORT_GEN_DISCOVERED 0x20000000
+#define RIO_PORT_N_MNT_REQ_CSR(x) (0x0040 + x*0x20) /* 0x0002 */
+#define RIO_PORT_N_MNT_RSP_CSR(x) (0x0044 + x*0x20) /* 0x0002 */
+#define RIO_PORT_N_ACK_STS_CSR(x) (0x0048 + x*0x20) /* 0x0002 */
+#define RIO_PORT_N_ERR_STS_CSR(x) (0x58 + x*0x20)
+#define PORT_N_ERR_STS_PORT_OK 0x00000002
+#define RIO_PORT_N_CTL_CSR(x) (0x5c + x*0x20)
+
+#endif /* LINUX_RIO_REGS_H */
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 106f9757339a..3c1f1120fe88 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -79,6 +79,8 @@ struct seminfo {
#ifdef __KERNEL__
+struct task_struct;
+
/* One semaphore structure for each semaphore in the system. */
struct sem {
int semval; /* current value */
diff --git a/include/linux/shm.h b/include/linux/shm.h
index 80113a1f60bc..a2c896ad0bef 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -92,6 +92,7 @@ struct shmid_kernel /* private to the kernel */
#define SHM_DEST 01000 /* segment will be destroyed on last detach */
#define SHM_LOCKED 02000 /* segment will not be swapped */
#define SHM_HUGETLB 04000 /* segment will use huge TLB pages */
+#define SHM_NORESERVE 010000 /* don't check for reservations */
#ifdef CONFIG_SYSVIPC
long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr);
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 09b9aa60063d..d1ea4051b996 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -9,7 +9,7 @@
#if defined(__KERNEL__)
-typedef struct kmem_cache_s kmem_cache_t;
+typedef struct kmem_cache kmem_cache_t;
#include <linux/config.h> /* kmalloc_sizes.h needs CONFIG_ options */
#include <linux/gfp.h>
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 5af8800e0ce3..e4086ec8b952 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -171,7 +171,8 @@ xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
{
char *cp = (char *)p;
struct kvec *vec = &rqstp->rq_arg.head[0];
- return cp - (char*)vec->iov_base <= vec->iov_len;
+ return cp >= (char*)vec->iov_base
+ && cp <= (char*)vec->iov_base + vec->iov_len;
}
static inline int
diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h
index c906c5a0aaef..17ea468fa362 100644
--- a/include/linux/superhyway.h
+++ b/include/linux/superhyway.h
@@ -19,7 +19,7 @@
*/
#define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183
-struct vcr_info {
+struct superhyway_vcr_info {
u8 perr_flags; /* P-port Error flags */
u8 merr_flags; /* Module Error flags */
u16 mod_vers; /* Module Version */
@@ -28,6 +28,17 @@ struct vcr_info {
u8 top_mb; /* Top Memory block */
};
+struct superhyway_ops {
+ int (*read_vcr)(unsigned long base, struct superhyway_vcr_info *vcr);
+ int (*write_vcr)(unsigned long base, struct superhyway_vcr_info vcr);
+};
+
+struct superhyway_bus {
+ struct superhyway_ops *ops;
+};
+
+extern struct superhyway_bus superhyway_channels[];
+
struct superhyway_device_id {
unsigned int id;
unsigned long driver_data;
@@ -55,9 +66,11 @@ struct superhyway_device {
struct superhyway_device_id id;
struct superhyway_driver *drv;
+ struct superhyway_bus *bus;
- struct resource resource;
- struct vcr_info vcr;
+ int num_resources;
+ struct resource *resource;
+ struct superhyway_vcr_info vcr;
};
#define to_superhyway_device(d) container_of((d), struct superhyway_device, dev)
@@ -65,12 +78,27 @@ struct superhyway_device {
#define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev)
#define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p))
-extern int superhyway_scan_bus(void);
+static inline int
+superhyway_read_vcr(struct superhyway_device *dev, unsigned long base,
+ struct superhyway_vcr_info *vcr)
+{
+ return dev->bus->ops->read_vcr(base, vcr);
+}
+
+static inline int
+superhyway_write_vcr(struct superhyway_device *dev, unsigned long base,
+ struct superhyway_vcr_info vcr)
+{
+ return dev->bus->ops->write_vcr(base, vcr);
+}
+
+extern int superhyway_scan_bus(struct superhyway_bus *);
/* drivers/sh/superhyway/superhyway.c */
int superhyway_register_driver(struct superhyway_driver *);
void superhyway_unregister_driver(struct superhyway_driver *);
-int superhyway_add_device(unsigned int, unsigned long, unsigned long long);
+int superhyway_add_device(unsigned long base, struct superhyway_device *, struct superhyway_bus *);
+int superhyway_add_devices(struct superhyway_bus *bus, struct superhyway_device **devices, int nr_devices);
/* drivers/sh/superhyway/superhyway-sysfs.c */
extern struct device_attribute superhyway_dev_attrs[];
diff --git a/include/linux/wait.h b/include/linux/wait.h
index d38c9fecdc36..d28518236b62 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -54,6 +54,7 @@ struct __wait_queue_head {
};
typedef struct __wait_queue_head wait_queue_head_t;
+struct task_struct;
/*
* Macros for declaration and initialisaton of the datatypes
diff --git a/ipc/shm.c b/ipc/shm.c
index b58c651d31ae..587d836d80d9 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -212,8 +212,16 @@ static int newseg (key_t key, int shmflg, size_t size)
file = hugetlb_zero_setup(size);
shp->mlock_user = current->user;
} else {
+ int acctflag = VM_ACCOUNT;
+ /*
+ * Do not allow no accounting for OVERCOMMIT_NEVER, even
+ * if it's asked for.
+ */
+ if ((shmflg & SHM_NORESERVE) &&
+ sysctl_overcommit_memory != OVERCOMMIT_NEVER)
+ acctflag = 0;
sprintf (name, "SYSV%08x", key);
- file = shmem_file_setup(name, size, VM_ACCOUNT);
+ file = shmem_file_setup(name, size, acctflag);
}
error = PTR_ERR(file);
if (IS_ERR(file))
diff --git a/ipc/util.c b/ipc/util.c
index 10e836d0d89e..23f1cec150c1 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -410,7 +410,8 @@ void ipc_rcu_getref(void *ptr)
}
/**
- * ipc_schedule_free - free ipc + rcu space
+ * ipc_schedule_free - free ipc + rcu space
+ * @head: RCU callback structure for queued work
*
* Since RCU callback function is called in bh,
* we need to defer the vfree to schedule_work
@@ -427,10 +428,10 @@ static void ipc_schedule_free(struct rcu_head *head)
}
/**
- * ipc_immediate_free - free ipc + rcu space
- *
- * Free from the RCU callback context
+ * ipc_immediate_free - free ipc + rcu space
+ * @head: RCU callback structure that contains pointer to be freed
*
+ * Free from the RCU callback context
*/
static void ipc_immediate_free(struct rcu_head *head)
{
diff --git a/kernel/exit.c b/kernel/exit.c
index 537394b25e8d..452a1d116178 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -28,6 +28,7 @@
#include <linux/cpuset.h>
#include <linux/syscalls.h>
#include <linux/signal.h>
+#include <linux/cn_proc.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -863,6 +864,7 @@ fastcall NORET_TYPE void do_exit(long code)
module_put(tsk->binfmt->module);
tsk->exit_code = code;
+ proc_exit_connector(tsk);
exit_notify(tsk);
#ifdef CONFIG_NUMA
mpol_free(tsk->mempolicy);
diff --git a/kernel/fork.c b/kernel/fork.c
index 8a069612eac3..efac2c58ec7d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -42,6 +42,7 @@
#include <linux/profile.h>
#include <linux/rmap.h>
#include <linux/acct.h>
+#include <linux/cn_proc.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -1143,6 +1144,7 @@ static task_t *copy_process(unsigned long clone_flags,
__get_cpu_var(process_counts)++;
}
+ proc_fork_connector(p);
if (!current->signal->tty && p->signal->tty)
p->signal->tty = NULL;
diff --git a/kernel/futex.c b/kernel/futex.c
index 3b4d5ad44cc6..aca8d10704f6 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -365,6 +365,11 @@ retry:
if (bh1 != bh2)
spin_unlock(&bh2->lock);
+ if (unlikely(op_ret != -EFAULT)) {
+ ret = op_ret;
+ goto out;
+ }
+
/* futex_atomic_op_inuser needs to both read and write
* *(int __user *)uaddr2, but we can't modify it
* non-atomically. Therefore, if get_user below is not
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 1cfdb08ddf20..3bd7226d15fa 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -24,6 +24,7 @@ cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
/**
* synchronize_irq - wait for pending IRQ handlers (on other CPUs)
+ * @irq: interrupt number to wait for
*
* This function waits for any pending IRQ handlers for this interrupt
* to complete before returning. If you use this function while
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index ce4915dd683a..5beda378cc75 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -32,7 +32,6 @@
* <prasanna@in.ibm.com> added function-return probes.
*/
#include <linux/kprobes.h>
-#include <linux/spinlock.h>
#include <linux/hash.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -49,9 +48,9 @@
static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
-unsigned int kprobe_cpu = NR_CPUS;
-static DEFINE_SPINLOCK(kprobe_lock);
-static struct kprobe *curr_kprobe;
+static DEFINE_SPINLOCK(kprobe_lock); /* Protects kprobe_table */
+DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
+static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
/*
* kprobe->ainsn.insn points to the copy of the instruction to be
@@ -153,50 +152,31 @@ void __kprobes free_insn_slot(kprobe_opcode_t *slot)
}
}
-/* Locks kprobe: irqs must be disabled */
-void __kprobes lock_kprobes(void)
+/* We have preemption disabled.. so it is safe to use __ versions */
+static inline void set_kprobe_instance(struct kprobe *kp)
{
- unsigned long flags = 0;
-
- /* Avoiding local interrupts to happen right after we take the kprobe_lock
- * and before we get a chance to update kprobe_cpu, this to prevent
- * deadlock when we have a kprobe on ISR routine and a kprobe on task
- * routine
- */
- local_irq_save(flags);
-
- spin_lock(&kprobe_lock);
- kprobe_cpu = smp_processor_id();
-
- local_irq_restore(flags);
+ __get_cpu_var(kprobe_instance) = kp;
}
-void __kprobes unlock_kprobes(void)
+static inline void reset_kprobe_instance(void)
{
- unsigned long flags = 0;
-
- /* Avoiding local interrupts to happen right after we update
- * kprobe_cpu and before we get a a chance to release kprobe_lock,
- * this to prevent deadlock when we have a kprobe on ISR routine and
- * a kprobe on task routine
- */
- local_irq_save(flags);
-
- kprobe_cpu = NR_CPUS;
- spin_unlock(&kprobe_lock);
-
- local_irq_restore(flags);
+ __get_cpu_var(kprobe_instance) = NULL;
}
-/* You have to be holding the kprobe_lock */
+/*
+ * This routine is called either:
+ * - under the kprobe_lock spinlock - during kprobe_[un]register()
+ * OR
+ * - with preemption disabled - from arch/xxx/kernel/kprobes.c
+ */
struct kprobe __kprobes *get_kprobe(void *addr)
{
struct hlist_head *head;
struct hlist_node *node;
+ struct kprobe *p;
head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)];
- hlist_for_each(node, head) {
- struct kprobe *p = hlist_entry(node, struct kprobe, hlist);
+ hlist_for_each_entry_rcu(p, node, head, hlist) {
if (p->addr == addr)
return p;
}
@@ -211,13 +191,13 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp;
- list_for_each_entry(kp, &p->list, list) {
+ list_for_each_entry_rcu(kp, &p->list, list) {
if (kp->pre_handler) {
- curr_kprobe = kp;
+ set_kprobe_instance(kp);
if (kp->pre_handler(kp, regs))
return 1;
}
- curr_kprobe = NULL;
+ reset_kprobe_instance();
}
return 0;
}
@@ -227,11 +207,11 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
{
struct kprobe *kp;
- list_for_each_entry(kp, &p->list, list) {
+ list_for_each_entry_rcu(kp, &p->list, list) {
if (kp->post_handler) {
- curr_kprobe = kp;
+ set_kprobe_instance(kp);
kp->post_handler(kp, regs, flags);
- curr_kprobe = NULL;
+ reset_kprobe_instance();
}
}
return;
@@ -240,12 +220,14 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
int trapnr)
{
+ struct kprobe *cur = __get_cpu_var(kprobe_instance);
+
/*
* if we faulted "during" the execution of a user specified
* probe handler, invoke just that probe's fault handler
*/
- if (curr_kprobe && curr_kprobe->fault_handler) {
- if (curr_kprobe->fault_handler(curr_kprobe, regs, trapnr))
+ if (cur && cur->fault_handler) {
+ if (cur->fault_handler(cur, regs, trapnr))
return 1;
}
return 0;
@@ -253,17 +235,18 @@ static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
{
- struct kprobe *kp = curr_kprobe;
- if (curr_kprobe && kp->break_handler) {
- if (kp->break_handler(kp, regs)) {
- curr_kprobe = NULL;
- return 1;
- }
+ struct kprobe *cur = __get_cpu_var(kprobe_instance);
+ int ret = 0;
+
+ if (cur && cur->break_handler) {
+ if (cur->break_handler(cur, regs))
+ ret = 1;
}
- curr_kprobe = NULL;
- return 0;
+ reset_kprobe_instance();
+ return ret;
}
+/* Called with kretprobe_lock held */
struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)
{
struct hlist_node *node;
@@ -273,6 +256,7 @@ struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp)
return NULL;
}
+/* Called with kretprobe_lock held */
static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe
*rp)
{
@@ -283,6 +267,7 @@ static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe
return NULL;
}
+/* Called with kretprobe_lock held */
void __kprobes add_rp_inst(struct kretprobe_instance *ri)
{
/*
@@ -301,6 +286,7 @@ void __kprobes add_rp_inst(struct kretprobe_instance *ri)
hlist_add_head(&ri->uflist, &ri->rp->used_instances);
}
+/* Called with kretprobe_lock held */
void __kprobes recycle_rp_inst(struct kretprobe_instance *ri)
{
/* remove rp inst off the rprobe_inst_table */
@@ -334,13 +320,13 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
struct hlist_node *node, *tmp;
unsigned long flags = 0;
- spin_lock_irqsave(&kprobe_lock, flags);
+ spin_lock_irqsave(&kretprobe_lock, flags);
head = kretprobe_inst_table_head(current);
hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
if (ri->task == tk)
recycle_rp_inst(ri);
}
- spin_unlock_irqrestore(&kprobe_lock, flags);
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
}
/*
@@ -351,9 +337,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
struct pt_regs *regs)
{
struct kretprobe *rp = container_of(p, struct kretprobe, kp);
+ unsigned long flags = 0;
/*TODO: consider to only swap the RA after the last pre_handler fired */
+ spin_lock_irqsave(&kretprobe_lock, flags);
arch_prepare_kretprobe(rp, regs);
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
return 0;
}
@@ -384,13 +373,13 @@ static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
struct kprobe *kp;
if (p->break_handler) {
- list_for_each_entry(kp, &old_p->list, list) {
+ list_for_each_entry_rcu(kp, &old_p->list, list) {
if (kp->break_handler)
return -EEXIST;
}
- list_add_tail(&p->list, &old_p->list);
+ list_add_tail_rcu(&p->list, &old_p->list);
} else
- list_add(&p->list, &old_p->list);
+ list_add_rcu(&p->list, &old_p->list);
return 0;
}
@@ -408,18 +397,18 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
ap->break_handler = aggr_break_handler;
INIT_LIST_HEAD(&ap->list);
- list_add(&p->list, &ap->list);
+ list_add_rcu(&p->list, &ap->list);
INIT_HLIST_NODE(&ap->hlist);
- hlist_del(&p->hlist);
- hlist_add_head(&ap->hlist,
+ hlist_del_rcu(&p->hlist);
+ hlist_add_head_rcu(&ap->hlist,
&kprobe_table[hash_ptr(ap->addr, KPROBE_HASH_BITS)]);
}
/*
* This is the second or subsequent kprobe at the address - handle
* the intricacies
- * TODO: Move kcalloc outside the spinlock
+ * TODO: Move kcalloc outside the spin_lock
*/
static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
struct kprobe *p)
@@ -445,7 +434,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p,
static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags)
{
arch_disarm_kprobe(p);
- hlist_del(&p->hlist);
+ hlist_del_rcu(&p->hlist);
spin_unlock_irqrestore(&kprobe_lock, flags);
arch_remove_kprobe(p);
}
@@ -453,11 +442,10 @@ static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags)
static inline void cleanup_aggr_kprobe(struct kprobe *old_p,
struct kprobe *p, unsigned long flags)
{
- list_del(&p->list);
- if (list_empty(&old_p->list)) {
+ list_del_rcu(&p->list);
+ if (list_empty(&old_p->list))
cleanup_kprobe(old_p, flags);
- kfree(old_p);
- } else
+ else
spin_unlock_irqrestore(&kprobe_lock, flags);
}
@@ -480,9 +468,9 @@ int __kprobes register_kprobe(struct kprobe *p)
if ((ret = arch_prepare_kprobe(p)) != 0)
goto rm_kprobe;
+ p->nmissed = 0;
spin_lock_irqsave(&kprobe_lock, flags);
old_p = get_kprobe(p->addr);
- p->nmissed = 0;
if (old_p) {
ret = register_aggr_kprobe(old_p, p);
goto out;
@@ -490,7 +478,7 @@ int __kprobes register_kprobe(struct kprobe *p)
arch_copy_kprobe(p);
INIT_HLIST_NODE(&p->hlist);
- hlist_add_head(&p->hlist,
+ hlist_add_head_rcu(&p->hlist,
&kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
arch_arm_kprobe(p);
@@ -511,10 +499,16 @@ void __kprobes unregister_kprobe(struct kprobe *p)
spin_lock_irqsave(&kprobe_lock, flags);
old_p = get_kprobe(p->addr);
if (old_p) {
+ /* cleanup_*_kprobe() does the spin_unlock_irqrestore */
if (old_p->pre_handler == aggr_pre_handler)
cleanup_aggr_kprobe(old_p, p, flags);
else
cleanup_kprobe(p, flags);
+
+ synchronize_sched();
+ if (old_p->pre_handler == aggr_pre_handler &&
+ list_empty(&old_p->list))
+ kfree(old_p);
} else
spin_unlock_irqrestore(&kprobe_lock, flags);
}
@@ -591,13 +585,13 @@ void __kprobes unregister_kretprobe(struct kretprobe *rp)
unregister_kprobe(&rp->kp);
/* No race here */
- spin_lock_irqsave(&kprobe_lock, flags);
+ spin_lock_irqsave(&kretprobe_lock, flags);
free_rp_inst(rp);
while ((ri = get_used_rp_inst(rp)) != NULL) {
ri->rp = NULL;
hlist_del(&ri->uflist);
}
- spin_unlock_irqrestore(&kprobe_lock, flags);
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
}
static int __init init_kprobes(void)
diff --git a/kernel/module.c b/kernel/module.c
index ff5c500ab625..2ea929d51ad0 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -37,6 +37,7 @@
#include <linux/stop_machine.h>
#include <linux/device.h>
#include <linux/string.h>
+#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 91a894264941..84af54c39e1b 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -497,7 +497,7 @@ static void process_timer_rebalance(struct task_struct *p,
left = cputime_div(cputime_sub(expires.cpu, val.cpu),
nthreads);
do {
- if (!unlikely(t->flags & PF_EXITING)) {
+ if (likely(!(t->flags & PF_EXITING))) {
ticks = cputime_add(prof_ticks(t), left);
if (cputime_eq(t->it_prof_expires,
cputime_zero) ||
@@ -512,7 +512,7 @@ static void process_timer_rebalance(struct task_struct *p,
left = cputime_div(cputime_sub(expires.cpu, val.cpu),
nthreads);
do {
- if (!unlikely(t->flags & PF_EXITING)) {
+ if (likely(!(t->flags & PF_EXITING))) {
ticks = cputime_add(virt_ticks(t), left);
if (cputime_eq(t->it_virt_expires,
cputime_zero) ||
@@ -527,7 +527,7 @@ static void process_timer_rebalance(struct task_struct *p,
nsleft = expires.sched - val.sched;
do_div(nsleft, nthreads);
do {
- if (!unlikely(t->flags & PF_EXITING)) {
+ if (likely(!(t->flags & PF_EXITING))) {
ns = t->sched_time + nsleft;
if (t->it_sched_expires == 0 ||
t->it_sched_expires > ns) {
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 42a628704398..723f5179883e 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -168,9 +168,8 @@ static unsigned count_data_pages(void)
{
struct zone *zone;
unsigned long zone_pfn;
- unsigned n;
+ unsigned int n = 0;
- n = 0;
for_each_zone (zone) {
if (is_highmem(zone))
continue;
@@ -250,10 +249,10 @@ static inline void fill_pb_page(struct pbe *pbpage)
* of memory pages allocated with alloc_pagedir()
*/
-void create_pbe_list(struct pbe *pblist, unsigned nr_pages)
+void create_pbe_list(struct pbe *pblist, unsigned int nr_pages)
{
struct pbe *pbpage, *p;
- unsigned num = PBES_PER_PAGE;
+ unsigned int num = PBES_PER_PAGE;
for_each_pb_page (pbpage, pblist) {
if (num >= nr_pages)
@@ -293,9 +292,9 @@ static void *alloc_image_page(void)
* On each page we set up a list of struct_pbe elements.
*/
-struct pbe *alloc_pagedir(unsigned nr_pages)
+struct pbe *alloc_pagedir(unsigned int nr_pages)
{
- unsigned num;
+ unsigned int num;
struct pbe *pblist, *pbe;
if (!nr_pages)
@@ -329,7 +328,7 @@ void swsusp_free(void)
for_each_zone(zone) {
for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
if (pfn_valid(zone_pfn + zone->zone_start_pfn)) {
- struct page * page;
+ struct page *page;
page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
if (PageNosave(page) && PageNosaveFree(page)) {
ClearPageNosave(page);
@@ -348,7 +347,7 @@ void swsusp_free(void)
* free pages.
*/
-static int enough_free_mem(unsigned nr_pages)
+static int enough_free_mem(unsigned int nr_pages)
{
pr_debug("swsusp: available memory: %u pages\n", nr_free_pages());
return nr_free_pages() > (nr_pages + PAGES_FOR_IO +
@@ -356,7 +355,7 @@ static int enough_free_mem(unsigned nr_pages)
}
-static struct pbe *swsusp_alloc(unsigned nr_pages)
+static struct pbe *swsusp_alloc(unsigned int nr_pages)
{
struct pbe *pblist, *p;
@@ -380,7 +379,7 @@ static struct pbe *swsusp_alloc(unsigned nr_pages)
asmlinkage int swsusp_save(void)
{
- unsigned nr_pages;
+ unsigned int nr_pages;
pr_debug("swsusp: critical section: \n");
if (save_highmem()) {
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 12db1d2ad61f..e1ab28b9b217 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -85,18 +85,11 @@ unsigned int nr_copy_pages __nosavedata = 0;
/* Suspend pagedir is allocated before final copy, therefore it
must be freed after resume
- Warning: this is evil. There are actually two pagedirs at time of
- resume. One is "pagedir_save", which is empty frame allocated at
- time of suspend, that must be freed. Second is "pagedir_nosave",
- allocated at time of resume, that travels through memory not to
- collide with anything.
-
Warning: this is even more evil than it seems. Pagedirs this file
talks about are completely different from page directories used by
MMU hardware.
*/
suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
-suspend_pagedir_t *pagedir_save;
#define SWSUSP_SIG "S1SUSPEND"
@@ -122,8 +115,8 @@ static struct swsusp_info swsusp_info;
static unsigned short swapfile_used[MAX_SWAPFILES];
static unsigned short root_swap;
-static int write_page(unsigned long addr, swp_entry_t * loc);
-static int bio_read_page(pgoff_t page_off, void * page);
+static int write_page(unsigned long addr, swp_entry_t *loc);
+static int bio_read_page(pgoff_t page_off, void *page);
static u8 key_iv[MAXKEY+MAXIV];
@@ -355,7 +348,7 @@ static void lock_swapdevices(void)
* This is a partial improvement, since we will at least return other
* errors, though we need to eventually fix the damn code.
*/
-static int write_page(unsigned long addr, swp_entry_t * loc)
+static int write_page(unsigned long addr, swp_entry_t *loc)
{
swp_entry_t entry;
int error = 0;
@@ -383,9 +376,9 @@ static int write_page(unsigned long addr, swp_entry_t * loc)
static void data_free(void)
{
swp_entry_t entry;
- struct pbe * p;
+ struct pbe *p;
- for_each_pbe(p, pagedir_nosave) {
+ for_each_pbe (p, pagedir_nosave) {
entry = p->swap_address;
if (entry.val)
swap_free(entry);
@@ -492,8 +485,8 @@ static void free_pagedir_entries(void)
static int write_pagedir(void)
{
int error = 0;
- unsigned n = 0;
- struct pbe * pbe;
+ unsigned int n = 0;
+ struct pbe *pbe;
printk( "Writing pagedir...");
for_each_pb_page (pbe, pagedir_nosave) {
@@ -543,7 +536,7 @@ static int write_suspend_image(void)
* We should only consider resume_device.
*/
-int enough_swap(unsigned nr_pages)
+int enough_swap(unsigned int nr_pages)
{
struct sysinfo i;
@@ -694,7 +687,7 @@ static int check_pagedir(struct pbe *pblist)
* restore from the loaded pages later. We relocate them here.
*/
-static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
+static struct pbe *swsusp_pagedir_relocate(struct pbe *pblist)
{
struct zone *zone;
unsigned long zone_pfn;
@@ -770,7 +763,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
static atomic_t io_done = ATOMIC_INIT(0);
-static int end_io(struct bio * bio, unsigned int num, int err)
+static int end_io(struct bio *bio, unsigned int num, int err)
{
if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
panic("I/O error reading memory image");
@@ -778,7 +771,7 @@ static int end_io(struct bio * bio, unsigned int num, int err)
return 0;
}
-static struct block_device * resume_bdev;
+static struct block_device *resume_bdev;
/**
* submit - submit BIO request.
@@ -791,10 +784,10 @@ static struct block_device * resume_bdev;
* Then submit it and wait.
*/
-static int submit(int rw, pgoff_t page_off, void * page)
+static int submit(int rw, pgoff_t page_off, void *page)
{
int error = 0;
- struct bio * bio;
+ struct bio *bio;
bio = bio_alloc(GFP_ATOMIC, 1);
if (!bio)
@@ -823,12 +816,12 @@ static int submit(int rw, pgoff_t page_off, void * page)
return error;
}
-static int bio_read_page(pgoff_t page_off, void * page)
+static int bio_read_page(pgoff_t page_off, void *page)
{
return submit(READ, page_off, page);
}
-static int bio_write_page(pgoff_t page_off, void * page)
+static int bio_write_page(pgoff_t page_off, void *page)
{
return submit(WRITE, page_off, page);
}
@@ -838,7 +831,7 @@ static int bio_write_page(pgoff_t page_off, void * page)
* I really don't think that it's foolproof but more than nothing..
*/
-static const char * sanity_check(void)
+static const char *sanity_check(void)
{
dump_info();
if (swsusp_info.version_code != LINUX_VERSION_CODE)
@@ -864,7 +857,7 @@ static const char * sanity_check(void)
static int check_header(void)
{
- const char * reason = NULL;
+ const char *reason = NULL;
int error;
if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info)))
@@ -912,7 +905,7 @@ static int check_sig(void)
static int data_read(struct pbe *pblist)
{
- struct pbe * p;
+ struct pbe *p;
int error = 0;
int i = 0;
int mod = swsusp_info.image_pages / 100;
@@ -950,7 +943,7 @@ static int data_read(struct pbe *pblist)
static int read_pagedir(struct pbe *pblist)
{
struct pbe *pbpage, *p;
- unsigned i = 0;
+ unsigned int i = 0;
int error;
if (!pblist)
diff --git a/kernel/printk.c b/kernel/printk.c
index 3cb9708209bc..e9be027bc930 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -806,7 +806,6 @@ void console_unblank(void)
c->unblank();
release_console_sem();
}
-EXPORT_SYMBOL(console_unblank);
/*
* Return the console tty driver structure and its associated index
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 863eee8bff47..5b8dd98a230e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -406,3 +406,85 @@ int ptrace_request(struct task_struct *child, long request,
return ret;
}
+
+#ifndef __ARCH_SYS_PTRACE
+static int ptrace_get_task_struct(long request, long pid,
+ struct task_struct **childp)
+{
+ struct task_struct *child;
+ int ret;
+
+ /*
+ * Callers use child == NULL as an indication to exit early even
+ * when the return value is 0, so make sure it is non-NULL here.
+ */
+ *childp = NULL;
+
+ if (request == PTRACE_TRACEME) {
+ /*
+ * Are we already being traced?
+ */
+ if (current->ptrace & PT_PTRACED)
+ return -EPERM;
+ ret = security_ptrace(current->parent, current);
+ if (ret)
+ return -EPERM;
+ /*
+ * Set the ptrace bit in the process ptrace flags.
+ */
+ current->ptrace |= PT_PTRACED;
+ return 0;
+ }
+
+ /*
+ * You may not mess with init
+ */
+ if (pid == 1)
+ return -EPERM;
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ return -ESRCH;
+
+ *childp = child;
+ return 0;
+}
+
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ long ret;
+
+ /*
+ * This lock_kernel fixes a subtle race with suid exec
+ */
+ lock_kernel();
+ ret = ptrace_get_task_struct(request, pid, &child);
+ if (!child)
+ goto out;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out;
+ }
+
+ ret = ptrace_check_attach(child, request == PTRACE_KILL);
+ if (ret < 0)
+ goto out_put_task_struct;
+
+ ret = arch_ptrace(child, request, addr, data);
+ if (ret < 0)
+ goto out_put_task_struct;
+
+ out_put_task_struct:
+ put_task_struct(child);
+ out:
+ unlock_kernel();
+ return ret;
+}
+#endif /* __ARCH_SYS_PTRACE */
diff --git a/kernel/sched.c b/kernel/sched.c
index b4f4eb613537..3ce26954be12 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3563,8 +3563,6 @@ int idle_cpu(int cpu)
return cpu_curr(cpu) == cpu_rq(cpu)->idle;
}
-EXPORT_SYMBOL_GPL(idle_cpu);
-
/**
* idle_task - return the idle task for a given cpu.
* @cpu: the processor in question.
@@ -4680,7 +4678,8 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
#ifdef CONFIG_HOTPLUG_CPU
case CPU_UP_CANCELED:
/* Unbind it from offline cpu so it can run. Fall thru. */
- kthread_bind(cpu_rq(cpu)->migration_thread,smp_processor_id());
+ kthread_bind(cpu_rq(cpu)->migration_thread,
+ any_online_cpu(cpu_online_map));
kthread_stop(cpu_rq(cpu)->migration_thread);
cpu_rq(cpu)->migration_thread = NULL;
break;
diff --git a/kernel/softirq.c b/kernel/softirq.c
index f766b2fc48be..ad3295cdded5 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -470,7 +470,8 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
#ifdef CONFIG_HOTPLUG_CPU
case CPU_UP_CANCELED:
/* Unbind so it can run. Fall thru. */
- kthread_bind(per_cpu(ksoftirqd, hotcpu), smp_processor_id());
+ kthread_bind(per_cpu(ksoftirqd, hotcpu),
+ any_online_cpu(cpu_online_map));
case CPU_DEAD:
p = per_cpu(ksoftirqd, hotcpu);
per_cpu(ksoftirqd, hotcpu) = NULL;
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 75976209cea7..a2dcceb9437d 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -123,7 +123,8 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
#ifdef CONFIG_HOTPLUG_CPU
case CPU_UP_CANCELED:
/* Unbind so it can run. Fall thru. */
- kthread_bind(per_cpu(watchdog_task, hotcpu), smp_processor_id());
+ kthread_bind(per_cpu(watchdog_task, hotcpu),
+ any_online_cpu(cpu_online_map));
case CPU_DEAD:
p = per_cpu(watchdog_task, hotcpu);
per_cpu(watchdog_task, hotcpu) = NULL;
diff --git a/kernel/sys.c b/kernel/sys.c
index 2fa1ed18123c..c43b3e22bbda 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -28,6 +28,7 @@
#include <linux/suspend.h>
#include <linux/tty.h>
#include <linux/signal.h>
+#include <linux/cn_proc.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
@@ -375,18 +376,21 @@ void emergency_restart(void)
}
EXPORT_SYMBOL_GPL(emergency_restart);
-/**
- * kernel_restart - reboot the system
- *
- * Shutdown everything and perform a clean reboot.
- * This is not safe to call in interrupt context.
- */
void kernel_restart_prepare(char *cmd)
{
notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
system_state = SYSTEM_RESTART;
device_shutdown();
}
+
+/**
+ * kernel_restart - reboot the system
+ * @cmd: pointer to buffer containing command to execute for restart
+ * or %NULL
+ *
+ * Shutdown everything and perform a clean reboot.
+ * This is not safe to call in interrupt context.
+ */
void kernel_restart(char *cmd)
{
kernel_restart_prepare(cmd);
@@ -623,6 +627,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
current->egid = new_egid;
current->gid = new_rgid;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
return 0;
}
@@ -662,6 +667,7 @@ asmlinkage long sys_setgid(gid_t gid)
return -EPERM;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
return 0;
}
@@ -751,6 +757,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
current->fsuid = current->euid;
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
}
@@ -798,6 +805,7 @@ asmlinkage long sys_setuid(uid_t uid)
current->suid = new_suid;
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
@@ -846,6 +854,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
current->suid = suid;
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}
@@ -898,6 +907,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
current->sgid = sgid;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
return 0;
}
@@ -940,6 +950,7 @@ asmlinkage long sys_setfsuid(uid_t uid)
}
key_fsuid_changed(current);
+ proc_id_connector(current, PROC_EVENT_UID);
security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
@@ -968,6 +979,7 @@ asmlinkage long sys_setfsgid(gid_t gid)
}
current->fsgid = gid;
key_fsgid_changed(current);
+ proc_id_connector(current, PROC_EVENT_GID);
}
return old_fsgid;
}
@@ -1485,8 +1497,6 @@ EXPORT_SYMBOL(in_egroup_p);
DECLARE_RWSEM(uts_sem);
-EXPORT_SYMBOL(uts_sem);
-
asmlinkage long sys_newuname(struct new_utsname __user * name)
{
int errno = 0;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8e56e2495542..c4f35f96884d 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -952,7 +952,7 @@ static ctl_table fs_table[] = {
.data = &aio_nr,
.maxlen = sizeof(aio_nr),
.mode = 0444,
- .proc_handler = &proc_dointvec,
+ .proc_handler = &proc_doulongvec_minmax,
},
{
.ctl_name = FS_AIO_MAX_NR,
@@ -960,7 +960,7 @@ static ctl_table fs_table[] = {
.data = &aio_max_nr,
.maxlen = sizeof(aio_max_nr),
.mode = 0644,
- .proc_handler = &proc_dointvec,
+ .proc_handler = &proc_doulongvec_minmax,
},
#ifdef CONFIG_INOTIFY
{
@@ -1997,6 +1997,7 @@ int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
* @filp: the file structure
* @buffer: the user buffer
* @lenp: the size of the user buffer
+ * @ppos: pointer to the file position
*
* Reads/writes up to table->maxlen/sizeof(unsigned int) integer
* values from/to the user buffer, treated as an ASCII string.
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 7cee222231bc..42df83d7fad2 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -524,7 +524,7 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
list_for_each_entry(wq, &workqueues, list) {
/* Unbind so it can run. */
kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread,
- smp_processor_id());
+ any_online_cpu(cpu_online_map));
cleanup_workqueue_thread(wq, hotcpu);
}
break;
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index d1c057e71b68..88511c3805ad 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -281,35 +281,60 @@ int radix_tree_insert(struct radix_tree_root *root,
}
EXPORT_SYMBOL(radix_tree_insert);
-/**
- * radix_tree_lookup - perform lookup operation on a radix tree
- * @root: radix tree root
- * @index: index key
- *
- * Lookup the item at the position @index in the radix tree @root.
- */
-void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
+static inline void **__lookup_slot(struct radix_tree_root *root,
+ unsigned long index)
{
unsigned int height, shift;
- struct radix_tree_node *slot;
+ struct radix_tree_node **slot;
height = root->height;
if (index > radix_tree_maxindex(height))
return NULL;
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
- slot = root->rnode;
+ slot = &root->rnode;
while (height > 0) {
- if (slot == NULL)
+ if (*slot == NULL)
return NULL;
- slot = slot->slots[(index >> shift) & RADIX_TREE_MAP_MASK];
+ slot = (struct radix_tree_node **)
+ ((*slot)->slots +
+ ((index >> shift) & RADIX_TREE_MAP_MASK));
shift -= RADIX_TREE_MAP_SHIFT;
height--;
}
- return slot;
+ return (void **)slot;
+}
+
+/**
+ * radix_tree_lookup_slot - lookup a slot in a radix tree
+ * @root: radix tree root
+ * @index: index key
+ *
+ * Lookup the slot corresponding to the position @index in the radix tree
+ * @root. This is useful for update-if-exists operations.
+ */
+void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index)
+{
+ return __lookup_slot(root, index);
+}
+EXPORT_SYMBOL(radix_tree_lookup_slot);
+
+/**
+ * radix_tree_lookup - perform lookup operation on a radix tree
+ * @root: radix tree root
+ * @index: index key
+ *
+ * Lookup the item at the position @index in the radix tree @root.
+ */
+void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
+{
+ void **slot;
+
+ slot = __lookup_slot(root, index);
+ return slot != NULL ? *slot : NULL;
}
EXPORT_SYMBOL(radix_tree_lookup);
diff --git a/mm/Kconfig b/mm/Kconfig
index 1a4473fcb2ca..ae9ce6b73e8a 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -126,9 +126,11 @@ comment "Memory hotplug is currently incompatible with Software Suspend"
# Default to 4 for wider testing, though 8 might be more appropriate.
# ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock.
# PA-RISC's debug spinlock_t is too large for the 32-bit struct page.
+# ARM26 and SPARC32 and PPC64 may use one page for multiple page tables.
#
config SPLIT_PTLOCK_CPUS
int
default "4096" if ARM && !CPU_CACHE_VIPT
default "4096" if PARISC && DEBUG_SPINLOCK && !64BIT
+ default "4096" if ARM26 || SPARC32 || PPC64
default "4"
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 9a565808da3f..728e9bda12ea 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -237,7 +237,6 @@ unsigned long hugetlb_total_pages(void)
{
return nr_huge_pages * (HPAGE_SIZE / PAGE_SIZE);
}
-EXPORT_SYMBOL(hugetlb_total_pages);
/*
* We cannot handle pagefaults against hugetlb pages at all. They cause
diff --git a/mm/mmap.c b/mm/mmap.c
index 320dda1778c3..6c997b159600 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -155,10 +155,6 @@ int __vm_enough_memory(long pages, int cap_sys_admin)
return -ENOMEM;
}
-EXPORT_SYMBOL(sysctl_overcommit_memory);
-EXPORT_SYMBOL(sysctl_overcommit_ratio);
-EXPORT_SYMBOL(sysctl_max_map_count);
-EXPORT_SYMBOL(vm_committed_space);
EXPORT_SYMBOL(__vm_enough_memory);
/*
diff --git a/mm/nommu.c b/mm/nommu.c
index d1e076a487cb..6deb6ab3d6ad 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -44,10 +44,6 @@ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
int heap_stack_gap = 0;
EXPORT_SYMBOL(mem_map);
-EXPORT_SYMBOL(sysctl_max_map_count);
-EXPORT_SYMBOL(sysctl_overcommit_memory);
-EXPORT_SYMBOL(sysctl_overcommit_ratio);
-EXPORT_SYMBOL(vm_committed_space);
EXPORT_SYMBOL(__vm_enough_memory);
/* list of shareable VMAs */
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 0166ea15c9ee..74138c9a22b9 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -750,7 +750,6 @@ int clear_page_dirty_for_io(struct page *page)
}
return TestClearPageDirty(page);
}
-EXPORT_SYMBOL(clear_page_dirty_for_io);
int test_clear_page_writeback(struct page *page)
{
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2dbdd98426fd..ff81b5c65511 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -64,7 +64,6 @@ long nr_swap_pages;
int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = { 256, 32 };
EXPORT_SYMBOL(totalram_pages);
-EXPORT_SYMBOL(nr_swap_pages);
/*
* Used by page_zone() to look up the address of the struct zone whose
diff --git a/mm/readahead.c b/mm/readahead.c
index d0b50034e245..72e7adbb87c7 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -254,7 +254,7 @@ out:
*/
static int
__do_page_cache_readahead(struct address_space *mapping, struct file *filp,
- unsigned long offset, unsigned long nr_to_read)
+ pgoff_t offset, unsigned long nr_to_read)
{
struct inode *inode = mapping->host;
struct page *page;
@@ -274,7 +274,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp,
*/
read_lock_irq(&mapping->tree_lock);
for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
- unsigned long page_offset = offset + page_idx;
+ pgoff_t page_offset = offset + page_idx;
if (page_offset > end_index)
break;
@@ -311,7 +311,7 @@ out:
* memory at once.
*/
int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
- unsigned long offset, unsigned long nr_to_read)
+ pgoff_t offset, unsigned long nr_to_read)
{
int ret = 0;
@@ -368,7 +368,7 @@ static inline int check_ra_success(struct file_ra_state *ra,
* request queues.
*/
int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
- unsigned long offset, unsigned long nr_to_read)
+ pgoff_t offset, unsigned long nr_to_read)
{
if (bdi_read_congested(mapping->backing_dev_info))
return -1;
@@ -385,7 +385,7 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
*/
static int
blockable_page_cache_readahead(struct address_space *mapping, struct file *filp,
- unsigned long offset, unsigned long nr_to_read,
+ pgoff_t offset, unsigned long nr_to_read,
struct file_ra_state *ra, int block)
{
int actual;
@@ -430,14 +430,27 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp,
return ret;
}
-/*
- * page_cache_readahead is the main function. If performs the adaptive
+/**
+ * page_cache_readahead - generic adaptive readahead
+ * @mapping: address_space which holds the pagecache and I/O vectors
+ * @ra: file_ra_state which holds the readahead state
+ * @filp: passed on to ->readpage() and ->readpages()
+ * @offset: start offset into @mapping, in PAGE_CACHE_SIZE units
+ * @req_size: hint: total size of the read which the caller is performing in
+ * PAGE_CACHE_SIZE units
+ *
+ * page_cache_readahead() is the main function. If performs the adaptive
* readahead window size management and submits the readahead I/O.
+ *
+ * Note that @filp is purely used for passing on to the ->readpage[s]()
+ * handler: it may refer to a different file from @mapping (so we may not use
+ * @filp->f_mapping or @filp->f_dentry->d_inode here).
+ * Also, @ra may not be equal to &@filp->f_ra.
+ *
*/
unsigned long
page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
- struct file *filp, unsigned long offset,
- unsigned long req_size)
+ struct file *filp, pgoff_t offset, unsigned long req_size)
{
unsigned long max, newsize;
int sequential;
diff --git a/mm/slab.c b/mm/slab.c
index 22bfb0b2ac8b..e291f5e1afbb 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -368,7 +368,7 @@ static inline void kmem_list3_init(struct kmem_list3 *parent)
* manages a cache.
*/
-struct kmem_cache_s {
+struct kmem_cache {
/* 1) per-cpu data, touched during every alloc/free */
struct array_cache *array[NR_CPUS];
unsigned int batchcount;
@@ -1502,6 +1502,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
{
size_t left_over, slab_size, ralign;
kmem_cache_t *cachep = NULL;
+ struct list_head *p;
/*
* Sanity checks... these are all serious usage bugs.
@@ -1516,6 +1517,35 @@ kmem_cache_create (const char *name, size_t size, size_t align,
BUG();
}
+ down(&cache_chain_sem);
+
+ list_for_each(p, &cache_chain) {
+ kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
+ mm_segment_t old_fs = get_fs();
+ char tmp;
+ int res;
+
+ /*
+ * This happens when the module gets unloaded and doesn't
+ * destroy its slab cache and no-one else reuses the vmalloc
+ * area of the module. Print a warning.
+ */
+ set_fs(KERNEL_DS);
+ res = __get_user(tmp, pc->name);
+ set_fs(old_fs);
+ if (res) {
+ printk("SLAB: cache with size %d has lost its name\n",
+ pc->objsize);
+ continue;
+ }
+
+ if (!strcmp(pc->name,name)) {
+ printk("kmem_cache_create: duplicate cache %s\n", name);
+ dump_stack();
+ goto oops;
+ }
+ }
+
#if DEBUG
WARN_ON(strchr(name, ' ')); /* It confuses parsers */
if ((flags & SLAB_DEBUG_INITIAL) && !ctor) {
@@ -1592,7 +1622,7 @@ kmem_cache_create (const char *name, size_t size, size_t align,
/* Get cache's description obj. */
cachep = (kmem_cache_t *) kmem_cache_alloc(&cache_cache, SLAB_KERNEL);
if (!cachep)
- goto opps;
+ goto oops;
memset(cachep, 0, sizeof(kmem_cache_t));
#if DEBUG
@@ -1686,7 +1716,7 @@ next:
printk("kmem_cache_create: couldn't create cache %s.\n", name);
kmem_cache_free(&cache_cache, cachep);
cachep = NULL;
- goto opps;
+ goto oops;
}
slab_size = ALIGN(cachep->num*sizeof(kmem_bufctl_t)
+ sizeof(struct slab), align);
@@ -1781,43 +1811,14 @@ next:
cachep->limit = BOOT_CPUCACHE_ENTRIES;
}
- /* Need the semaphore to access the chain. */
- down(&cache_chain_sem);
- {
- struct list_head *p;
- mm_segment_t old_fs;
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- list_for_each(p, &cache_chain) {
- kmem_cache_t *pc = list_entry(p, kmem_cache_t, next);
- char tmp;
- /* This happens when the module gets unloaded and doesn't
- destroy its slab cache and noone else reuses the vmalloc
- area of the module. Print a warning. */
- if (__get_user(tmp,pc->name)) {
- printk("SLAB: cache with size %d has lost its name\n",
- pc->objsize);
- continue;
- }
- if (!strcmp(pc->name,name)) {
- printk("kmem_cache_create: duplicate cache %s\n",name);
- up(&cache_chain_sem);
- unlock_cpu_hotplug();
- BUG();
- }
- }
- set_fs(old_fs);
- }
-
/* cache setup completed, link it into the list */
list_add(&cachep->next, &cache_chain);
- up(&cache_chain_sem);
unlock_cpu_hotplug();
-opps:
+oops:
if (!cachep && (flags & SLAB_PANIC))
panic("kmem_cache_create(): failed to create slab `%s'\n",
name);
+ up(&cache_chain_sem);
return cachep;
}
EXPORT_SYMBOL(kmem_cache_create);
@@ -3262,6 +3263,7 @@ static void drain_array_locked(kmem_cache_t *cachep,
/**
* cache_reap - Reclaim memory from caches.
+ * @unused: unused parameter
*
* Called from workqueue/eventd every few seconds.
* Purpose:
@@ -3278,7 +3280,7 @@ static void cache_reap(void *unused)
if (down_trylock(&cache_chain_sem)) {
/* Give up. Setup the next iteration. */
- schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
+ schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
return;
}
@@ -3347,7 +3349,7 @@ next:
up(&cache_chain_sem);
drain_remote_pages();
/* Setup the next iteration */
- schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
+ schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC);
}
#ifdef CONFIG_PROC_FS
diff --git a/mm/swap.c b/mm/swap.c
index 154ae13d8b7e..d09cf7f03e76 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -413,7 +413,6 @@ void vm_acct_memory(long pages)
}
preempt_enable();
}
-EXPORT_SYMBOL(vm_acct_memory);
#ifdef CONFIG_HOTPLUG_CPU
static void lru_drain_cache(unsigned int cpu)
diff --git a/mm/swap_state.c b/mm/swap_state.c
index dfd9a46755b8..0df9a57b1de8 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -40,7 +40,6 @@ struct address_space swapper_space = {
.i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear),
.backing_dev_info = &swap_backing_dev_info,
};
-EXPORT_SYMBOL(swapper_space);
#define INC_CACHE_INFO(x) do { swap_cache_info.x++; } while (0)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 8970c0b74194..edafeace301f 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -36,8 +36,6 @@ unsigned int nr_swapfiles;
long total_swap_pages;
static int swap_overflow;
-EXPORT_SYMBOL(total_swap_pages);
-
static const char Bad_file[] = "Bad swap file entry ";
static const char Unused_file[] = "Unused swap file entry ";
static const char Bad_offset[] = "Bad swap offset entry ";
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 54a90e83cb31..729eb3eec75f 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -457,7 +457,7 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
* @size: allocation size
* @gfp_mask: flags for the page level allocator
* @prot: protection mask for the allocated pages
- * @node node to use for allocation or -1
+ * @node: node to use for allocation or -1
*
* Allocate enough pages to cover @size from the page level
* allocator with @gfp_mask flags. Map them into contiguous
@@ -507,7 +507,7 @@ EXPORT_SYMBOL(vmalloc);
* vmalloc_node - allocate memory on a specific node
*
* @size: allocation size
- * @node; numa node
+ * @node: numa node
*
* Allocate enough pages to cover @size from the page level
* allocator and map them into contiguous kernel virtual space.
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e9bd91265f70..5a220b2bb376 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -313,6 +313,11 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
rqstp->rq_proc = proc = ntohl(svc_getu32(argv)); /* procedure number */
progp = serv->sv_program;
+
+ for (progp = serv->sv_program; progp; progp = progp->pg_next)
+ if (prog == progp->pg_prog)
+ break;
+
/*
* Decode auth data, and add verifier to reply buffer.
* We do this before anything else in order to get a decent
@@ -320,7 +325,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
*/
auth_res = svc_authenticate(rqstp, &auth_stat);
/* Also give the program a chance to reject this call: */
- if (auth_res == SVC_OK) {
+ if (auth_res == SVC_OK && progp) {
auth_stat = rpc_autherr_badcred;
auth_res = progp->pg_authenticate(rqstp);
}
@@ -340,10 +345,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
case SVC_COMPLETE:
goto sendit;
}
-
- for (progp = serv->sv_program; progp; progp = progp->pg_next)
- if (prog == progp->pg_prog)
- break;
+
if (progp == NULL)
goto err_bad_prog;
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 455aeabd95dd..c65c435c4923 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -118,7 +118,7 @@ clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \
# Needed for systems without gettext
KBUILD_HAVE_NLS := $(shell \
- if echo "\#include <libint.h>" | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \
+ if echo "\#include <libintl.h>" | $(HOSTCC) $(HOSTCFLAGS) -E - > /dev/null 2>&1 ; \
then echo yes ; \
else echo no ; fi)
ifeq ($(KBUILD_HAVE_NLS),no)
diff --git a/security/keys/key.c b/security/keys/key.c
index ccde17aff616..01bcfecb7eae 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -115,8 +115,7 @@ struct key_user *key_user_lookup(uid_t uid)
found:
atomic_inc(&user->usage);
spin_unlock(&key_user_lock);
- if (candidate)
- kfree(candidate);
+ kfree(candidate);
out:
return user;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e1cc4dd79012..c7a0ab1cfda3 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -434,8 +434,8 @@ ascend:
if (sp >= KEYRING_SEARCH_MAX_DEPTH)
continue;
- if (!key_task_permission(make_key_ref(key, possessed),
- context, KEY_SEARCH) < 0)
+ if (key_task_permission(make_key_ref(key, possessed),
+ context, KEY_SEARCH) < 0)
continue;
/* stack the current position */
@@ -621,8 +621,8 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
if (strcmp(keyring->description, name) != 0)
continue;
- if (!key_permission(make_key_ref(keyring, 0),
- KEY_SEARCH) < 0)
+ if (key_permission(make_key_ref(keyring, 0),
+ KEY_SEARCH) < 0)
continue;
/* found a potential candidate, but we still need to
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 2f5f539875f2..0ac311dc8371 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -632,22 +632,22 @@ void policydb_destroy(struct policydb *p)
cond_policydb_destroy(p);
for (tr = p->role_tr; tr; tr = tr->next) {
- if (ltr) kfree(ltr);
+ kfree(ltr);
ltr = tr;
}
- if (ltr) kfree(ltr);
+ kfree(ltr);
for (ra = p->role_allow; ra; ra = ra -> next) {
- if (lra) kfree(lra);
+ kfree(lra);
lra = ra;
}
- if (lra) kfree(lra);
+ kfree(lra);
for (rt = p->range_tr; rt; rt = rt -> next) {
- if (lrt) kfree(lrt);
+ kfree(lrt);
lrt = rt;
}
- if (lrt) kfree(lrt);
+ kfree(lrt);
if (p->type_attr_map) {
for (i = 0; i < p->p_types.nprim; i++)
diff --git a/sound/oss/sequencer_syms.c b/sound/oss/sequencer_syms.c
index 45edfd767e4e..5d008798c310 100644
--- a/sound/oss/sequencer_syms.c
+++ b/sound/oss/sequencer_syms.c
@@ -19,7 +19,6 @@ EXPORT_SYMBOL(sequencer_timer);
EXPORT_SYMBOL(sound_timer_init);
EXPORT_SYMBOL(sound_timer_interrupt);
EXPORT_SYMBOL(sound_timer_syncinterval);
-EXPORT_SYMBOL(reprogram_timer);
/* Tuning */